From 12e8894693991807a9f9238ce9c66482ef826dae Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Fri, 13 Dec 2019 09:34:33 -0500 Subject: [PATCH 1/8] Document additional config option --- assets/js/app/Dashboard.js | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/js/app/Dashboard.js b/assets/js/app/Dashboard.js index 60223447..b6f18b40 100644 --- a/assets/js/app/Dashboard.js +++ b/assets/js/app/Dashboard.js @@ -847,6 +847,7 @@ LocusZoom.Dashboard.Components.add('region_scale', function(layout) { * @augments LocusZoom.Dashboard.Component * @param {string} [layout.button_html="Download Image"] * @param {string} [layout.button_title="Download image of the current plot as locuszoom.svg"] + * @param {string} [layout.filename="locuszoom.svg"] The default filename to use when saving the image */ LocusZoom.Dashboard.Components.add('download', function(layout) { LocusZoom.Dashboard.Component.apply(this, arguments); From ad8aa004d985418072279014c5e429f661cee308 Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Mon, 16 Dec 2019 14:51:34 -0500 Subject: [PATCH 2/8] Fix double render bug with panel-level text widgets --- assets/js/app/Dashboard.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/assets/js/app/Dashboard.js b/assets/js/app/Dashboard.js index b6f18b40..71925fa3 100644 --- a/assets/js/app/Dashboard.js +++ b/assets/js/app/Dashboard.js @@ -789,9 +789,11 @@ LocusZoom.Dashboard.Component.Button = function(parent) { LocusZoom.Dashboard.Components.add('title', function(layout) { LocusZoom.Dashboard.Component.apply(this, arguments); this.show = function() { - this.div_selector = this.parent.selector.append('div') - .attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position); - this.title_selector = this.div_selector.append('h3'); + if (!this.div_selector) { + this.div_selector = this.parent.selector.append('div') + .attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position); + this.title_selector = this.div_selector.append('h3'); + } return this.update(); }; this.update = function() { From e9dd63797a67ceb5012f8304b484dbd534bb495f Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Wed, 18 Dec 2019 09:51:03 -0500 Subject: [PATCH 3/8] Less aggressive `engines` for package.json; update tests (yarn is strict about engines flag, so frontend installs failed for people not using node10 LTS on server) --- .travis.yml | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 71c33a04..f21c6dc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: node_js node_js: - "lts/carbon" + - "lts/erbium" cache: yarn: true directories: @@ -15,7 +16,6 @@ branches: - develop notifications: email: - - chriclrk@umich.edu - abought@umich.edu slack: secure: z9tSuzj4LCeJ8SWA0mnOkXPzbufXGlbDOGXSihPAahFVoiTWgL2biA7ZOlZrF3lUBKurJnbP/vOJRAdcA/p+4gymvUXjNJY1uUAxRPo0TVApzhlJAVlYGD/KRoALhbCKMj8Y949esbY1IEKb1/IbfFSCL51wFo2E3G6woSAL3MlH+nDP8WI0LjqjqckrrFgKq8PI5v1b0eSVVK5Guog8+UZYWZhP8A3dvpwBB1cteggby7kmEedQQu4VZ6fh2GbdkZJ4w2IZVFdgTx+nEQuElcnTFvLGiK1U9eR44aLOzJRvnvNxswgiQj2DkEf1Qf2+XvCi9Z4ckozfpqt0fgUIgIOM/7Gi2xmEQVjxTzlQhvhnokX2aT6IRokCS2e0ooHZwtF3bK37OKKrseCxIxYDihJa/Sqh5CkPQAd3J2HnVbGMH/WAaD5zivh213WjhQcZbk6F6UGwAsNO4VP06E1zSzS8E2+hWnKTWbgDHKuFAZvck1P08hQD97gBxA0H2M8PtbSMDuKABemletyvYt/V1yHU1fDSXGQl1gn43OpQPnV4Hc/Potsqc8GKYmqtVJZkmcmjgYHlFzRAhwwS7kjGsWFp8b6ValufvJqmSMVko2aXFiJXw6g+SKqIFUTw5LN8m3vdsofyMLCzXf7HX/sFJbm/IKXS7Kwqc7rPZUN6VR8= diff --git a/package.json b/package.json index 9b0a400d..d30381a7 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ ], "main": "dist/locuszoom.app.min.js", "engines": { - "node": ">=10.17.0" + "node": ">=8.9.0" }, "repository": { "type": "git", From 131f8395f7113b3793d6bb0c70a1c422e44193dd Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Tue, 14 Jan 2020 13:57:11 -0500 Subject: [PATCH 4/8] Restore constraint table using gnomAD, and update sample data It's unusual to replace a source (instead of deprecating), but the server it is designed to target does not exist and custom user-provided data is very rare --- assets/js/app/Data.js | 74 +++++++------ assets/js/app/Layouts.js | 15 ++- index.html | 6 +- .../constraint_10_114550452-115067678.json | 102 ++++++++++-------- 4 files changed, 113 insertions(+), 84 deletions(-) diff --git a/assets/js/app/Data.js b/assets/js/app/Data.js index 98ef42bc..c044c7b2 100644 --- a/assets/js/app/Data.js +++ b/assets/js/app/Data.js @@ -1035,17 +1035,16 @@ LocusZoom.Data.GeneSource.prototype.normalizeResponse = function (data) { return LocusZoom.Data.GeneSource.prototype.extractFields = function (data, fields, outnames, trans) { return data; }; /** - * Data Source for Gene Constraint Data, as fetched from the ExAC server (or compatible) + * Data Source for Gene Constraint Data, as fetched from the gnomAD server (or compatible) * - * FIXME: The ExAc server has been decommissioned. This source is kept here to avoid breaking existing layouts; we may - * be able to restore this feature in the future once the gnomAD API is further developed + * In the past, this source used ExAC, which has been completely decommissioned. Since the old source referenced a + * server that no longer exists, this was redefined in 0.11.0 in a backwards-incompatible manner. * * @public * @class * @augments LocusZoom.Data.Source */ LocusZoom.Data.GeneConstraintSource = LocusZoom.Data.Source.extend(function(init) { - console.warn('The gene constraint source depends on a server (ExAC) that is no longer active. This information may not be displayed.'); this.parseInit(init); }, 'GeneConstraintLZ'); @@ -1060,19 +1059,29 @@ LocusZoom.Data.GeneConstraintSource.prototype.getCacheKey = function(state, chai }; LocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function(state, chain, fields) { - var geneids = []; - chain.body.forEach(function(gene) { - var gene_id = gene.gene_id; - if (gene_id.indexOf('.')) { - gene_id = gene_id.substr(0, gene_id.indexOf('.')); - } - geneids.push(gene_id); + var build = state.genome_build || this.params.build; + if (!build) { + throw new Error(['Data source', this.constructor.SOURCE_NAME, 'requires that you specify a genome_build'].join(' ')); + } + + var query = chain.body.map(function (gene) { + var gene_name = gene.gene_name; + // GraphQL alias names must match a specific set of allowed characters: https://stackoverflow.com/a/45757065/1422268 + var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_'); + // Each gene is a separate graphQL query, grouped into one request using aliases + return alias + ': gene(gene_symbol: "' + gene_name + '", reference_genome: ' + build + ') { gnomad_constraint { exp_syn obs_syn syn_z exp_mis obs_mis mis_z exp_lof obs_lof pLI } } '; }); + + if (!query.length) { + // If there are no genes, skip the network request + return Promise.resolve({ data: null }); + } + + query = '{' + query.join(' ') + ' }'; // GraphQL isn't quite JSON; items are separated by spaces but not commas var url = this.getURL(state, chain, fields); - var body = 'geneids=' + encodeURIComponent(JSON.stringify(geneids)); - var headers = { - 'Content-Type': 'application/x-www-form-urlencoded' - }; + // See: https://graphql.org/learn/serving-over-http/ + var body = JSON.stringify({ query: query }); + var headers = { 'Content-Type': 'application/json' }; return LocusZoom.createCORSPromise('POST', url, body, headers); }; @@ -1080,26 +1089,23 @@ LocusZoom.Data.GeneConstraintSource.prototype.combineChainBody = function (data, if (!data) { return chain; } - var constraint_fields = ['bp', 'exp_lof', 'exp_mis', 'exp_syn', 'lof_z', 'mis_z', 'mu_lof', 'mu_mis','mu_syn', 'n_exons', 'n_lof', 'n_mis', 'n_syn', 'pLI', 'syn_z']; - chain.body.forEach(function(gene, i) { - var gene_id = gene.gene_id; - if (gene_id.indexOf('.')) { - gene_id = gene_id.substr(0, gene_id.indexOf('.')); - } - constraint_fields.forEach(function(field) { - // Do not overwrite any fields defined in the original gene source - if (typeof chain.body[i][field] != 'undefined') { return; } - if (data[gene_id]) { - var val = data[gene_id][field]; - if (typeof val == 'number' && val.toString().indexOf('.') !== -1) { - val = parseFloat(val.toFixed(2)); + + chain.body.forEach(function(gene) { + // Find payload keys that match gene names in this response + var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_'); // aliases are modified gene names + var constraint = data[alias] && data[alias]['gnomad_constraint']; // gnomad API has two ways of specifying missing data for a requested gene + if (constraint) { + // Add all fields from constraint data- do not override fields present in the gene source + Object.keys(constraint).forEach(function (key) { + var val = constraint[key]; + if (typeof gene[key] === 'undefined') { + if (typeof val == 'number' && val.toString().indexOf('.') !== -1) { + val = parseFloat(val.toFixed(2)); + } + gene[key] = val; // These two sources are both designed to bypass namespacing } - chain.body[i][field] = val; - } else { - // If the gene did not come back in the response then set the same field with a null values - chain.body[i][field] = null; - } - }); + }); + } }); return chain.body; }; diff --git a/assets/js/app/Layouts.js b/assets/js/app/Layouts.js index 4fff5444..f9852dea 100644 --- a/assets/js/app/Layouts.js +++ b/assets/js/app/Layouts.js @@ -229,8 +229,15 @@ LocusZoom.Layouts.add('tooltip', 'standard_genes', { show: { or: ['highlighted', 'selected'] }, hide: { and: ['unhighlighted', 'unselected'] }, html: '

{{gene_name|htmlescape}}

' - + 'Gene ID: {{gene_id|htmlescape}}
' - + 'Transcript ID: {{transcript_id|htmlescape}}
' + + '
Gene ID: {{gene_id|htmlescape}}
' + + '
Transcript ID: {{transcript_id|htmlescape}}
' + + '
' + + '' + + '' + + '' + + '' + + '' + + '
ConstraintExpected variantsObserved variantsConst. Metric
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
LoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
' + 'More data on gnomAD' }); @@ -463,10 +470,10 @@ LocusZoom.Layouts.add('data_layer', 'phewas_pvalues', { }); LocusZoom.Layouts.add('data_layer', 'genes', { - namespace: { 'gene': 'gene' }, + namespace: { 'gene': 'gene', 'constraint': 'constraint' }, id: 'genes', type: 'genes', - fields: ['{{namespace[gene]}}all'], + fields: ['{{namespace[gene]}}all', '{{namespace[constraint]}}all'], id_field: 'gene_id', behaviors: { onmouseover: [ diff --git a/index.html b/index.html index 642e9416..94558bf7 100644 --- a/index.html +++ b/index.html @@ -211,14 +211,16 @@
Multiple Phenotypes (Layered)
.add("assoc", ["AssociationLZ", {url: apiBase + "statistic/single/", params: { source: 45, id_field: "variant" }}]) .add("ld", ["LDLZ2", { url: "https://portaldev.sph.umich.edu/ld/", params: { source: '1000G', build: 'GRCh37', population: 'ALL' } }]) .add("gene", ["GeneLZ", { url: apiBase + "annotation/genes/", params: { build: 'GRCh37' } }]) - .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/", params: { build: 'GRCh37' } }]); + .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/", params: { build: 'GRCh37' } }]) + .add("constraint", ["GeneConstraintLZ", { url: "https://gnomad.broadinstitute.org/api", params: { build: 'GRCh37' } }]); } else { apiBase = window.location.origin + window.location.pathname.substr(0, window.location.pathname.lastIndexOf("/") + 1) + "staticdata/"; data_sources = new LocusZoom.DataSources() .add("assoc", ["AssociationLZ", {url: apiBase + "assoc_10_114550452-115067678.json?", params: { source: 45, id_field: "variant" }}]) .add("ld", ["LDLZ", { url: apiBase + "ld_10_114550452-115067678.json?" }]) .add("gene", ["GeneLZ", { url: apiBase + "genes_10_114550452-115067678.json?", params: { build: 'GRCh37' } }]) - .add("recomb", ["RecombLZ", { url: apiBase + "recomb_10_114550452-115067678.json?", params: { build: 'GRCh37' } }]); + .add("recomb", ["RecombLZ", { url: apiBase + "recomb_10_114550452-115067678.json?", params: { build: 'GRCh37' } }]) + .add("constraint", ["GeneConstraintLZ", { url: apiBase + "constraint_10_114550452-115067678.json?", params: { build: 'GRCh37' } }]); } // Get the standard association plot layout from LocusZoom's built-in layouts diff --git a/staticdata/constraint_10_114550452-115067678.json b/staticdata/constraint_10_114550452-115067678.json index 08f88b1e..0dd0f22e 100644 --- a/staticdata/constraint_10_114550452-115067678.json +++ b/staticdata/constraint_10_114550452-115067678.json @@ -1,46 +1,60 @@ { - "ENSG00000148737": { - "bp": 1809.0, - "exp_lof": 26.6820162112, - "exp_mis": 241.265237982, - "exp_syn": 144.572146929, - "lof_z": 4.54149691871399, - "mis_z": 3.06285628978657, - "mu_lof": 2.11056303577e-06, - "mu_mis": 2.26963069583e-05, - "mu_syn": 1.33820470884e-05, - "n_exons": 14.0, - "n_lof": 3.0, - "n_mis": 144.0, - "n_syn": 148.0, - "pLI": 0.98960502908944, - "syn_z": -0.176740203662137, - "transcript": "ENST00000543371", - "tx_end": 114925731.0, - "tx_start": 114710515.0 - }, - "ENSG00000151532": { - "bp": 654.0, - "exp_lof": 13.572671789, - "exp_mis": 84.1884336039, - "exp_syn": 37.5932161446, - "lof_z": 2.84277031197829, - "mis_z": 0.0100447769411539, - "mu_lof": 1.01189147728e-06, - "mu_mis": 7.65962683037e-06, - "mu_syn": 3.27657476692e-06, - "n_exons": 8.0, - "n_lof": 3.0, - "n_mis": 84.0, - "n_syn": 19.0, - "pLI": 0.413424037513717, - "syn_z": 1.87996297825622, - "transcript": "ENST00000393077", - "tx_end": 114575142.0, - "tx_start": 114207131.0 - }, - "ENSG00000225292": null, - "ENSG00000227560": null, - "ENSG00000233547": null, - "ENSG00000260917": null + "errors": [ + { + "message": "Gene not found" + }, + { + "message": "Constraint not found for transcript ENST00000428766" + }, + { + "message": "Constraint not found for transcript ENST00000369391" + }, + { + "message": "Constraint not found for transcript ENST00000564352" + }, + { + "message": "Constraint not found for transcript ENST00000420976" + } + ], + "data": { + "VTI1A": { + "gnomad_constraint": { + "exp_syn": 45.96999843014132, + "obs_syn": 39, + "syn_z": 0.8080936395821224, + "exp_mis": 129.1265254408911, + "obs_mis": 124, + "mis_z": 0.16031755135682893, + "exp_lof": 16.78485712967592, + "obs_lof": 8, + "pLI": 0.0005417333080260623 + } + }, + "AL158212_3": { + "gnomad_constraint": null + }, + "AL158212_4": null, + "AL158212_1": { + "gnomad_constraint": null + }, + "TCF7L2": { + "gnomad_constraint": { + "exp_syn": 168.21182745386096, + "obs_syn": 203, + "syn_z": -2.1084805717361723, + "exp_mis": 354.04931087054916, + "obs_mis": 227, + "mis_z": 2.399419166103715, + "exp_lof": 33.549020888679706, + "obs_lof": 4, + "pLI": 0.9953718384354076 + } + }, + "AL158212_2": { + "gnomad_constraint": null + }, + "RPS15AP30": { + "gnomad_constraint": null + } + } } From c256e7142cac363dff1e4bf1172d0292adc2fc01 Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Tue, 14 Jan 2020 15:56:04 -0500 Subject: [PATCH 5/8] Update fields in constraint table to use latest gnomAD metrics --- assets/js/app/Data.js | 2 +- assets/js/app/Layouts.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/js/app/Data.js b/assets/js/app/Data.js index c044c7b2..2299fd89 100644 --- a/assets/js/app/Data.js +++ b/assets/js/app/Data.js @@ -1069,7 +1069,7 @@ LocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function(state, cha // GraphQL alias names must match a specific set of allowed characters: https://stackoverflow.com/a/45757065/1422268 var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_'); // Each gene is a separate graphQL query, grouped into one request using aliases - return alias + ': gene(gene_symbol: "' + gene_name + '", reference_genome: ' + build + ') { gnomad_constraint { exp_syn obs_syn syn_z exp_mis obs_mis mis_z exp_lof obs_lof pLI } } '; + return alias + ': gene(gene_symbol: "' + gene_name + '", reference_genome: ' + build + ') { gnomad_constraint { exp_syn obs_syn syn_z oe_syn oe_syn_lower oe_syn_upper exp_mis obs_mis mis_z oe_mis oe_mis_lower oe_mis_upper exp_lof obs_lof pLI oe_lof oe_lof_lower oe_lof_upper } } '; }); if (!query.length) { diff --git a/assets/js/app/Layouts.js b/assets/js/app/Layouts.js index f9852dea..baece44f 100644 --- a/assets/js/app/Layouts.js +++ b/assets/js/app/Layouts.js @@ -234,9 +234,9 @@ LocusZoom.Layouts.add('tooltip', 'standard_genes', { + '
' + '' + '' - + '' - + '' - + '' + + '' + + '' + + '' + '
ConstraintExpected variantsObserved variantsConst. Metric
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
LoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
o/e = {{oe_syn}} ({{oe_syn_lower}} - {{oe_syn_upper}})
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
o/e = {{oe_mis}} ({{oe_mis_lower}} - {{oe_mis_upper}})
pLoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
o/e = {{oe_lof}} ({{oe_lof_lower}} - {{oe_lof_upper}})
' + 'More data on gnomAD' }); From e9fb018f58c93340dc66729e6a6ddadbe4f194f8 Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Tue, 14 Jan 2020 16:13:00 -0500 Subject: [PATCH 6/8] Hide constraint table if no data for that gene --- assets/js/app/Layouts.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/assets/js/app/Layouts.js b/assets/js/app/Layouts.js index baece44f..9b8b7949 100644 --- a/assets/js/app/Layouts.js +++ b/assets/js/app/Layouts.js @@ -229,15 +229,14 @@ LocusZoom.Layouts.add('tooltip', 'standard_genes', { show: { or: ['highlighted', 'selected'] }, hide: { and: ['unhighlighted', 'unselected'] }, html: '

{{gene_name|htmlescape}}

' - + '' - + '
Transcript ID: {{transcript_id|htmlescape}}
' - + '
' - + '' + + 'Gene ID: {{gene_id|htmlescape}}
' + + 'Transcript ID: {{transcript_id|htmlescape}}
' + + '{{#if pLI}}
' + '' + '' + '' + '' - + '
ConstraintExpected variantsObserved variantsConst. Metric
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
o/e = {{oe_syn}} ({{oe_syn_lower}} - {{oe_syn_upper}})
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
o/e = {{oe_mis}} ({{oe_mis_lower}} - {{oe_mis_upper}})
pLoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
o/e = {{oe_lof}} ({{oe_lof_lower}} - {{oe_lof_upper}})
' + + '
{{/if}}' + 'More data on gnomAD' }); From 833b91d4d0444a813412035baf516b69a841bf53 Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Wed, 15 Jan 2020 11:12:06 -0500 Subject: [PATCH 7/8] Add constraint usage back to all demos --- docs/simplest_template.html | 3 +- examples/covariates_model.html | 3 +- examples/credible_sets.html | 3 +- examples/gwas_catalog.html | 3 +- examples/interval_annotations.html | 3 +- examples/js/aggregation-tests-example-page.js | 3 +- examples/multiple_phenotypes_layered.html | 3 +- examples/phewas_scatter.html | 4 +- .../constraint_10_114550452-115067678.json | 28 +++++-- ...ne_constraints_10_114508349-115008349.json | 78 +++++++++++++++++++ 10 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 staticdata/gene_constraints_10_114508349-115008349.json diff --git a/docs/simplest_template.html b/docs/simplest_template.html index 205efc6b..44e83ac1 100644 --- a/docs/simplest_template.html +++ b/docs/simplest_template.html @@ -30,7 +30,8 @@ .add("assoc", ["AssociationLZ", {url: apiBase + "statistic/single/", params: { source: 45, id_field: "variant" }}]) .add("ld", ["LDLZ2", { url: "https://portaldev.sph.umich.edu/ld/" }]) .add("gene", ["GeneLZ", { url: apiBase + "annotation/genes/" }]) - .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/" }]); + .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/" }]) + .add("constraint", ["GeneConstraintLZ", { url: "https://gnomad.broadinstitute.org/api", params: { build: 'GRCh37' } }]); // Second, specify what kind of information to display. This demo uses a pre-defined set of panels with common // display options, and tells all annotation tracks to auto-select data for a specific build diff --git a/examples/covariates_model.html b/examples/covariates_model.html index 7335e8c7..47cb5e29 100644 --- a/examples/covariates_model.html +++ b/examples/covariates_model.html @@ -67,7 +67,8 @@

Top Hits

.add("assoc", ["AssociationLZ", {url: apiBase + "statistic/single/", params: { source: 45, id_field: "variant" }}]) .add("ld", ["LDLZ2", { url: "https://portaldev.sph.umich.edu/ld/", params: { source: '1000G', build: 'GRCh37', population: 'ALL' } }]) .add("gene", ["GeneLZ", { url: apiBase + "annotation/genes/", params: { build: 'GRCh37' } }]) - .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/", params: { build: 'GRCh37' } }]); + .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/", params: { build: 'GRCh37' } }]) + .add("constraint", ["GeneConstraintLZ", { url: "https://gnomad.broadinstitute.org/api", params: { build: 'GRCh37' } }]); // Get the standard assocation plot layout from LocusZoom's built-in layouts var mods = { diff --git a/examples/credible_sets.html b/examples/credible_sets.html index cf7150df..663fd087 100644 --- a/examples/credible_sets.html +++ b/examples/credible_sets.html @@ -94,7 +94,8 @@

Top Hits

.add("credset", ["CredibleSetLZ", { params: { fields: { log_pvalue: 'assoc:log_pvalue' }, threshold: 0.95 } }]) .add("ld", ["LDLZ2", { url: "https://portaldev.sph.umich.edu/ld/", params: { source: '1000G', build: 'GRCh37', population: 'ALL' } }]) .add("gene", ["GeneLZ", {url: apiBase + "annotation/genes/", params: { build: 'GRCh37' }}]) - .add("recomb", ["RecombLZ", {url: apiBase + "annotation/recomb/results/", params: { build: 'GRCh37' }}]); + .add("recomb", ["RecombLZ", {url: apiBase + "annotation/recomb/results/", params: { build: 'GRCh37' }}]) + .add("constraint", ["GeneConstraintLZ", { url: "https://gnomad.broadinstitute.org/api", params: { build: 'GRCh37' } }]); /* Define and render the plot diff --git a/examples/gwas_catalog.html b/examples/gwas_catalog.html index 621e4075..a87ca227 100644 --- a/examples/gwas_catalog.html +++ b/examples/gwas_catalog.html @@ -89,7 +89,8 @@

Top Hits

.add("ld", ["LDLZ2", { url: "https://portaldev.sph.umich.edu/ld/", params: { source: '1000G', population: 'ALL' } }]) .add("gene", ["GeneLZ", { url: apiBase + "annotation/genes/" }]) .add("catalog", ["GwasCatalogLZ", { url: apiBase + 'annotation/gwascatalog/results/' }]) - .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/" }]); + .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/" }]) + .add("constraint", ["GeneConstraintLZ", { url: "https://gnomad.broadinstitute.org/api", params: { build: 'GRCh37' } }]); /* Define and render the plot diff --git a/examples/interval_annotations.html b/examples/interval_annotations.html index aeea680b..227a73d5 100644 --- a/examples/interval_annotations.html +++ b/examples/interval_annotations.html @@ -67,7 +67,8 @@

Top Hits

.add("ld", ["LDLZ2", { url: "https://portaldev.sph.umich.edu/ld/", params: { source: '1000G', build: 'GRCh37', population: 'ALL' } }]) .add("gene", ["GeneLZ", { url: apiBase + "annotation/genes/", params: { build: 'GRCh37' } }]) .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/", params: { build: 'GRCh37' } }]) - .add("intervals", ["IntervalLZ", { url: apiBase + "annotation/intervals/results/", params: {source: 19} }]); + .add("intervals", ["IntervalLZ", { url: apiBase + "annotation/intervals/results/", params: {source: 19} }]) + .add("constraint", ["GeneConstraintLZ", { url: "https://gnomad.broadinstitute.org/api", params: { build: 'GRCh37' } }]); // Get the standard assocation plot layout from LocusZoom's built-in layouts var mods = { diff --git a/examples/js/aggregation-tests-example-page.js b/examples/js/aggregation-tests-example-page.js index e90fb1ae..aa5d21a5 100644 --- a/examples/js/aggregation-tests-example-page.js +++ b/examples/js/aggregation-tests-example-page.js @@ -205,7 +205,8 @@ function createDisplayWidgets(label_store, context) { gene_ns: 'gene' } }]) - .add('recomb', ['RecombLZ', { url: apiBase + 'annotation/recomb/results/', params: { build: 'GRCh37' } }]); + .add('recomb', ['RecombLZ', { url: apiBase + 'annotation/recomb/results/', params: { build: 'GRCh37' } }]) + .add('constraint', ['GeneConstraintLZ', { url: 'https://gnomad.broadinstitute.org/api', params: { build: 'GRCh37' } }]); var stateUrlMapping = {chr: 'chrom', start: 'start', end: 'end'}; var initialState = LocusZoom.ext.DynamicUrls.paramsFromUrl(stateUrlMapping); diff --git a/examples/multiple_phenotypes_layered.html b/examples/multiple_phenotypes_layered.html index 37034964..891a770c 100644 --- a/examples/multiple_phenotypes_layered.html +++ b/examples/multiple_phenotypes_layered.html @@ -67,7 +67,8 @@

Top Hits

var apiBase = "https://portaldev.sph.umich.edu/api/v1/"; var data_sources = new LocusZoom.DataSources() .add("recomb", ["RecombLZ", { url: apiBase + "annotation/recomb/results/", params: { build: 'GRCh37' } }]) - .add("gene", ["GeneLZ", { url: apiBase + "annotation/genes/", params: { build: 'GRCh37' } }]); + .add("gene", ["GeneLZ", { url: apiBase + "annotation/genes/", params: { build: 'GRCh37' } }]) + .add("constraint", ["GeneConstraintLZ", { url: "https://gnomad.broadinstitute.org/api", params: { build: 'GRCh37' } }]); // Build the base layout var association_panel_mods = { diff --git a/examples/phewas_scatter.html b/examples/phewas_scatter.html index 5b5e9b85..fcf20b6b 100644 --- a/examples/phewas_scatter.html +++ b/examples/phewas_scatter.html @@ -225,6 +225,7 @@

API (for developers)

params: { build: ["GRCh37"] } }]) .add("gene", ["GeneLZ", { url: apiBase + "annotation/genes/", params: { build: 'GRCh37' } }]) + .add("constraint", ["GeneConstraintLZ", { url: "https://gnomad.broadinstitute.org/api", params: { build: 'GRCh37' } }]); } else { apiBase = window.location.origin + window.location.pathname.substr(0, window.location.pathname.lastIndexOf("/") + 1) + "../staticdata/"; dataSources @@ -232,7 +233,8 @@

API (for developers)

url: apiBase + "phewas_" + String(variantChrom) + "_" + String(variantPosition) + "_C-T.json", params: { build: ["GRCh37"] } }]) - .add("gene", ["GeneLZ", { url: apiBase + "genes_10_114508349-115008349.json", params: { build: 'GRCh37' } }]); + .add("gene", ["GeneLZ", { url: apiBase + "genes_10_114508349-115008349.json", params: { build: 'GRCh37' } }]) + .add("constraint", ["GeneConstraintLZ", { url: apiBase + "gene_constraints_10_114508349-115008349.json", params: { build: 'GRCh37' } }]); } // Static blobs (independent of host) dataSources diff --git a/staticdata/constraint_10_114550452-115067678.json b/staticdata/constraint_10_114550452-115067678.json index 0dd0f22e..97a19183 100644 --- a/staticdata/constraint_10_114550452-115067678.json +++ b/staticdata/constraint_10_114550452-115067678.json @@ -4,13 +4,13 @@ "message": "Gene not found" }, { - "message": "Constraint not found for transcript ENST00000428766" + "message": "Constraint not found for transcript ENST00000564352" }, { - "message": "Constraint not found for transcript ENST00000369391" + "message": "Constraint not found for transcript ENST00000428766" }, { - "message": "Constraint not found for transcript ENST00000564352" + "message": "Constraint not found for transcript ENST00000369391" }, { "message": "Constraint not found for transcript ENST00000420976" @@ -22,12 +22,21 @@ "exp_syn": 45.96999843014132, "obs_syn": 39, "syn_z": 0.8080936395821224, + "oe_syn": 0.8483794068269693, + "oe_syn_lower": 0.656, + "oe_syn_upper": 1.108, "exp_mis": 129.1265254408911, "obs_mis": 124, "mis_z": 0.16031755135682893, + "oe_mis": 0.9602984326931508, + "oe_mis_lower": 0.829, + "oe_mis_upper": 1.115, "exp_lof": 16.78485712967592, "obs_lof": 8, - "pLI": 0.0005417333080260623 + "pLI": 0.0005417333080260623, + "oe_lof": 0.4766200831019205, + "oe_lof_lower": 0.279, + "oe_lof_upper": 0.86 } }, "AL158212_3": { @@ -42,12 +51,21 @@ "exp_syn": 168.21182745386096, "obs_syn": 203, "syn_z": -2.1084805717361723, + "oe_syn": 1.2068116913816962, + "oe_syn_lower": 1.076, + "oe_syn_upper": 1.356, "exp_mis": 354.04931087054916, "obs_mis": 227, "mis_z": 2.399419166103715, + "oe_mis": 0.6411536275606475, + "oe_mis_lower": 0.574, + "oe_mis_upper": 0.716, "exp_lof": 33.549020888679706, "obs_lof": 4, - "pLI": 0.9953718384354076 + "pLI": 0.9953718384354076, + "oe_lof": 0.1192285167806403, + "oe_lof_lower": 0.058, + "oe_lof_upper": 0.273 } }, "AL158212_2": { diff --git a/staticdata/gene_constraints_10_114508349-115008349.json b/staticdata/gene_constraints_10_114508349-115008349.json new file mode 100644 index 00000000..97a19183 --- /dev/null +++ b/staticdata/gene_constraints_10_114508349-115008349.json @@ -0,0 +1,78 @@ +{ + "errors": [ + { + "message": "Gene not found" + }, + { + "message": "Constraint not found for transcript ENST00000564352" + }, + { + "message": "Constraint not found for transcript ENST00000428766" + }, + { + "message": "Constraint not found for transcript ENST00000369391" + }, + { + "message": "Constraint not found for transcript ENST00000420976" + } + ], + "data": { + "VTI1A": { + "gnomad_constraint": { + "exp_syn": 45.96999843014132, + "obs_syn": 39, + "syn_z": 0.8080936395821224, + "oe_syn": 0.8483794068269693, + "oe_syn_lower": 0.656, + "oe_syn_upper": 1.108, + "exp_mis": 129.1265254408911, + "obs_mis": 124, + "mis_z": 0.16031755135682893, + "oe_mis": 0.9602984326931508, + "oe_mis_lower": 0.829, + "oe_mis_upper": 1.115, + "exp_lof": 16.78485712967592, + "obs_lof": 8, + "pLI": 0.0005417333080260623, + "oe_lof": 0.4766200831019205, + "oe_lof_lower": 0.279, + "oe_lof_upper": 0.86 + } + }, + "AL158212_3": { + "gnomad_constraint": null + }, + "AL158212_4": null, + "AL158212_1": { + "gnomad_constraint": null + }, + "TCF7L2": { + "gnomad_constraint": { + "exp_syn": 168.21182745386096, + "obs_syn": 203, + "syn_z": -2.1084805717361723, + "oe_syn": 1.2068116913816962, + "oe_syn_lower": 1.076, + "oe_syn_upper": 1.356, + "exp_mis": 354.04931087054916, + "obs_mis": 227, + "mis_z": 2.399419166103715, + "oe_mis": 0.6411536275606475, + "oe_mis_lower": 0.574, + "oe_mis_upper": 0.716, + "exp_lof": 33.549020888679706, + "obs_lof": 4, + "pLI": 0.9953718384354076, + "oe_lof": 0.1192285167806403, + "oe_lof_lower": 0.058, + "oe_lof_upper": 0.273 + } + }, + "AL158212_2": { + "gnomad_constraint": null + }, + "RPS15AP30": { + "gnomad_constraint": null + } + } +} From c8f6b20cf13cf06ceed934ea37e9ee4bb1c6247b Mon Sep 17 00:00:00 2001 From: Andy Boughton Date: Wed, 15 Jan 2020 11:41:03 -0500 Subject: [PATCH 8/8] Bump version for 0.10.1 --- assets/js/app/LocusZoom.js | 2 +- dist/locuszoom.app.js | 114 +++++++++++++++++----------------- dist/locuszoom.app.js.map | 2 +- dist/locuszoom.app.min.js | 2 +- dist/locuszoom.app.min.js.map | 2 +- index.html | 6 +- package-lock.json | 2 +- package.json | 2 +- 8 files changed, 67 insertions(+), 65 deletions(-) diff --git a/assets/js/app/LocusZoom.js b/assets/js/app/LocusZoom.js index 6602f5d2..73343651 100644 --- a/assets/js/app/LocusZoom.js +++ b/assets/js/app/LocusZoom.js @@ -2,7 +2,7 @@ * @namespace */ var LocusZoom = { - version: '0.10.0' + version: '0.10.1' }; /** diff --git a/dist/locuszoom.app.js b/dist/locuszoom.app.js index 2db9bf9e..44242eba 100644 --- a/dist/locuszoom.app.js +++ b/dist/locuszoom.app.js @@ -39,7 +39,7 @@ } // ESTemplate: module content goes here // ESTemplate: module content goes here ; - var LocusZoom = { version: '0.10.0' }; + var LocusZoom = { version: '0.10.1' }; /** * Populate a single element with a LocusZoom plot. * selector can be a string for a DOM Query or a d3 selector. @@ -1024,7 +1024,7 @@ 'unselected' ] }, - html: '

{{gene_name|htmlescape}}

' + 'Gene ID: {{gene_id|htmlescape}}
' + 'Transcript ID: {{transcript_id|htmlescape}}
' + 'More data on gnomAD' + html: '

{{gene_name|htmlescape}}

' + 'Gene ID: {{gene_id|htmlescape}}
' + 'Transcript ID: {{transcript_id|htmlescape}}
' + '{{#if pLI}}' + '' + '' + '' + '' + '
ConstraintExpected variantsObserved variantsConst. Metric
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
o/e = {{oe_syn}} ({{oe_syn_lower}} - {{oe_syn_upper}})
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
o/e = {{oe_mis}} ({{oe_mis_lower}} - {{oe_mis_upper}})
pLoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
o/e = {{oe_lof}} ({{oe_lof_lower}} - {{oe_lof_upper}})

{{/if}}' + 'More data on gnomAD' }); LocusZoom.Layouts.add('tooltip', 'standard_intervals', { namespace: { 'intervals': 'intervals' }, @@ -1357,10 +1357,16 @@ } }); LocusZoom.Layouts.add('data_layer', 'genes', { - namespace: { 'gene': 'gene' }, + namespace: { + 'gene': 'gene', + 'constraint': 'constraint' + }, id: 'genes', type: 'genes', - fields: ['{{namespace[gene]}}all'], + fields: [ + '{{namespace[gene]}}all', + '{{namespace[constraint]}}all' + ], id_field: 'gene_id', behaviors: { onmouseover: [{ @@ -7348,8 +7354,10 @@ LocusZoom.Dashboard.Components.add('title', function (layout) { LocusZoom.Dashboard.Component.apply(this, arguments); this.show = function () { - this.div_selector = this.parent.selector.append('div').attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position); - this.title_selector = this.div_selector.append('h3'); + if (!this.div_selector) { + this.div_selector = this.parent.selector.append('div').attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position); + this.title_selector = this.div_selector.append('h3'); + } return this.update(); }; this.update = function () { @@ -7411,6 +7419,7 @@ * @augments LocusZoom.Dashboard.Component * @param {string} [layout.button_html="Download Image"] * @param {string} [layout.button_title="Download image of the current plot as locuszoom.svg"] + * @param {string} [layout.filename="locuszoom.svg"] The default filename to use when saving the image */ LocusZoom.Dashboard.Components.add('download', function (layout) { LocusZoom.Dashboard.Component.apply(this, arguments); @@ -9337,17 +9346,16 @@ return data; }; /** - * Data Source for Gene Constraint Data, as fetched from the ExAC server (or compatible) + * Data Source for Gene Constraint Data, as fetched from the gnomAD server (or compatible) * - * FIXME: The ExAc server has been decommissioned. This source is kept here to avoid breaking existing layouts; we may - * be able to restore this feature in the future once the gnomAD API is further developed + * In the past, this source used ExAC, which has been completely decommissioned. Since the old source referenced a + * server that no longer exists, this was redefined in 0.11.0 in a backwards-incompatible manner. * * @public * @class * @augments LocusZoom.Data.Source */ LocusZoom.Data.GeneConstraintSource = LocusZoom.Data.Source.extend(function (init) { - console.warn('The gene constraint source depends on a server (ExAC) that is no longer active. This information may not be displayed.'); this.parseInit(init); }, 'GeneConstraintLZ'); LocusZoom.Data.GeneConstraintSource.prototype.getURL = function () { @@ -9360,61 +9368,55 @@ return this.url + JSON.stringify(state); }; LocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function (state, chain, fields) { - var geneids = []; - chain.body.forEach(function (gene) { - var gene_id = gene.gene_id; - if (gene_id.indexOf('.')) { - gene_id = gene_id.substr(0, gene_id.indexOf('.')); - } - geneids.push(gene_id); + var build = state.genome_build || this.params.build; + if (!build) { + throw new Error([ + 'Data source', + this.constructor.SOURCE_NAME, + 'requires that you specify a genome_build' + ].join(' ')); + } + var query = chain.body.map(function (gene) { + var gene_name = gene.gene_name; + // GraphQL alias names must match a specific set of allowed characters: https://stackoverflow.com/a/45757065/1422268 + var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_'); + // Each gene is a separate graphQL query, grouped into one request using aliases + return alias + ': gene(gene_symbol: "' + gene_name + '", reference_genome: ' + build + ') { gnomad_constraint { exp_syn obs_syn syn_z oe_syn oe_syn_lower oe_syn_upper exp_mis obs_mis mis_z oe_mis oe_mis_lower oe_mis_upper exp_lof obs_lof pLI oe_lof oe_lof_lower oe_lof_upper } } '; }); + if (!query.length) { + // If there are no genes, skip the network request + return Promise.resolve({ data: null }); + } + query = '{' + query.join(' ') + ' }'; + // GraphQL isn't quite JSON; items are separated by spaces but not commas var url = this.getURL(state, chain, fields); - var body = 'geneids=' + encodeURIComponent(JSON.stringify(geneids)); - var headers = { 'Content-Type': 'application/x-www-form-urlencoded' }; + // See: https://graphql.org/learn/serving-over-http/ + var body = JSON.stringify({ query: query }); + var headers = { 'Content-Type': 'application/json' }; return LocusZoom.createCORSPromise('POST', url, body, headers); }; LocusZoom.Data.GeneConstraintSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) { if (!data) { return chain; } - var constraint_fields = [ - 'bp', - 'exp_lof', - 'exp_mis', - 'exp_syn', - 'lof_z', - 'mis_z', - 'mu_lof', - 'mu_mis', - 'mu_syn', - 'n_exons', - 'n_lof', - 'n_mis', - 'n_syn', - 'pLI', - 'syn_z' - ]; - chain.body.forEach(function (gene, i) { - var gene_id = gene.gene_id; - if (gene_id.indexOf('.')) { - gene_id = gene_id.substr(0, gene_id.indexOf('.')); - } - constraint_fields.forEach(function (field) { - // Do not overwrite any fields defined in the original gene source - if (typeof chain.body[i][field] != 'undefined') { - return; - } - if (data[gene_id]) { - var val = data[gene_id][field]; - if (typeof val == 'number' && val.toString().indexOf('.') !== -1) { - val = parseFloat(val.toFixed(2)); + chain.body.forEach(function (gene) { + // Find payload keys that match gene names in this response + var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_'); + // aliases are modified gene names + var constraint = data[alias] && data[alias]['gnomad_constraint']; + // gnomad API has two ways of specifying missing data for a requested gene + if (constraint) { + // Add all fields from constraint data- do not override fields present in the gene source + Object.keys(constraint).forEach(function (key) { + var val = constraint[key]; + if (typeof gene[key] === 'undefined') { + if (typeof val == 'number' && val.toString().indexOf('.') !== -1) { + val = parseFloat(val.toFixed(2)); + } + gene[key] = val; // These two sources are both designed to bypass namespacing } - chain.body[i][field] = val; - } else { - // If the gene did not come back in the response then set the same field with a null values - chain.body[i][field] = null; - } - }); + }); + } }); return chain.body; }; diff --git a/dist/locuszoom.app.js.map b/dist/locuszoom.app.js.map index 15f872c0..2ea14ff2 100644 --- a/dist/locuszoom.app.js.map +++ b/dist/locuszoom.app.js.map @@ -1 +1 @@ -{"version":3,"sources":["LocusZoom.js","Layouts.js","DataLayer.js","annotation_track.js","forest.js","genes.js","genome_legend.js","intervals.js","line.js","scatter.js","Singletons.js","Dashboard.js","Legend.js","Data.js","Plot.js","Panel.js"],"names":["LocusZoom","version","populate","selector","datasource","layout","Error","d3","select","html","plot","call","node","id","iterator","empty","attr","Plot","container","dataset","region","parsed_state","parsePositionQuery","Object","keys","forEach","key","state","svg","append","style","setDimensions","positionPanels","initialize","length","refresh","populateAll","plots","selectAll","each","d","i","positionIntToString","pos","exp","suffix","exp_symbols","isNaN","log","Math","LN10","min","max","places_exp","floor","toFixed","min_exp","places","ret","pow","positionStringToInt","p","val","toUpperCase","replace","suffixre","exec","mult","Number","x","chrposoff","chrpos","match","center","offset","chr","start","end","position","prettyTicks","range","clip_range","target_tick_count","parseInt","min_n","shrink_sml","high_u_bias","u5_bias","abs","c","base","base_toFixed","round","unit","ticks","parseFloat","push","indexOf","slice","pop","createCORSPromise","method","url","body","headers","timeout","Promise","resolve","reject","xhr","XMLHttpRequest","open","XDomainRequest","onreadystatechange","readyState","status","response","setTimeout","header","setRequestHeader","send","validateState","new_state","validated_region","attempted_midpoint","attempted_scale","temp","min_region_scale","max_region_scale","parseFields","data","tokens","regex","m","text","index","condition","variable","close","console","error","JSON","stringify","astify","token","shift","then","ast","cache","hasOwnProperty","Data","Field","render_node","value","map","join","getToolTipData","parentNode","classed","getToolTipDataLayer","getDataLayer","getToolTipPanel","data_layer","parent","getToolTipPlot","panel","generateCurtain","curtain","showing","content_selector","hide_delay","show","content","css","parent_plot","insert","on","hide","bind","update","clearTimeout","page_origin","getPageOrigin","top","y","left","width","height","delay","remove","generateLoader","loader","progress_selector","cancel_selector","percent","padding","loader_boundrect","getBoundingClientRect","animate","setPercentCompleted","subclass","extra","Sub","constructor","apply","arguments","prototype","create","k","ext","LZ_SIG_THRESHOLD_LOGP","Layouts","obj","layouts","get","type","name","modifications","merge","unnamespaced","parse","default_namespace","namespace","default","toString","applyNamespaces","element","re","resolved_namespace","r","merge_namespace","namespaced_element","namespaced_property","property","set","add","list","custom_layout","default_layout","custom_type","default_type","Array","isArray","closable","or","and","covariates_model_association","orientation","fields","z_index","x_axis","field","y_axis","axis","ceiling","point_shape","scale_function","parameters","field_value","else","point_size","color","breaks","values","legend","shape","size","label","class","id_field","upper_buffer","min_extent","behaviors","onmouseover","action","onmouseout","onclick","exclusive","onshiftclick","tooltip","l","fill_opacity","catalog","tooltip_positioning","category_field","lower_buffer","categories","null_value","spacing","lines","filters","operator","start_field","end_field","track_split_field","split_tracks","always_hide_legend","button_html","show_selected","button_title","state_field","options","display_name","components","group_position","title","subtitle","covariates_model_plot_dashboard","region_nav_plot_dashboard","step","min_width","min_height","proportional_width","margin","right","bottom","inner_border","dashboard","axes","label_offset","tick_format","extent","y1","y2","origin","hidden","interaction","drag_background_to_pan","drag_x_ticks_to_scale","drag_y1_ticks_to_scale","drag_y2_ticks_to_scale","scroll_to_zoom","x_linked","data_layers","layer_name","default_config_display_name","display","transform","data_layer_id","pad_from_bottom","responsive_resize","panels","proportional_height","StandardLayout","mouse_guide","DataLayer","initialized","layout_idx","Panel","DefaultLayout","_base_layout","state_id","setDefaultState","tooltips","global_statuses","addField","fieldName","transformations","fieldString","layer_state","Statuses","adjectives","verbs","menu_antiverbs","getBaseId","getAbsoluteDataHeight","dataBCR","group","canTransition","transition","panel_boundaries","dragging","panel_id","getElementId","element_id","getElementStatusNodeId","getElementById","applyDataMethods","field_to_match","receive","broadcast_value","lz_match_value","undefined","lz_highlight_match","toHTML","deselect","unselectElement","applyCustomDataMethods","clipRect","moveUp","data_layer_ids_by_z_index","resortDataLayers","moveDown","resolveScalableParameter","idx","f","ScaleFunctions","_getDataExtent","axis_config","getAxisExtent","dimension","axis_name","axis_layout","data_extent","original_extent_span","range_min","range_max","getTicks","config","createTooltip","positionTooltip","arrow","updateTooltip","destroyTooltip","element_or_id","temporary","label_mark_position","splice","destroyAllTooltips","event","pageX","pageY","positionAllTooltips","showOrHideTooltip","first_time","resolveStatus","statuses","directive","reduce","previousValue","currentValue","sub_status","sub_operator","show_directive","hide_directive","antistatus","show_resolved","hide_resolved","has_tooltip","tooltip_was_closed","filter","return_type","test","operators","a","b","matches","filterIndexes","filterElements","verb","adjective","antiverb","setElementStatus","setElementStatusByFilters","setAllElementStatus","active","get_element_id_error","element_status_node_id","element_status_idx","added_status","emit","is_selected","value_to_broadcast","toggle","status_ids","applyBehaviors","selection","event_match","executeBehaviors","requiredKeyStates","ctrl","ctrlKey","shiftKey","behavior","current_status_boolean","href","target","window","location","panel_origin","exportData","format","default_format","toLowerCase","e","warn","jsonified","delimiter","record","draw","cliparea","reMap","promise","lzd","getData","new_data","DataLayers","datalayers","datalayer","extend","parent_name","overrides","child","hit_area_width","render","self","trackData","visible_lines_group","enter","exit","hit_areas_group","hit_areas_selection","_getX","x_center","x_left","left_node","left_node_x_center","crds","arrow_type","arrow_top","arrow_left","arrow_width","stroke_width","tooltip_box","data_layer_height","data_layer_width","x_scale","y_center","offset_right","offset_left","top_offset","mouse","confidence_intervals","show_no_significance_line","border_radius","y_scale","sqrt","PI","ci_selection","ci_transform","ci_width","ci_height","duration","ease","points_selection","initial_y","fill","symbol","element_data","ci_config","axis_num","item","field_to_add","stroke","label_font_size","label_exon_spacing","exon_height","bounding_box_padding","track_vertical_spacing","getTrackHeight","transcript_idx","tracks","gene_track_index","assignTracks","getLabelWidth","gene_name","font_size","temp_text","label_width","getBBox","g","gene_id","split","gene_version","transcript_id","transcripts","display_range","text_anchor","centered_margin","display_domain","invert","track","potential_track","collision_on_potential_track","placed_gene","min_start","max_end","t","exons","gene","bboxes","boundary_fill","boundary_stroke","boundaries","labels","strand","exon_fill","exon_stroke","exon_id","clickareas","gene_bbox_id","gene_bbox","gene_center_x","chromosome_fill_colors","light","dark","chromosome_label_colors","genome_start","genome_end","chromosomes","variant_parts","variant","track_split_order","track_split_legend_to_y_axis","track_height","previous_tracks","interval_track_index","track_split_field_index","reverse","placed_interval","psuedoElement","sharedstatusnode_style","interval","statusnode_style","statusnodes","rects","interval_name","updateSplitTrackAxis","interval_bbox","interval_center_x","legend_axis","track_spacing","target_height","scaleHeightToData","toggleSplitTracks","interpolate","hitarea_width","mouse_event","line","tooltip_timeout","getMouseDisplayAndData","slope","x_field","y_field","bisect","bisector","datum","startDatum","endDatum","interpolateNumber","x_precision","toPrecision","y_precision","dd","min_arrow_left","max_arrow_left","path","area","y0","hitarea","hitarea_line","path_class","global_status","decoupled","x_extent","y_extent","x_range","default_y","flip_labels","handle_lines","Boolean","min_x","max_x","flip","dn","dnl","dnx","text_swing","dnlx2","line_swing","label_texts","da","dax","abound","dal","label_lines","db","bbound","collision","separate_labels","seperate_iterations","alpha","again","sign","adjust","new_a_y","new_b_y","min_y","max_y","delta","label_elements","label_line","filtered_data","label_groups","makeLDReference","ref","applyState","ldrefvar","_prepareData","xField","sourceData","sort","ak","bk","av","bv","_generateCategoryBounds","uniqueCategories","category","bounds","categoryNames","_setDynamicColorScheme","_getColorScale","from_source","color_params","find","colorParams","baseParams","parameters_categories_hash","every","colors","color_scale","scale","category10","category20","concat","categoryBounds","_categories","knownCategories","knownColors","xPos","diff","KnownDataSources","sources","findSourceByName","SOURCE_NAME","source","source_name","newObj","params","Function","getAll","setAll","clear","TransformationFunctions","getTrans","fun","parseTrans","parseTransString","funs","result","substring","fn","ceil","toExponential","str","encodeURIComponent","s","functions","input","threshold","prev","curr","nullval","upper_idx","brk","normalized_input","isFinite","Dashboard","hide_timeout","persist","component","Components","shouldPersist","visibility","destroy","force","Component","parent_panel","parent_svg","button","menu","Button","parent_dashboard","tag","setTag","setHtml","setText","setTitle","setColor","setStyle","getClass","permanent","setPermanent","bool","setStatus","highlight","disable","setOnMouseover","setOnMouseout","setOnclick","preUpdate","postUpdate","outer_selector","inner_selector","scroll_position","scrollTop","scrollbar_padding","menu_height_padding","page_scroll_top","document","documentElement","container_offset","getContainerOffset","dashboard_client_rect","button_client_rect","menu_client_rect","total_content_height","scrollHeight","base_max_width","container_max_width","content_max_width","base_max_height","max_height","setPopulate","menu_populate_function","div_selector","title_selector","display_width","display_height","generateBase64SVG","old","URL","revokeObjectURL","filename","css_string","stylesheet","styleSheets","outerHTML","dy","initial_html","style_def","insert_at","Blob","createObjectURL","suppress_confirm","confirm","removePanel","is_at_top","y_index","is_at_bottom","panel_ids_by_y_index","can_zoom","current_region_scale","zoom_factor","new_region_scale","menu_html","model","covariates","CovariatesModel","element_reference","updateComponent","removeByIdx","removeAll","table","covariate","row","cov","scale_timeout","status_adj","status_idx","status_verb","at_top","at_bottom","td","removeDataLayer","allowed_fields","fields_whitelist","dataLayer","dataLayerLayout","defaultConfig","configSlot","_selected_item","uniqueID","random","menuLayout","renderRow","display_options","row_id","radioId","field_name","defaultName","Legend","background_rect","elements","elements_group","label_size","line_height","label_x","label_y","path_y","symbolTypes","radius","bcr","right_x","pad_from_right","validateBuildSource","class_name","build","DataSources","addSource","ns","dsobj","source_id","getSource","removeSource","fromJSON","ds","toJSON","parts","full_name","applyTransformations","Requester","split_requests","requests","raw","trans","outnames","request_handles","discrete","Source","enableCache","dependentSource","parseInit","init","getCacheKey","chain","getURL","fetchRequest","getRequest","req","cacheKey","_cachedKey","_cachedResponse","preGetData","pre","resp","parseResponse","normalizeResponse","N","sameLength","records","j","prepareData","annotateData","extractFields","fieldFound","output_record","v","combineChainBody","json","standardized","one_source_body","new_body","parseArraysToObjects","standard","parseObjectsToObjects","parseData","constructorFun","uniqueName","getPrototypeOf","AssociationSource","unshift","analysis","LDSource","findMergeFields","exactMatch","arr","regexes","dataFields","position_field","pvalue","pvalue_field","_names_","names","nameMatch","id_match","RegExp","findRequestedFields","isrefvarin","isrefvarout","ldin","ldout","getRefvar","findExtremeValue","pval_field","is_log","cmp","extremeVal","extremeIdx","reqFields","refVar","columns","refSource","ldrefsource","leftJoin","lfield","rfield","position2","tagRefVariant","refvar","idfield","outrefname","outldname","corrField","rsquare","LDSource2","genome_build","ld_source","population","ld_pop","combined","chainRequests","payload","next","GwasCatalog","build_option","default_source","knownFields","posMatch","decider","decider_out","n_matches","outn","chainNames","catNames","GeneSource","GeneConstraintSource","geneids","substr","constraint_fields","RecombinationRateSource","IntervalSource","bedtracksource","StaticSource","_data","PheWASSource","ConnectorSource","_source_name_mapping","specified_ids","REQUIRED_SOURCES","chain_source_id","applyPanelYIndexesToPanelLayouts","pid","remap_promises","window_onresize","event_hooks","hook","off","theseHooks","hookMatch","eventData","sourceID","hookToRun","eventContext","bounding_client_rect","x_offset","scrollLeft","y_offset","offsetParent","offsetTop","offsetLeft","canInteract","loading_data","zooming","initializeLayout","aspect_ratio","sumProportional","total","rescaleSVG","clientRect","RESIZE_MODES","panel_layout","addPanel","panel_width","panel_height","setOrigin","proportional_origin","clearPanelData","panelId","mode","panelsList","dlid","layer","x_linked_margins","total_proportional_height","proportional_adjustment","calculated_plot_height","mouse_guide_svg","mouse_guide_vertical_svg","mouse_guide_horizontal_svg","vertical","horizontal","selectors","corner_selector","panel_idx","panel_resize_drag","drag","this_panel","original_panel_height","panel_height_change","new_calculated_plot_height","loop_panel_id","loop_panel_idx","loop_panel","corner_drag","dx","plot_page_origin","panel_page_origin","corner_padding","corner_size","mouseout_mouse_guide","mousemove_mouse_guide","coords","mouseup","stopDrag","mousemove","preventDefault","dragged_x","start_x","dragged_y","start_y","linked_panel_ids","to_send","client_rect","subscribeToData","success_callback","opts","error_callback","onerror","err","listener","catch","state_changes","all","message","startDrag","getLinkedPanelIds","overrideAxisLayout","axis_number","y_axis_number","generateID","applyDataLayerZIndexesToDataLayerLayouts","data_promises","y1_scale","y2_scale","y1_extent","y2_extent","x_ticks","y1_ticks","y2_ticks","zoom_timeout","bubble","plot_origin","background_click","y1_linked","y2_linked","panel_count","setMargin","y1_range","y2_range","label_function","data_layer_layout","addDataLayer","clipPath","clearSelections","x_axis_label","y1_axis","y1_axis_label","y2_axis","y2_axis_label","mousedown","ascending","generateExtents","generateTicks","baseTickConfig","combinedTicks","acc","nextLayer","itemConfig","constrain","limit_exponent","neg_min","neg_max","pos_min","pos_max","Infinity","ranges","base_x_range","x_shifted","base_y1_range","y1_shifted","base_y2_range","y2_shifted","anchor","scalar","current_extent_size","current_scaled_extent_size","potential_extent_size","new_extent_size","offset_ratio","new_x_extent_start","y_shifted","linear","domain","renderAxis","zoom_handler","wheelDelta","detail","deltaY","zoom_listener","zoom","canRender","axis_params","label_rotate","ticksAreAllNumbers","orient","tickPadding","tickValues","tickFormat","tick_selector","tick_mouseover","focus","cursor","dh","addBasicLoader","show_immediately"],"mappings":"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","file":"locuszoom.app.js","sourcesContent":["/**\n * @namespace\n */\nvar LocusZoom = {\n version: '0.10.0'\n};\n\n/**\n * Populate a single element with a LocusZoom plot.\n * selector can be a string for a DOM Query or a d3 selector.\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot} The newly created plot instance\n */\nLocusZoom.populate = function(selector, datasource, layout) {\n if (typeof selector == 'undefined') {\n throw new Error('LocusZoom.populate selector not defined');\n }\n // Empty the selector of any existing content\n d3.select(selector).html('');\n var plot;\n d3.select(selector).call(function() {\n // Require each containing element have an ID. If one isn't present, create one.\n if (typeof this.node().id == 'undefined') {\n var iterator = 0;\n while (!d3.select('#lz-' + iterator).empty()) { iterator++; }\n this.attr('id', '#lz-' + iterator);\n }\n // Create the plot\n plot = new LocusZoom.Plot(this.node().id, datasource, layout);\n plot.container = this.node();\n // Detect data-region and fill in state values if present\n if (typeof this.node().dataset !== 'undefined' && typeof this.node().dataset.region !== 'undefined') {\n var parsed_state = LocusZoom.parsePositionQuery(this.node().dataset.region);\n Object.keys(parsed_state).forEach(function(key) {\n plot.state[key] = parsed_state[key];\n });\n }\n // Add an SVG to the div and set its dimensions\n plot.svg = d3.select('div#' + plot.id)\n .append('svg')\n .attr('version', '1.1')\n .attr('xmlns', 'http://www.w3.org/2000/svg')\n .attr('id', plot.id + '_svg').attr('class', 'lz-locuszoom')\n .style(plot.layout.style);\n plot.setDimensions();\n plot.positionPanels();\n // Initialize the plot\n plot.initialize();\n // If the plot has defined data sources then trigger its first mapping based on state values\n if (typeof datasource == 'object' && Object.keys(datasource).length) {\n plot.refresh();\n }\n });\n return plot;\n};\n\n/**\n * Populate arbitrarily many elements each with a LocusZoom plot\n * using a common datasource and layout\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot[]}\n */\nLocusZoom.populateAll = function(selector, datasource, layout) {\n var plots = [];\n d3.selectAll(selector).each(function(d,i) {\n plots[i] = LocusZoom.populate(this, datasource, layout);\n });\n return plots;\n};\n\n/**\n * Convert an integer chromosome position to an SI string representation (e.g. 23423456 => \"23.42\" (Mb))\n * @param {Number} pos Position\n * @param {Number} [exp] Exponent to use for the returned string, eg 6=> MB. If not specified, will attempt to guess\n * the most appropriate SI prefix based on the number provided.\n * @param {Boolean} [suffix=false] Whether or not to append a suffix (e.g. \"Mb\") to the end of the returned string\n * @returns {string}\n */\nLocusZoom.positionIntToString = function(pos, exp, suffix) {\n var exp_symbols = { 0: '', 3: 'K', 6: 'M', 9: 'G' };\n suffix = suffix || false;\n if (isNaN(exp) || exp === null) {\n var log = Math.log(pos) / Math.LN10;\n exp = Math.min(Math.max(log - (log % 3), 0), 9);\n }\n var places_exp = exp - Math.floor((Math.log(pos) / Math.LN10).toFixed(exp + 3));\n var min_exp = Math.min(Math.max(exp, 0), 2);\n var places = Math.min(Math.max(places_exp, min_exp), 12);\n var ret = '' + (pos / Math.pow(10, exp)).toFixed(places);\n if (suffix && typeof exp_symbols[exp] !== 'undefined') {\n ret += ' ' + exp_symbols[exp] + 'b';\n }\n return ret;\n};\n\n/**\n * Convert an SI string chromosome position to an integer representation (e.g. \"5.8 Mb\" => 58000000)\n * @param {String} p The chromosome position\n * @returns {Number}\n */\nLocusZoom.positionStringToInt = function(p) {\n var val = p.toUpperCase();\n val = val.replace(/,/g, '');\n var suffixre = /([KMG])[B]*$/;\n var suffix = suffixre.exec(val);\n var mult = 1;\n if (suffix) {\n if (suffix[1] === 'M') {\n mult = 1e6;\n } else if (suffix[1] === 'G') {\n mult = 1e9;\n } else {\n mult = 1e3; //K\n }\n val = val.replace(suffixre,'');\n }\n val = Number(val) * mult;\n return val;\n};\n\n/**\n * Parse region queries into their constituent parts\n * TODO: handle genes (or send off to API)\n * @param {String} x A chromosome position query. May be any of the forms `chr:start-end`, `chr:center+offset`,\n * or `chr:pos`\n * @returns {{chr:*, start: *, end:*} | {chr:*, position:*}}\n */\nLocusZoom.parsePositionQuery = function(x) {\n var chrposoff = /^(\\w+):([\\d,.]+[kmgbKMGB]*)([-+])([\\d,.]+[kmgbKMGB]*)$/;\n var chrpos = /^(\\w+):([\\d,.]+[kmgbKMGB]*)$/;\n var match = chrposoff.exec(x);\n if (match) {\n if (match[3] === '+') {\n var center = LocusZoom.positionStringToInt(match[2]);\n var offset = LocusZoom.positionStringToInt(match[4]);\n return {\n chr:match[1],\n start: center - offset,\n end: center + offset\n };\n } else {\n return {\n chr: match[1],\n start: LocusZoom.positionStringToInt(match[2]),\n end: LocusZoom.positionStringToInt(match[4])\n };\n }\n }\n match = chrpos.exec(x);\n if (match) {\n return {\n chr:match[1],\n position: LocusZoom.positionStringToInt(match[2])\n };\n }\n return null;\n};\n\n/**\n * Generate a \"pretty\" set of ticks (multiples of 1, 2, or 5 on the same order of magnitude for the range)\n * Based on R's \"pretty\" function: https://github.com/wch/r-source/blob/b156e3a711967f58131e23c1b1dc1ea90e2f0c43/src/appl/pretty.c\n * @param {Number[]} range A two-item array specifying [low, high] values for the axis range\n * @param {('low'|'high'|'both'|'neither')} [clip_range='neither'] What to do if first and last generated ticks extend\n * beyond the range. Set this to \"low\", \"high\", \"both\", or \"neither\" to clip the first (low) or last (high) tick to\n * be inside the range or allow them to extend beyond.\n * e.g. \"low\" will clip the first (low) tick if it extends beyond the low end of the range but allow the\n * last (high) tick to extend beyond the range. \"both\" clips both ends, \"neither\" allows both to extend beyond.\n * @param {Number} [target_tick_count=5] The approximate number of ticks you would like to be returned; may not be exact\n * @returns {Number[]}\n */\nLocusZoom.prettyTicks = function(range, clip_range, target_tick_count) {\n if (typeof target_tick_count == 'undefined' || isNaN(parseInt(target_tick_count))) {\n target_tick_count = 5;\n }\n target_tick_count = parseInt(target_tick_count);\n\n var min_n = target_tick_count / 3;\n var shrink_sml = 0.75;\n var high_u_bias = 1.5;\n var u5_bias = 0.5 + 1.5 * high_u_bias;\n\n var d = Math.abs(range[0] - range[1]);\n var c = d / target_tick_count;\n if ((Math.log(d) / Math.LN10) < -2) {\n c = (Math.max(Math.abs(d)) * shrink_sml) / min_n;\n }\n\n var base = Math.pow(10, Math.floor(Math.log(c) / Math.LN10));\n var base_toFixed = 0;\n if (base < 1 && base !== 0) {\n base_toFixed = Math.abs(Math.round(Math.log(base) / Math.LN10));\n }\n\n var unit = base;\n if ( ((2 * base) - c) < (high_u_bias * (c - unit)) ) {\n unit = 2 * base;\n if ( ((5 * base) - c) < (u5_bias * (c - unit)) ) {\n unit = 5 * base;\n if ( ((10 * base) - c) < (high_u_bias * (c - unit)) ) {\n unit = 10 * base;\n }\n }\n }\n\n var ticks = [];\n var i = parseFloat( (Math.floor(range[0] / unit) * unit).toFixed(base_toFixed) );\n while (i < range[1]) {\n ticks.push(i);\n i += unit;\n if (base_toFixed > 0) {\n i = parseFloat(i.toFixed(base_toFixed));\n }\n }\n ticks.push(i);\n\n if (typeof clip_range == 'undefined' || ['low', 'high', 'both', 'neither'].indexOf(clip_range) === -1) {\n clip_range = 'neither';\n }\n if (clip_range === 'low' || clip_range === 'both') {\n if (ticks[0] < range[0]) { ticks = ticks.slice(1); }\n }\n if (clip_range === 'high' || clip_range === 'both') {\n if (ticks[ticks.length - 1] > range[1]) { ticks.pop(); }\n }\n\n return ticks;\n};\n\n/**\n * Make an AJAX request and return a promise.\n * From http://www.html5rocks.com/en/tutorials/cors/\n * and with promises from https://gist.github.com/kriskowal/593076\n *\n * @param {String} method The HTTP verb\n * @param {String} url\n * @param {String} [body] The request body to send to the server\n * @param {Object} [headers] Object of custom request headers\n * @param {Number} [timeout] If provided, wait this long (in ms) before timing out\n * @returns {Promise}\n */\nLocusZoom.createCORSPromise = function (method, url, body, headers, timeout) {\n return new Promise(function (resolve, reject) {\n var xhr = new XMLHttpRequest();\n if ('withCredentials' in xhr) {\n // Check if the XMLHttpRequest object has a \"withCredentials\" property.\n // \"withCredentials\" only exists on XMLHTTPRequest2 objects.\n xhr.open(method, url, true);\n } else if (typeof XDomainRequest != 'undefined') {\n // Otherwise, check if XDomainRequest.\n // XDomainRequest only exists in IE, and is IE's way of making CORS requests.\n xhr = new XDomainRequest();\n xhr.open(method, url);\n } else {\n // Otherwise, CORS is not supported by the browser.\n xhr = null;\n }\n if (xhr) {\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4) {\n if (xhr.status === 200 || xhr.status === 0 ) {\n resolve(xhr.response);\n } else {\n reject('HTTP ' + xhr.status + ' for ' + url);\n }\n }\n };\n timeout && setTimeout(reject, timeout);\n body = typeof body !== 'undefined' ? body : '';\n if (typeof headers !== 'undefined') {\n for (var header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n }\n // Send the request\n xhr.send(body);\n }\n });\n};\n\n/**\n * Validate a (presumed complete) plot state object against internal rules for consistency, and ensure the plot fits\n * within any constraints imposed by the layout.\n * @param {Object} new_state\n * @param {Number} new_state.start\n * @param {Number} new_state.end\n * @param {Object} layout\n * @returns {*|{}}\n */\nLocusZoom.validateState = function(new_state, layout) {\n\n new_state = new_state || {};\n layout = layout || {};\n\n // If a \"chr\", \"start\", and \"end\" are present then resolve start and end\n // to numeric values that are not decimal, negative, or flipped\n var validated_region = false;\n if (typeof new_state.chr != 'undefined' && typeof new_state.start != 'undefined' && typeof new_state.end != 'undefined') {\n // Determine a numeric scale and midpoint for the attempted region,\n var attempted_midpoint = null; var attempted_scale;\n new_state.start = Math.max(parseInt(new_state.start), 1);\n new_state.end = Math.max(parseInt(new_state.end), 1);\n if (isNaN(new_state.start) && isNaN(new_state.end)) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_midpoint = 0.5;\n attempted_scale = 0;\n } else if (isNaN(new_state.start) || isNaN(new_state.end)) {\n attempted_midpoint = new_state.start || new_state.end;\n attempted_scale = 0;\n new_state.start = (isNaN(new_state.start) ? new_state.end : new_state.start);\n new_state.end = (isNaN(new_state.end) ? new_state.start : new_state.end);\n } else {\n attempted_midpoint = Math.round((new_state.start + new_state.end) / 2);\n attempted_scale = new_state.end - new_state.start;\n if (attempted_scale < 0) {\n var temp = new_state.start;\n new_state.end = new_state.start;\n new_state.start = temp;\n attempted_scale = new_state.end - new_state.start;\n }\n if (attempted_midpoint < 0) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_scale = 0;\n }\n }\n validated_region = true;\n }\n\n // Constrain w/r/t layout-defined minimum region scale\n if (!isNaN(layout.min_region_scale) && validated_region && attempted_scale < layout.min_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.min_region_scale / 2), 1);\n new_state.end = new_state.start + layout.min_region_scale;\n }\n\n // Constrain w/r/t layout-defined maximum region scale\n if (!isNaN(layout.max_region_scale) && validated_region && attempted_scale > layout.max_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.max_region_scale / 2), 1);\n new_state.end = new_state.start + layout.max_region_scale;\n }\n\n return new_state;\n};\n\n//\n/**\n * Replace placeholders in an html string with field values defined in a data object\n * Only works on scalar values! Will ignore non-scalars.\n *\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @param {Object} data\n * @param {String} html A placeholder string in which to substitute fields. Supports several template options:\n * `{{field_name}}` is a variable placeholder for the value of `field_name` from the provided data\n * `{{#if field_name}} Conditional text {{/if}}` will insert the contents of the tag only if the value exists.\n * Since this is only an existence check, **variables with a value of 0 will be evaluated as true**.\n * This can be used with namespaced values, `{{#if assoc:field}}`; any dynamic namespacing will be applied when the\n * layout is first retrieved.\n * @returns {string}\n */\nLocusZoom.parseFields = function (data, html) {\n if (typeof data != 'object') {\n throw new Error('LocusZoom.parseFields invalid arguments: data is not an object');\n }\n if (typeof html != 'string') {\n throw new Error('LocusZoom.parseFields invalid arguments: html is not a string');\n }\n // `tokens` is like [token,...]\n // `token` is like {text: '...'} or {variable: 'foo|bar'} or {condition: 'foo|bar'} or {close: 'if'}\n var tokens = [];\n var regex = /\\{\\{(?:(#if )?([A-Za-z0-9_:|]+)|(\\/if))\\}\\}/;\n while (html.length > 0) {\n var m = regex.exec(html);\n if (!m) { tokens.push({text: html}); html = ''; }\n else if (m.index !== 0) { tokens.push({text: html.slice(0, m.index)}); html = html.slice(m.index); }\n else if (m[1] === '#if ') { tokens.push({condition: m[2]}); html = html.slice(m[0].length); }\n else if (m[2]) { tokens.push({variable: m[2]}); html = html.slice(m[0].length); }\n else if (m[3] === '/if') { tokens.push({close: 'if'}); html = html.slice(m[0].length); }\n else {\n console.error('Error tokenizing tooltip when remaining template is ' + JSON.stringify(html) +\n ' and previous tokens are ' + JSON.stringify(tokens) +\n ' and current regex match is ' + JSON.stringify([m[1], m[2], m[3]]));\n html = html.slice(m[0].length);\n }\n }\n var astify = function() {\n var token = tokens.shift();\n if (typeof token.text !== 'undefined' || token.variable) {\n return token;\n } else if (token.condition) {\n token.then = [];\n while(tokens.length > 0) {\n if (tokens[0].close === 'if') { tokens.shift(); break; }\n token.then.push(astify());\n }\n return token;\n } else {\n console.error('Error making tooltip AST due to unknown token ' + JSON.stringify(token));\n return { text: '' };\n }\n };\n // `ast` is like [thing,...]\n // `thing` is like {text: \"...\"} or {variable:\"foo|bar\"} or {condition: \"foo|bar\", then:[thing,...]}\n var ast = [];\n while (tokens.length > 0) {\n ast.push(astify());\n }\n\n var resolve = function(variable) {\n if (!resolve.cache.hasOwnProperty(variable)) {\n resolve.cache[variable] = (new LocusZoom.Data.Field(variable)).resolve(data);\n }\n return resolve.cache[variable];\n };\n resolve.cache = {};\n var render_node = function(node) {\n if (typeof node.text !== 'undefined') {\n return node.text;\n } else if (node.variable) {\n try {\n var value = resolve(node.variable);\n if (['string','number','boolean'].indexOf(typeof value) !== -1) { return value; }\n if (value === null) { return ''; }\n } catch (error) { console.error('Error while processing variable ' + JSON.stringify(node.variable)); }\n return '{{' + node.variable + '}}';\n } else if (node.condition) {\n try {\n var condition = resolve(node.condition);\n if (condition || condition === 0) {\n return node.then.map(render_node).join('');\n }\n } catch (error) { console.error('Error while processing condition ' + JSON.stringify(node.variable)); }\n return '';\n } else { console.error('Error rendering tooltip due to unknown AST node ' + JSON.stringify(node)); }\n };\n return ast.map(render_node).join('');\n};\n\n/**\n * Shortcut method for getting the data bound to a tool tip.\n * @param {Element} node\n * @returns {*} The first element of data bound to the tooltip\n */\nLocusZoom.getToolTipData = function(node) {\n if (typeof node != 'object' || typeof node.parentNode == 'undefined') {\n throw new Error('Invalid node object');\n }\n // If this node is a locuszoom tool tip then return its data\n var selector = d3.select(node);\n if (selector.classed('lz-data_layer-tooltip') && typeof selector.data()[0] != 'undefined') {\n return selector.data()[0];\n } else {\n return LocusZoom.getToolTipData(node.parentNode);\n }\n};\n\n/**\n * Shortcut method for getting a reference to the data layer that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.getToolTipDataLayer = function(node) {\n var data = LocusZoom.getToolTipData(node);\n if (data.getDataLayer) { return data.getDataLayer(); }\n return null;\n};\n\n/**\n * Shortcut method for getting a reference to the panel that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.getToolTipPanel = function(node) {\n var data_layer = LocusZoom.getToolTipDataLayer(node);\n if (data_layer) { return data_layer.parent; }\n return null;\n};\n\n/**\n * Shortcut method for getting a reference to the plot that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.getToolTipPlot = function(node) {\n var panel = LocusZoom.getToolTipPanel(node);\n if (panel) { return panel.parent; }\n return null;\n};\n\n/**\n * Generate a curtain object for a plot, panel, or any other subdivision of a layout\n * The panel curtain, like the plot curtain is an HTML overlay that obscures the entire panel. It can be styled\n * arbitrarily and display arbitrary messages. It is useful for reporting error messages visually to an end user\n * when the error renders the panel unusable.\n * TODO: Improve type doc here\n * @returns {object}\n */\nLocusZoom.generateCurtain = function() {\n var curtain = {\n showing: false,\n selector: null,\n content_selector: null,\n hide_delay: null,\n\n /**\n * Generate the curtain. Any content (string) argument passed will be displayed in the curtain as raw HTML.\n * CSS (object) can be passed which will apply styles to the curtain and its content.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n show: function(content, css) {\n if (!this.curtain.showing) {\n this.curtain.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div')\n .attr('class', 'lz-curtain').attr('id', this.id + '.curtain');\n this.curtain.content_selector = this.curtain.selector.append('div').attr('class', 'lz-curtain-content');\n this.curtain.selector.append('div').attr('class', 'lz-curtain-dismiss').html('Dismiss')\n .on('click', function() {\n this.curtain.hide();\n }.bind(this));\n this.curtain.showing = true;\n }\n return this.curtain.update(content, css);\n }.bind(this),\n\n /**\n * Update the content and css of the curtain that's currently being shown. This method also adjusts the size\n * and positioning of the curtain to ensure it still covers the entire panel with no overlap.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n update: function(content, css) {\n if (!this.curtain.showing) { return this.curtain; }\n clearTimeout(this.curtain.hide_delay);\n // Apply CSS if provided\n if (typeof css == 'object') {\n this.curtain.selector.style(css);\n }\n // Update size and position\n var page_origin = this.getPageOrigin();\n this.curtain.selector.style({\n top: page_origin.y + 'px',\n left: page_origin.x + 'px',\n width: this.layout.width + 'px',\n height: this.layout.height + 'px'\n });\n this.curtain.content_selector.style({\n 'max-width': (this.layout.width - 40) + 'px',\n 'max-height': (this.layout.height - 40) + 'px'\n });\n // Apply content if provided\n if (typeof content == 'string') {\n this.curtain.content_selector.html(content);\n }\n return this.curtain;\n }.bind(this),\n\n /**\n * Remove the curtain\n * @param {number} delay Time to wait (in ms)\n */\n hide: function(delay) {\n if (!this.curtain.showing) { return this.curtain; }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.curtain.hide_delay);\n this.curtain.hide_delay = setTimeout(this.curtain.hide, delay);\n return this.curtain;\n }\n // Remove curtain\n this.curtain.selector.remove();\n this.curtain.selector = null;\n this.curtain.content_selector = null;\n this.curtain.showing = false;\n return this.curtain;\n }.bind(this)\n };\n return curtain;\n};\n\n/**\n * Generate a loader object for a plot, panel, or any other subdivision of a layout\n *\n * The panel loader is a small HTML overlay that appears in the lower left corner of the panel. It cannot be styled\n * arbitrarily, but can show a custom message and show a minimalist loading bar that can be updated to specific\n * completion percentages or be animated.\n * TODO Improve type documentation\n * @returns {object}\n */\nLocusZoom.generateLoader = function() {\n var loader = {\n showing: false,\n selector: null,\n content_selector: null,\n progress_selector: null,\n cancel_selector: null,\n\n /**\n * Show a loading indicator\n * @param {string} [content='Loading...'] Loading message (displayed as raw HTML)\n */\n show: function(content) {\n // Generate loader\n if (!this.loader.showing) {\n this.loader.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div')\n .attr('class', 'lz-loader').attr('id', this.id + '.loader');\n this.loader.content_selector = this.loader.selector.append('div')\n .attr('class', 'lz-loader-content');\n this.loader.progress_selector = this.loader.selector\n .append('div').attr('class', 'lz-loader-progress-container')\n .append('div').attr('class', 'lz-loader-progress');\n /* TODO: figure out how to make this cancel button work\n this.loader.cancel_selector = this.loader.selector.append(\"div\")\n .attr(\"class\", \"lz-loader-cancel\").html(\"Cancel\")\n .on(\"click\", function(){\n this.loader.hide();\n }.bind(this));\n */\n this.loader.showing = true;\n if (typeof content == 'undefined') { content = 'Loading...'; }\n }\n return this.loader.update(content);\n }.bind(this),\n\n /**\n * Update the currently displayed loader and ensure the new content is positioned correctly.\n * @param {string} content The text to display (as raw HTML). If not a string, will be ignored.\n * @param {number} [percent] A number from 1-100. If a value is specified, it will stop all animations\n * in progress.\n */\n update: function(content, percent) {\n if (!this.loader.showing) { return this.loader; }\n clearTimeout(this.loader.hide_delay);\n // Apply content if provided\n if (typeof content == 'string') {\n this.loader.content_selector.html(content);\n }\n // Update size and position\n var padding = 6; // is there a better place to store/define this?\n var page_origin = this.getPageOrigin();\n var loader_boundrect = this.loader.selector.node().getBoundingClientRect();\n this.loader.selector.style({\n top: (page_origin.y + this.layout.height - loader_boundrect.height - padding) + 'px',\n left: (page_origin.x + padding) + 'px'\n });\n /* Uncomment this code when a functional cancel button can be shown\n var cancel_boundrect = this.loader.cancel_selector.node().getBoundingClientRect();\n this.loader.content_selector.style({\n \"padding-right\": (cancel_boundrect.width + padding) + \"px\"\n });\n */\n // Apply percent if provided\n if (typeof percent == 'number') {\n this.loader.progress_selector.style({\n width: (Math.min(Math.max(percent, 1), 100)) + '%'\n });\n }\n return this.loader;\n }.bind(this),\n\n /**\n * Adds a class to the loading bar that makes it loop infinitely in a loading animation. Useful when exact\n * percent progress is not available.\n */\n animate: function() {\n this.loader.progress_selector.classed('lz-loader-progress-animated', true);\n return this.loader;\n }.bind(this),\n\n /**\n * Sets the loading bar in the loader to percentage width equal to the percent (number) value passed. Percents\n * will automatically be limited to a range of 1 to 100. Will stop all animations in progress.\n */\n setPercentCompleted: function(percent) {\n this.loader.progress_selector.classed('lz-loader-progress-animated', false);\n return this.loader.update(null, percent);\n }.bind(this),\n\n /**\n * Remove the loader\n * @param {number} delay Time to wait (in ms)\n */\n hide: function(delay) {\n if (!this.loader.showing) { return this.loader; }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.loader.hide_delay);\n this.loader.hide_delay = setTimeout(this.loader.hide, delay);\n return this.loader;\n }\n // Remove loader\n this.loader.selector.remove();\n this.loader.selector = null;\n this.loader.content_selector = null;\n this.loader.progress_selector = null;\n this.loader.cancel_selector = null;\n this.loader.showing = false;\n return this.loader;\n }.bind(this)\n };\n return loader;\n};\n\n/**\n * Create a new subclass following classical inheritance patterns. Some registry singletons use this internally to\n * enable code reuse and customization of known LZ core functionality.\n *\n * @param {Function} parent A parent class constructor that will be extended by the child class\n * @param {Object} extra An object of additional properties and methods to add/override behavior for the child class.\n * The special \"constructor\" property can be used to specify a custom constructor, or it will call parent by default.\n * Implementer must manage super calls when overriding the constructor.\n * @returns {Function} The constructor for the new child class\n */\nLocusZoom.subclass = function(parent, extra) {\n if (typeof parent !== 'function' ) {\n throw new Error('Parent must be a callable constructor');\n }\n\n extra = extra || {};\n var Sub = extra.hasOwnProperty('constructor') ? extra.constructor : function() {\n parent.apply(this, arguments);\n };\n\n Sub.prototype = Object.create(parent.prototype);\n Object.keys(extra).forEach(function(k) {\n Sub.prototype[k] = extra[k];\n });\n return Sub;\n};\n\n\n/**\n * LocusZoom optional extensions will live under this namespace.\n *\n * Extension code is not part of the core LocusZoom app.js bundle.\n * @namespace\n * @public\n */\nLocusZoom.ext = {};\n","/* global LocusZoom */\n'use strict';\n\nvar LZ_SIG_THRESHOLD_LOGP = 7.301; // -log10(.05/1e6)\n\n/**\n * Manage known layouts for all parts of the LocusZoom plot\n *\n * This registry allows for layouts to be reused and customized many times on a page, using a common base pattern.\n * It handles the work of ensuring that each new instance of the layout has no shared state with other copies.\n *\n * @class\n */\nLocusZoom.Layouts = (function () {\n var obj = {};\n var layouts = {\n 'plot': {},\n 'panel': {},\n 'data_layer': {},\n 'dashboard': {},\n 'dashboard_components': {},\n 'tooltip': {}\n };\n\n /**\n * Generate a layout configuration object\n * @param {('plot'|'panel'|'data_layer'|'dashboard'|'tooltip')} type The type of layout to retrieve\n * @param {string} name Identifier of the predefined layout within the specified type\n * @param {object} [modifications] Custom properties that override default settings for this layout\n * @returns {object} A JSON-serializable object representation\n */\n obj.get = function (type, name, modifications) {\n if (typeof type != 'string' || typeof name != 'string') {\n throw new Error('invalid arguments passed to LocusZoom.Layouts.get, requires string (layout type) and string (layout name)');\n } else if (layouts[type][name]) {\n // Get the base layout\n var layout = LocusZoom.Layouts.merge(modifications || {}, layouts[type][name]);\n // If \"unnamespaced\" is true then strike that from the layout and return the layout without namespacing\n if (layout.unnamespaced) {\n delete layout.unnamespaced;\n return JSON.parse(JSON.stringify(layout));\n }\n // Determine the default namespace for namespaced values\n var default_namespace = '';\n if (typeof layout.namespace == 'string') {\n default_namespace = layout.namespace;\n } else if (typeof layout.namespace == 'object' && Object.keys(layout.namespace).length) {\n if (typeof layout.namespace.default != 'undefined') {\n default_namespace = layout.namespace.default;\n } else {\n default_namespace = layout.namespace[Object.keys(layout.namespace)[0]].toString();\n }\n }\n default_namespace += default_namespace.length ? ':' : '';\n // Apply namespaces to layout, recursively\n var applyNamespaces = function (element, namespace) {\n if (namespace) {\n if (typeof namespace == 'string') {\n namespace = { default: namespace };\n }\n } else {\n namespace = { default: '' };\n }\n if (typeof element == 'string') {\n var re = /\\{\\{namespace(\\[[A-Za-z_0-9]+\\]|)\\}\\}/g;\n var match, base, key, resolved_namespace;\n var replace = [];\n while ((match = re.exec(element)) !== null) {\n base = match[0];\n key = match[1].length ? match[1].replace(/(\\[|\\])/g, '') : null;\n resolved_namespace = default_namespace;\n if (namespace != null && typeof namespace == 'object' && typeof namespace[key] != 'undefined') {\n resolved_namespace = namespace[key] + (namespace[key].length ? ':' : '');\n }\n replace.push({ base: base, namespace: resolved_namespace });\n }\n for (var r in replace) {\n element = element.replace(replace[r].base, replace[r].namespace);\n }\n } else if (typeof element == 'object' && element != null) {\n if (typeof element.namespace != 'undefined') {\n var merge_namespace = (typeof element.namespace == 'string') ? { default: element.namespace } : element.namespace;\n namespace = LocusZoom.Layouts.merge(namespace, merge_namespace);\n }\n var namespaced_element, namespaced_property;\n for (var property in element) {\n if (property === 'namespace') {\n continue;\n }\n namespaced_element = applyNamespaces(element[property], namespace);\n namespaced_property = applyNamespaces(property, namespace);\n if (property !== namespaced_property) {\n delete element[property];\n }\n element[namespaced_property] = namespaced_element;\n }\n }\n return element;\n };\n layout = applyNamespaces(layout, layout.namespace);\n // Return the layout as valid JSON only\n return JSON.parse(JSON.stringify(layout));\n } else {\n throw new Error('layout type [' + type + '] name [' + name + '] not found');\n }\n };\n\n /** @private */\n obj.set = function (type, name, layout) {\n if (typeof type != 'string' || typeof name != 'string' || typeof layout != 'object') {\n throw new Error('unable to set new layout; bad arguments passed to set()');\n }\n if (!layouts[type]) {\n layouts[type] = {};\n }\n if (layout) {\n return (layouts[type][name] = JSON.parse(JSON.stringify(layout)));\n } else {\n delete layouts[type][name];\n return null;\n }\n };\n\n /**\n * Register a new layout definition by name.\n *\n * @param {string} type The type of layout to add. Usually, this will be one of the predefined LocusZoom types,\n * but if you pass a different name, this method will automatically create the new `type` bucket\n * @param {string} name The identifier of the newly added layout\n * @param {object} [layout] A JSON-serializable object containing configuration properties for this layout\n * @returns The JSON representation of the newly created layout\n */\n obj.add = function (type, name, layout) {\n return obj.set(type, name, layout);\n };\n\n /**\n * List all registered layouts\n * @param [type] Optionally narrow the list to only layouts of a specific type; else return all known layouts\n * @returns {*}\n */\n obj.list = function (type) {\n if (!layouts[type]) {\n var list = {};\n Object.keys(layouts).forEach(function (type) {\n list[type] = Object.keys(layouts[type]);\n });\n return list;\n } else {\n return Object.keys(layouts[type]);\n }\n };\n\n /**\n * A helper method used for merging two objects. If a key is present in both, takes the value from the first object\n * Values from `default_layout` will be cleanly copied over, ensuring no references or shared state.\n *\n * Frequently used for preparing custom layouts. Both objects should be JSON-serializable.\n *\n * @param {object} custom_layout An object containing configuration parameters that override or add to defaults\n * @param {object} default_layout An object containing default settings.\n * @returns {object} The custom layout is modified in place and also returned from this method.\n */\n obj.merge = function (custom_layout, default_layout) {\n if (typeof custom_layout !== 'object' || typeof default_layout !== 'object') {\n throw new Error('LocusZoom.Layouts.merge only accepts two layout objects; ' + (typeof custom_layout) + ', ' + (typeof default_layout) + ' given');\n }\n for (var property in default_layout) {\n if (!default_layout.hasOwnProperty(property)) {\n continue;\n }\n // Get types for comparison. Treat nulls in the custom layout as undefined for simplicity.\n // (javascript treats nulls as \"object\" when we just want to overwrite them as if they're undefined)\n // Also separate arrays from objects as a discrete type.\n var custom_type = custom_layout[property] === null ? 'undefined' : typeof custom_layout[property];\n var default_type = typeof default_layout[property];\n if (custom_type === 'object' && Array.isArray(custom_layout[property])) {\n custom_type = 'array';\n }\n if (default_type === 'object' && Array.isArray(default_layout[property])) {\n default_type = 'array';\n }\n // Unsupported property types: throw an exception\n if (custom_type === 'function' || default_type === 'function') {\n throw new Error('LocusZoom.Layouts.merge encountered an unsupported property type');\n }\n // Undefined custom value: pull the default value\n if (custom_type === 'undefined') {\n custom_layout[property] = JSON.parse(JSON.stringify(default_layout[property]));\n continue;\n }\n // Both values are objects: merge recursively\n if (custom_type === 'object' && default_type === 'object') {\n custom_layout[property] = LocusZoom.Layouts.merge(custom_layout[property], default_layout[property]);\n continue;\n }\n }\n return custom_layout;\n };\n\n return obj;\n})();\n\n\n/**\n * Tooltip Layouts\n * @namespace LocusZoom.Layouts.tooltips\n */\n\nLocusZoom.Layouts.add('tooltip', 'standard_association', {\n namespace: { 'assoc': 'assoc' },\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[assoc]}}variant|htmlescape}}
'\n + 'P Value: {{{{namespace[assoc]}}log_pvalue|logtoscinotation|htmlescape}}
'\n + 'Ref. Allele: {{{{namespace[assoc]}}ref_allele|htmlescape}}
'\n + 'Make LD Reference
'\n});\n\nLocusZoom.Layouts.add('tooltip', 'covariates_model_association', function () {\n var covariates_model_association = LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true });\n covariates_model_association.html += 'Condition on Variant
';\n return covariates_model_association;\n}());\n\nLocusZoom.Layouts.add('tooltip', 'standard_genes', {\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '

{{gene_name|htmlescape}}

'\n + 'Gene ID: {{gene_id|htmlescape}}
'\n + 'Transcript ID: {{transcript_id|htmlescape}}
'\n + 'More data on gnomAD'\n});\n\nLocusZoom.Layouts.add('tooltip', 'standard_intervals', {\n namespace: { 'intervals': 'intervals' },\n closable: false,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[intervals]}}state_name|htmlescape}}
{{{{namespace[intervals]}}start|htmlescape}}-{{{{namespace[intervals]}}end|htmlescape}}'\n});\n\nLocusZoom.Layouts.add('tooltip', 'catalog_variant', {\n namespace: { 'assoc': 'assoc', 'catalog': 'catalog' },\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[catalog]}}variant|htmlescape}}
'\n + 'Catalog entries: {{n_catalog_matches|htmlescape}}
'\n + 'Top Trait: {{{{namespace[catalog]}}trait|htmlescape}}
'\n + 'Top P Value: {{{{namespace[catalog]}}log_pvalue|logtoscinotation}}
'\n // User note: if a different catalog is used, the tooltip will need to be replaced with a different link URL\n + 'More: GWAS catalog / dbSNP'\n});\n\n/**\n * Data Layer Layouts: represent specific information from a data source\n * @namespace Layouts.data_layer\n */\n\nLocusZoom.Layouts.add('data_layer', 'significance', {\n id: 'significance',\n type: 'orthogonal_line',\n orientation: 'horizontal',\n offset: LZ_SIG_THRESHOLD_LOGP\n});\n\nLocusZoom.Layouts.add('data_layer', 'recomb_rate', {\n namespace: { 'recomb': 'recomb' },\n id: 'recombrate',\n type: 'line',\n fields: ['{{namespace[recomb]}}position', '{{namespace[recomb]}}recomb_rate'],\n z_index: 1,\n style: {\n 'stroke': '#0000FF',\n 'stroke-width': '1.5px'\n },\n x_axis: {\n field: '{{namespace[recomb]}}position'\n },\n y_axis: {\n axis: 2,\n field: '{{namespace[recomb]}}recomb_rate',\n floor: 0,\n ceiling: 100\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'association_pvalues', {\n namespace: { 'assoc': 'assoc', 'ld': 'ld' },\n id: 'associationpvalues',\n type: 'scatter',\n point_shape: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 'diamond',\n else: 'circle'\n }\n },\n point_size: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 80,\n else: 40\n }\n },\n color: [\n {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: '#9632b8'\n }\n },\n {\n scale_function: 'numerical_bin',\n field: '{{namespace[ld]}}state',\n parameters: {\n breaks: [0, 0.2, 0.4, 0.6, 0.8],\n values: ['#357ebd', '#46b8da', '#5cb85c', '#eea236', '#d43f3a']\n }\n },\n '#B8B8B8'\n ],\n legend: [\n { shape: 'diamond', color: '#9632b8', size: 40, label: 'LD Ref Var', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#d43f3a', size: 40, label: '1.0 > r² ≥ 0.8', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#eea236', size: 40, label: '0.8 > r² ≥ 0.6', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#5cb85c', size: 40, label: '0.6 > r² ≥ 0.4', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#46b8da', size: 40, label: '0.4 > r² ≥ 0.2', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#357ebd', size: 40, label: '0.2 > r² ≥ 0.0', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#B8B8B8', size: 40, label: 'no r² data', class: 'lz-data_layer-scatter' }\n ],\n label: null,\n fields: ['{{namespace[assoc]}}variant', '{{namespace[assoc]}}position', '{{namespace[assoc]}}log_pvalue', '{{namespace[assoc]}}log_pvalue|logtoscinotation', '{{namespace[assoc]}}ref_allele', '{{namespace[ld]}}state', '{{namespace[ld]}}isrefvar'],\n id_field: '{{namespace[assoc]}}variant',\n z_index: 2,\n x_axis: {\n field: '{{namespace[assoc]}}position'\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[assoc]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.10,\n min_extent: [0, 10]\n },\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'association_pvalues_catalog', function () {\n // Slightly modify an existing layout\n var l = LocusZoom.Layouts.get('data_layer', 'association_pvalues', {\n unnamespaced: true,\n id: 'associationpvaluescatalog',\n fill_opacity: 0.7\n });\n l.tooltip.html += '{{#if {{namespace[catalog]}}rsid}}
See hits in GWAS catalog{{/if}}';\n l.namespace.catalog = 'catalog';\n l.fields.push('{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait', '{{namespace[catalog]}}log_pvalue');\n return l;\n}());\n\nLocusZoom.Layouts.add('data_layer', 'phewas_pvalues', {\n namespace: { 'phewas': 'phewas' },\n id: 'phewaspvalues',\n type: 'category_scatter',\n point_shape: 'circle',\n point_size: 70,\n tooltip_positioning: 'vertical',\n id_field: '{{namespace[phewas]}}id',\n fields: ['{{namespace[phewas]}}id', '{{namespace[phewas]}}log_pvalue', '{{namespace[phewas]}}trait_group', '{{namespace[phewas]}}trait_label'],\n x_axis: {\n field: '{{namespace[phewas]}}x', // Synthetic/derived field added by `category_scatter` layer\n category_field: '{{namespace[phewas]}}trait_group',\n lower_buffer: 0.025,\n upper_buffer: 0.025\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[phewas]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.15\n },\n color: [{\n field: '{{namespace[phewas]}}trait_group',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [],\n values: [],\n null_value: '#B8B8B8'\n }\n }],\n fill_opacity: 0.7,\n tooltip: {\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: [\n 'Trait: {{{{namespace[phewas]}}trait_label|htmlescape}}
',\n 'Trait Category: {{{{namespace[phewas]}}trait_group|htmlescape}}
',\n 'P-value: {{{{namespace[phewas]}}log_pvalue|logtoscinotation|htmlescape}}
'\n ].join('')\n },\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n label: {\n text: '{{{{namespace[phewas]}}trait_label|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n {\n field: '{{namespace[phewas]}}log_pvalue',\n operator: '>=',\n value: 20\n }\n ],\n style: {\n 'font-size': '14px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'genes', {\n namespace: { 'gene': 'gene' },\n id: 'genes',\n type: 'genes',\n fields: ['{{namespace[gene]}}all'],\n id_field: 'gene_id',\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_genes', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'genome_legend', {\n namespace: { 'genome': 'genome' },\n id: 'genome_legend',\n type: 'genome_legend',\n fields: ['{{namespace[genome]}}chr', '{{namespace[genome]}}base_pairs'],\n x_axis: {\n floor: 0,\n ceiling: 2881033286\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'intervals', {\n namespace: { 'intervals': 'intervals' },\n id: 'intervals',\n type: 'intervals',\n fields: ['{{namespace[intervals]}}start', '{{namespace[intervals]}}end', '{{namespace[intervals]}}state_id', '{{namespace[intervals]}}state_name'],\n id_field: '{{namespace[intervals]}}start',\n start_field: '{{namespace[intervals]}}start',\n end_field: '{{namespace[intervals]}}end',\n track_split_field: '{{namespace[intervals]}}state_id',\n split_tracks: true,\n always_hide_legend: false,\n color: {\n field: '{{namespace[intervals]}}state_id',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],\n values: ['rgb(212,63,58)', 'rgb(250,120,105)', 'rgb(252,168,139)', 'rgb(240,189,66)', 'rgb(250,224,105)', 'rgb(240,238,84)', 'rgb(244,252,23)', 'rgb(23,232,252)', 'rgb(32,191,17)', 'rgb(23,166,77)', 'rgb(32,191,17)', 'rgb(162,133,166)', 'rgb(212,212,212)'],\n null_value: '#B8B8B8'\n }\n },\n legend: [\n { shape: 'rect', color: 'rgb(212,63,58)', width: 9, label: 'Active Promoter', '{{namespace[intervals]}}state_id': 1 },\n { shape: 'rect', color: 'rgb(250,120,105)', width: 9, label: 'Weak Promoter', '{{namespace[intervals]}}state_id': 2 },\n { shape: 'rect', color: 'rgb(252,168,139)', width: 9, label: 'Poised Promoter', '{{namespace[intervals]}}state_id': 3 },\n { shape: 'rect', color: 'rgb(240,189,66)', width: 9, label: 'Strong enhancer', '{{namespace[intervals]}}state_id': 4 },\n { shape: 'rect', color: 'rgb(250,224,105)', width: 9, label: 'Strong enhancer', '{{namespace[intervals]}}state_id': 5 },\n { shape: 'rect', color: 'rgb(240,238,84)', width: 9, label: 'Weak enhancer', '{{namespace[intervals]}}state_id': 6 },\n { shape: 'rect', color: 'rgb(244,252,23)', width: 9, label: 'Weak enhancer', '{{namespace[intervals]}}state_id': 7 },\n { shape: 'rect', color: 'rgb(23,232,252)', width: 9, label: 'Insulator', '{{namespace[intervals]}}state_id': 8 },\n { shape: 'rect', color: 'rgb(32,191,17)', width: 9, label: 'Transcriptional transition', '{{namespace[intervals]}}state_id': 9 },\n { shape: 'rect', color: 'rgb(23,166,77)', width: 9, label: 'Transcriptional elongation', '{{namespace[intervals]}}state_id': 10 },\n { shape: 'rect', color: 'rgb(136,240,129)', width: 9, label: 'Weak transcribed', '{{namespace[intervals]}}state_id': 11 },\n { shape: 'rect', color: 'rgb(162,133,166)', width: 9, label: 'Polycomb-repressed', '{{namespace[intervals]}}state_id': 12 },\n { shape: 'rect', color: 'rgb(212,212,212)', width: 9, label: 'Heterochromatin / low signal', '{{namespace[intervals]}}state_id': 13 }\n ],\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_intervals', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'annotation_catalog', {\n // Identify GWAS hits that are present in the GWAS catalog\n namespace: { 'assoc': 'assoc', 'catalog': 'catalog' },\n id: 'annotation_catalog',\n type: 'annotation_track',\n id_field: '{{namespace[catalog]}}variant',\n x_axis: {\n field: '{{namespace[assoc]}}position'\n },\n color: '#0000CC',\n fields: [\n '{{namespace[assoc]}}variant', '{{namespace[assoc]}}chromosome', '{{namespace[assoc]}}position',\n '{{namespace[catalog]}}variant', '{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait',\n '{{namespace[catalog]}}log_pvalue', '{{namespace[catalog]}}pos'\n ],\n filters: [\n // Specify which points to show on the track. Any selection must satisfy ALL filters\n ['{{namespace[catalog]}}rsid', '!=', null],\n ['{{namespace[catalog]}}log_pvalue', '>', LZ_SIG_THRESHOLD_LOGP]\n ],\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'catalog_variant', { unnamespaced: true }),\n tooltip_positioning: 'top'\n});\n\n/**\n * Individual dashboard buttons\n * @namespace Layouts.dashboard_components\n */\nLocusZoom.Layouts.add('dashboard_components', 'ldlz2_pop_selector', {\n // **Note**: this widget is aimed at the LDLZ2 datasource, and the UM 1000G LDServer. Older LZ usages\n // (on the original LD data source) will not work with these population names.\n type: 'set_state',\n position: 'right',\n color: 'blue',\n button_html: 'LD Population: ',\n show_selected: true,\n button_title: 'Select LD Population: ',\n state_field: 'ld_pop',\n // This list below is hardcoded to work with the UMich LDServer, default 1000G populations\n // It can be customized to work with other LD servers that specify population differently\n // https://portaldev.sph.umich.edu/ld/genome_builds/GRCh37/references/1000G/populations\n options: [\n { display_name: 'ALL (default)', value: 'ALL' },\n { display_name: 'AFR', value: 'AFR' },\n { display_name: 'AMR', value: 'AMR' },\n { display_name: 'EAS', value: 'EAS' },\n { display_name: 'EUR', value: 'EUR' },\n { display_name: 'SAS', value: 'SAS' }\n ]\n});\n\n/**\n * Dashboard Layouts: Collections of toolbar buttons etc\n * @namespace Layouts.dashboard\n */\nLocusZoom.Layouts.add('dashboard', 'standard_panel', {\n components: [\n {\n type: 'remove_panel',\n position: 'right',\n color: 'red',\n group_position: 'end'\n },\n {\n type: 'move_panel_up',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'move_panel_down',\n position: 'right',\n group_position: 'start',\n style: { 'margin-left': '0.75em' }\n }\n ]\n});\n\nLocusZoom.Layouts.add('dashboard', 'standard_plot', {\n components: [\n {\n type: 'title',\n title: 'LocusZoom',\n subtitle: 'v' + LocusZoom.version + '',\n position: 'left'\n },\n {\n type: 'download',\n position: 'right'\n }\n ]\n});\n\nLocusZoom.Layouts.add('dashboard', 'covariates_model_plot', function () {\n var covariates_model_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n covariates_model_plot_dashboard.components.push({\n type: 'covariates_model',\n button_html: 'Model',\n button_title: 'Show and edit covariates currently in model',\n position: 'left'\n });\n return covariates_model_plot_dashboard;\n}());\n\nLocusZoom.Layouts.add('dashboard', 'region_nav_plot', function () {\n var region_nav_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n region_nav_plot_dashboard.components.push(\n {\n type: 'shift_region',\n step: 500000,\n button_html: '>>',\n position: 'right',\n group_position: 'end'\n }, {\n type: 'shift_region',\n step: 50000,\n button_html: '>',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'zoom_region',\n step: 0.2,\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'zoom_region',\n step: -0.2,\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'shift_region',\n step: -50000,\n button_html: '<',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'shift_region',\n step: -500000,\n button_html: '<<',\n position: 'right',\n group_position: 'start'\n }\n );\n return region_nav_plot_dashboard;\n}());\n\n/**\n * Panel Layouts\n * @namespace Layouts.panel\n */\n\nLocusZoom.Layouts.add('panel', 'association', {\n id: 'association',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 200,\n proportional_width: 1,\n margin: { top: 35, right: 50, bottom: 40, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_legend',\n position: 'right'\n });\n return l;\n })(),\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n },\n y2: {\n label: 'Recombination Rate (cM/Mb)',\n label_offset: 40\n }\n },\n legend: {\n orientation: 'vertical',\n origin: { x: 55, y: 40 },\n hidden: true\n },\n interaction: {\n drag_background_to_pan: true,\n drag_x_ticks_to_scale: true,\n drag_y1_ticks_to_scale: true,\n drag_y2_ticks_to_scale: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'association_catalog', function () {\n var l = LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n id: 'associationcatalog',\n namespace: { 'assoc': 'assoc', 'ld': 'ld', 'catalog': 'catalog' } // Required to resolve display options\n });\n l.dashboard.components.push({\n type: 'display_options',\n position: 'right',\n color: 'blue',\n // Below: special config specific to this widget\n button_html: 'Display options...',\n button_title: 'Control how plot items are displayed',\n\n layer_name: 'associationpvaluescatalog',\n default_config_display_name: 'No catalog labels (default)', // display name for the default plot color option (allow user to revert to plot defaults)\n\n options: [\n {\n // First dropdown menu item\n display_name: 'Label catalog traits', // Human readable representation of field name\n display: { // Specify layout directives that control display of the plot for this option\n label: {\n text: '{{{{namespace[catalog]}}trait|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n // Only label points if they are significant for some trait in the catalog, AND in high LD\n // with the top hit of interest\n {\n field: '{{namespace[catalog]}}trait',\n operator: '!=',\n value: null\n },\n {\n field: '{{namespace[catalog]}}log_pvalue',\n operator: '>',\n value: LZ_SIG_THRESHOLD_LOGP\n },\n {\n field: '{{namespace[ld]}}state',\n operator: '>',\n value: 0.4\n },\n ],\n style: {\n 'font-size': '10px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n }\n }\n ]\n });\n l.data_layers = [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues_catalog', { unnamespaced: true })\n ];\n return l;\n}());\n\nLocusZoom.Layouts.add('panel', 'genes', {\n id: 'genes',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 112.5,\n proportional_width: 1,\n margin: { top: 20, right: 50, bottom: 20, left: 50 },\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'resize_to_data',\n position: 'right',\n button_html: 'Show all genes',\n });\n return l;\n })(),\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'genes', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'phewas', {\n id: 'phewas',\n width: 800,\n height: 300,\n min_width: 800,\n min_height: 300,\n proportional_width: 1,\n margin: { top: 20, right: 50, bottom: 120, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n axes: {\n x: {\n ticks: { // Object based config (shared defaults; allow layers to specify ticks)\n style: {\n 'font-weight': 'bold',\n 'font-size': '11px',\n 'text-anchor': 'start'\n },\n transform: 'rotate(50)',\n position: 'left' // Special param recognized by `category_scatter` layers\n }\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'phewas_pvalues', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'genome_legend', {\n id: 'genome_legend',\n width: 800,\n height: 50,\n origin: { x: 0, y: 300 },\n min_width: 800,\n min_height: 50,\n proportional_width: 1,\n margin: { top: 0, right: 50, bottom: 35, left: 50 },\n axes: {\n x: {\n label: 'Genomic Position (number denotes chromosome)',\n label_offset: 35,\n ticks: [\n {\n x: 124625310,\n text: '1',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 370850307,\n text: '2',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 591461209,\n text: '3',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 786049562,\n text: '4',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 972084330,\n text: '5',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1148099493,\n text: '6',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1313226358,\n text: '7',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1465977701,\n text: '8',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1609766427,\n text: '9',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1748140516,\n text: '10',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1883411148,\n text: '11',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2017840353,\n text: '12',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2142351240,\n text: '13',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2253610949,\n text: '14',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2358551415,\n text: '15',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2454994487,\n text: '16',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2540769469,\n text: '17',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2620405698,\n text: '18',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2689008813,\n text: '19',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2750086065,\n text: '20',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2805663772,\n text: '21',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2855381003,\n text: '22',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n }\n ]\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'genome_legend', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'intervals', {\n id: 'intervals',\n width: 1000,\n height: 50,\n min_width: 500,\n min_height: 50,\n margin: { top: 25, right: 150, bottom: 5, left: 50 },\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_split_tracks',\n data_layer_id: 'intervals',\n position: 'right'\n });\n return l;\n })(),\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n legend: {\n hidden: true,\n orientation: 'horizontal',\n origin: { x: 50, y: 0 },\n pad_from_bottom: 5\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'intervals', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'annotation_catalog', {\n id: 'annotationcatalog',\n width: 800,\n height: 50,\n min_height: 50,\n proportional_width: 1,\n margin: { top: 25, right: 50, bottom: 0, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true }),\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'annotation_catalog', { unnamespaced: true })\n ]\n});\n\n/**\n * Plot Layouts\n * @namespace Layouts.plot\n */\n\nLocusZoom.Layouts.add('plot', 'standard_association', {\n state: {},\n width: 800,\n height: 450,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', { unnamespaced: true, proportional_height: 0.5 }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true, proportional_height: 0.5 })\n ]\n});\n\nLocusZoom.Layouts.add('plot', 'association_catalog', {\n state: {},\n width: 800,\n height: 500,\n responsive_resize: 'width_only',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'annotation_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'association_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true })\n ]\n});\n\n// Shortcut to \"StandardLayout\" for backward compatibility\nLocusZoom.StandardLayout = LocusZoom.Layouts.get('plot', 'standard_association');\n\nLocusZoom.Layouts.add('plot', 'standard_phewas', {\n width: 800,\n height: 600,\n min_width: 800,\n min_height: 600,\n responsive_resize: 'both',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'phewas', { unnamespaced: true, proportional_height: 0.45 }),\n LocusZoom.Layouts.get('panel', 'genome_legend', { unnamespaced: true, proportional_height: 0.1 }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true, proportional_height: 0.45,\n margin: { bottom: 40 },\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n }\n }\n })\n ],\n mouse_guide: false\n});\n\nLocusZoom.Layouts.add('plot', 'interval_association', {\n state: {},\n width: 800,\n height: 550,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n width: 800,\n proportional_height: (225 / 570)\n }),\n LocusZoom.Layouts.get('panel', 'intervals', { unnamespaced: true, proportional_height: (120 / 570) }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true, width: 800, proportional_height: (225 / 570) })\n ]\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A data layer is an abstract class representing a data set and its graphical representation within a panel\n * @public\n * @class\n * @param {Object} layout A JSON-serializable object describing the layout for this layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n*/\nLocusZoom.DataLayer = function(layout, parent) {\n /** @member {Boolean} */\n this.initialized = false;\n /** @member {Number} */\n this.layout_idx = null;\n\n /** @member {String} */\n this.id = null;\n /** @member {LocusZoom.Panel} */\n this.parent = parent || null;\n /**\n * @member {{group: d3.selection, container: d3.selection, clipRect: d3.selection}}\n */\n this.svg = {};\n\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n if (typeof parent != 'undefined' && parent instanceof LocusZoom.Panel) { this.parent_plot = parent.parent; }\n\n /** @member {Object} */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.DataLayer.DefaultLayout);\n if (this.layout.id) { this.id = this.layout.id; }\n\n // Ensure any axes defined in the layout have an explicit axis number (default: 1)\n if (this.layout.x_axis !== {} && typeof this.layout.x_axis.axis !== 'number') { this.layout.x_axis.axis = 1; }\n if (this.layout.y_axis !== {} && typeof this.layout.y_axis.axis !== 'number') { this.layout.y_axis.axis = 1; }\n\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original data layer state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n\n /** @member {Object} */\n this.state = {};\n /** @member {String} */\n this.state_id = null;\n\n this.setDefaultState();\n\n // Initialize parameters for storing data and tool tips\n /** @member {Array} */\n this.data = [];\n if (this.layout.tooltip) {\n /** @member {Object} */\n this.tooltips = {};\n }\n\n // Initialize flags for tracking global statuses\n this.global_statuses = {\n 'highlighted': false,\n 'selected': false,\n 'faded': false,\n 'hidden': false\n };\n\n return this;\n\n};\n\n/**\n * Instruct this datalayer to begin tracking additional fields from data sources (does not guarantee that such a field actually exists)\n *\n * Custom plots can use this to dynamically extend datalayer functionality after the plot is drawn\n *\n * (since removing core fields may break layer functionality, there is presently no hook for the inverse behavior)\n * @param fieldName\n * @param namespace\n * @param {String|String[]} transformations The name (or array of names) of transformations to apply to this field\n * @returns {String} The raw string added to the fields array\n */\nLocusZoom.DataLayer.prototype.addField = function(fieldName, namespace, transformations) {\n if (!fieldName || !namespace) {\n throw new Error('Must specify field name and namespace to use when adding field');\n }\n var fieldString = namespace + ':' + fieldName;\n if (transformations) {\n fieldString += '|';\n if (typeof transformations === 'string') {\n fieldString += transformations;\n } else if (Array.isArray(transformations)) {\n fieldString += transformations.join('|');\n } else {\n throw new Error('Must provide transformations as either a string or array of strings');\n }\n }\n var fields = this.layout.fields;\n if (fields.indexOf(fieldString) === -1) {\n fields.push(fieldString);\n }\n return fieldString;\n};\n\n/**\n * Define default state that should get tracked during the lifetime of this layer.\n *\n * In some special custom usages, it may be useful to completely reset a panel (eg \"click for\n * genome region\" links), plotting new data that invalidates any previously tracked state. This hook makes it\n * possible to reset without destroying the panel entirely. It is used by `Plot.clearPanelData`.\n */\nLocusZoom.DataLayer.prototype.setDefaultState = function() {\n // Define state parameters specific to this data layer. Within plot state, this will live under a key\n // `panel_name.layer_name`.\n if (this.parent) {\n this.state = this.parent.state;\n this.state_id = this.parent.id + '.' + this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n var layer_state = this.state[this.state_id];\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function(status) {\n layer_state[status] = layer_state[status] || [];\n });\n // Also initialize \"internal-only\" state fields\n layer_state['has_tooltip'] = layer_state['has_tooltip'] || [];\n }\n};\n\n/**\n * A basic description of keys expected in a layout. Not intended to be directly used or modified by an end user.\n * @protected\n * @type {{type: string, fields: Array, x_axis: {}, y_axis: {}}}\n */\nLocusZoom.DataLayer.DefaultLayout = {\n type: '',\n fields: [],\n x_axis: {},\n y_axis: {}\n};\n\n/**\n * Available statuses that individual elements can have. Each status is described by\n * a verb/antiverb and an adjective. Verbs and antiverbs are used to generate data layer\n * methods for updating the status on one or more elements. Adjectives are used in class\n * names and applied or removed from elements to have a visual representation of the status,\n * as well as used as keys in the state for tracking which elements are in which status(es)\n * @static\n * @type {{verbs: String[], adjectives: String[], menu_antiverbs: String[]}}\n */\nLocusZoom.DataLayer.Statuses = {\n verbs: ['highlight', 'select', 'fade', 'hide'],\n adjectives: ['highlighted', 'selected', 'faded', 'hidden'],\n menu_antiverbs: ['unhighlight', 'deselect', 'unfade', 'show']\n};\n\n/**\n * Get the fully qualified identifier for the data layer, prefixed by any parent or container elements\n *\n * @returns {string} A dot-delimited string of the format ..\n */\nLocusZoom.DataLayer.prototype.getBaseId = function() {\n return this.parent_plot.id + '.' + this.parent.id + '.' + this.id;\n};\n\n/**\n * Determine the pixel height of data-bound objects represented inside this data layer. (excluding elements such as axes)\n *\n * May be used by operations that resize the data layer to fit available data\n *\n * @public\n * @returns {number}\n */\nLocusZoom.DataLayer.prototype.getAbsoluteDataHeight = function() {\n var dataBCR = this.svg.group.node().getBoundingClientRect();\n return dataBCR.height;\n};\n\n/**\n * Whether transitions can be applied to this data layer\n * @returns {boolean}\n */\nLocusZoom.DataLayer.prototype.canTransition = function() {\n if (!this.layout.transition) { return false; }\n return !(this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.panel_id);\n};\n\n/**\n * Fetch the fully qualified ID to be associated with a specific visual element, based on the data to which that\n * element is bound. In general this element ID will be unique, allowing it to be addressed directly via selectors.\n * @param {String|Object} element\n * @returns {String}\n */\nLocusZoom.DataLayer.prototype.getElementId = function(element) {\n var element_id = 'element';\n if (typeof element == 'string') {\n element_id = element;\n } else if (typeof element == 'object') {\n var id_field = this.layout.id_field || 'id';\n if (typeof element[id_field] == 'undefined') {\n throw new Error('Unable to generate element ID');\n }\n element_id = element[id_field].toString().replace(/\\W/g,'');\n }\n return (this.getBaseId() + '-' + element_id).replace(/([:.[\\],])/g, '_');\n};\n\n/**\n * Fetch an ID that may bind a data element to a separate visual node for displaying status\n * Examples of this might be seperate visual nodes to show select/highlight statuses, or\n * even a common/shared node to show status across many elements in a set.\n * Abstract method. It should be overridden by data layers that implement seperate status\n * nodes specifically to the use case of the data layer type.\n * @param {String|Object} element\n * @returns {String|null}\n */\nLocusZoom.DataLayer.prototype.getElementStatusNodeId = function(element) {\n return null;\n};\n\n/**\n * Returns a reference to the underlying data associated with a single visual element in the data layer, as\n * referenced by the unique identifier for the element\n\n * @param {String} id The unique identifier for the element, as defined by `getElementId`\n * @returns {Object|null} The data bound to that element\n */\nLocusZoom.DataLayer.prototype.getElementById = function(id) {\n var selector = d3.select('#' + id.replace(/([:.[\\],])/g, '\\\\$1')); // escape special characters\n if (!selector.empty() && selector.data() && selector.data().length) {\n return selector.data()[0];\n } else {\n return null;\n }\n};\n\n/**\n * Basic method to apply arbitrary methods and properties to data elements.\n * This is called on all data immediately after being fetched.\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.applyDataMethods = function() {\n var field_to_match = (this.layout.match && this.layout.match.receive);\n var broadcast_value = this.parent_plot.state.lz_match_value;\n\n this.data.forEach(function(d, i) {\n // Basic toHTML() method - return the stringified value in the id_field, if defined.\n\n // When this layer receives data, mark whether points match (via a synthetic boolean field)\n // Any field-based layout directives (color, size, shape) can then be used to control display\n if (field_to_match && broadcast_value !== null && broadcast_value !== undefined) {\n d.lz_highlight_match = (d[field_to_match] === broadcast_value);\n }\n\n this.data[i].toHTML = function() {\n var id_field = this.layout.id_field || 'id';\n var html = '';\n if (this.data[i][id_field]) { html = this.data[i][id_field].toString(); }\n return html;\n }.bind(this);\n // getDataLayer() method - return a reference to the data layer\n this.data[i].getDataLayer = function() {\n return this;\n }.bind(this);\n // deselect() method - shortcut method to deselect the element\n this.data[i].deselect = function() {\n var data_layer = this.getDataLayer();\n data_layer.unselectElement(this);\n };\n }.bind(this));\n this.applyCustomDataMethods();\n return this;\n};\n\n/**\n * Hook that allows custom datalayers to apply additional methods and properties to data elements as needed\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.applyCustomDataMethods = function() {\n return this;\n};\n\n/**\n * Initialize a data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.initialize = function() {\n\n // Append a container group element to house the main data layer group element and the clip path\n this.svg.container = this.parent.svg.group.append('g')\n .attr('class', 'lz-data_layer-container')\n .attr('id', this.getBaseId() + '.data_layer_container');\n\n // Append clip path to the container element\n this.svg.clipRect = this.svg.container.append('clipPath')\n .attr('id', this.getBaseId() + '.clip')\n .append('rect');\n\n // Append svg group for rendering all data layer elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g')\n .attr('id', this.getBaseId() + '.data_layer')\n .attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n\n return this;\n\n};\n\n/**\n * Move a data layer up relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.moveUp = function() {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n};\n\n/**\n * Move a data layer down relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.moveDown = function() {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n};\n\n/**\n * Apply scaling functions to an element or parameter as needed, based on its layout and the element's data\n * If the layout parameter is already a primitive type, simply return the value as given\n * @param {Array|Number|String|Object} layout\n * @param {*} data The value to be used with the filter\n * @returns {*} The transformed value\n */\nLocusZoom.DataLayer.prototype.resolveScalableParameter = function(layout, data) {\n var ret = null;\n if (Array.isArray(layout)) {\n var idx = 0;\n while (ret === null && idx < layout.length) {\n ret = this.resolveScalableParameter(layout[idx], data);\n idx++;\n }\n } else {\n switch (typeof layout) {\n case 'number':\n case 'string':\n ret = layout;\n break;\n case 'object':\n if (layout.scale_function) {\n if(layout.field) {\n var f = new LocusZoom.Data.Field(layout.field);\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, f.resolve(data));\n } else {\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, data);\n }\n }\n break;\n }\n }\n return ret;\n};\n\n\n/**\n * Implementation hook for fetching the min and max values of available data. Used to determine axis range, if no other\n * explicit axis settings override. Useful for data layers where the data extent depends on more than one field.\n * (eg confidence intervals in a forest plot)\n * @param data\n * @param axis_config The configuration object for the specified axis.\n * @returns {Array} [min, max] without any padding applied\n * @private\n */\nLocusZoom.DataLayer.prototype._getDataExtent = function(data, axis_config) {\n data = data || this.data;\n // By default this depends only on a single field.\n return d3.extent(data, function (d) {\n var f = new LocusZoom.Data.Field(axis_config.field);\n return +f.resolve(d);\n });\n};\n\n/**\n * Generate dimension extent function based on layout parameters\n * @param {('x'|'y')} dimension\n */\nLocusZoom.DataLayer.prototype.getAxisExtent = function(dimension) {\n\n if (['x', 'y'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier passed to LocusZoom.DataLayer.getAxisExtent()');\n }\n\n var axis_name = dimension + '_axis';\n var axis_layout = this.layout[axis_name];\n\n // If a floor AND a ceiling are explicitly defined then just return that extent and be done\n if (!isNaN(axis_layout.floor) && !isNaN(axis_layout.ceiling)) {\n return [+axis_layout.floor, +axis_layout.ceiling];\n }\n\n // If a field is defined for the axis and the data layer has data then generate the extent from the data set\n var data_extent = [];\n if (axis_layout.field && this.data) {\n if (!this.data.length) {\n // If data has been fetched (but no points in region), enforce the min_extent (with no buffers,\n // because we don't need padding around an empty screen)\n data_extent = axis_layout.min_extent || [];\n return data_extent;\n } else {\n data_extent = this._getDataExtent(this.data, axis_layout);\n\n // Apply upper/lower buffers, if applicable\n var original_extent_span = data_extent[1] - data_extent[0];\n if (!isNaN(axis_layout.lower_buffer)) {\n data_extent[0] -= original_extent_span * axis_layout.lower_buffer;\n }\n if (!isNaN(axis_layout.upper_buffer)) {\n data_extent[1] += original_extent_span * axis_layout.upper_buffer;\n }\n\n if (typeof axis_layout.min_extent == 'object') {\n // The data should span at least the range specified by min_extent, an array with [low, high]\n var range_min = axis_layout.min_extent[0];\n var range_max = axis_layout.min_extent[1];\n if (!isNaN(range_min) && !isNaN(range_max)) {\n data_extent[0] = Math.min(data_extent[0], range_min);\n }\n if (!isNaN(range_max)) {\n data_extent[1] = Math.max(data_extent[1], range_max);\n }\n }\n // If specified, floor and ceiling will override the actual data range\n return [\n isNaN(axis_layout.floor) ? data_extent[0] : axis_layout.floor,\n isNaN(axis_layout.ceiling) ? data_extent[1] : axis_layout.ceiling\n ];\n }\n }\n\n // If this is for the x axis and no extent could be generated yet but state has a defined start and end\n // then default to using the state-defined region as the extent\n if (dimension === 'x' && !isNaN(this.state.start) && !isNaN(this.state.end)) {\n return [this.state.start, this.state.end];\n }\n\n // No conditions met for generating a valid extent, return an empty array\n return [];\n\n};\n\n/**\n * Allow this data layer to tell the panel what axis ticks it thinks it will require. The panel may choose whether\n * to use some, all, or none of these when rendering, either alone or in conjunction with other data layers.\n *\n * This method is a stub and should be overridden in data layers that need to specify custom behavior.\n *\n * @param {('x'|'y1'|'y2')} dimension\n * @param {Object} [config] Additional parameters for the panel to specify how it wants ticks to be drawn. The names\n * and meanings of these parameters may vary between different data layers.\n * @returns {Object[]}\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\nLocusZoom.DataLayer.prototype.getTicks = function (dimension, config) {\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier at layer level' + dimension);\n }\n return [];\n};\n\n/**\n * Generate a tool tip for a given element\n * @param {String|Object} data Data for the element associated with the tooltip\n */\nLocusZoom.DataLayer.prototype.createTooltip = function(data) {\n if (typeof this.layout.tooltip != 'object') {\n throw new Error('DataLayer [' + this.id + '] layout does not define a tooltip');\n }\n var id = this.getElementId(data);\n if (this.tooltips[id]) {\n this.positionTooltip(id);\n return;\n }\n this.tooltips[id] = {\n data: data,\n arrow: null,\n selector: d3.select(this.parent_plot.svg.node().parentNode).append('div')\n .attr('class', 'lz-data_layer-tooltip')\n .attr('id', id + '-tooltip')\n };\n this.state[this.state_id]['has_tooltip'].push(id);\n this.updateTooltip(data);\n return this;\n};\n\n/**\n * Update a tool tip (generate its inner HTML)\n * @param {String|Object} d The element associated with the tooltip\n * @param {String} [id] An identifier to the tooltip\n */\nLocusZoom.DataLayer.prototype.updateTooltip = function(d, id) {\n if (typeof id == 'undefined') { id = this.getElementId(d); }\n // Empty the tooltip of all HTML (including its arrow!)\n this.tooltips[id].selector.html('');\n this.tooltips[id].arrow = null;\n // Set the new HTML\n if (this.layout.tooltip.html) {\n this.tooltips[id].selector.html(LocusZoom.parseFields(d, this.layout.tooltip.html));\n }\n // If the layout allows tool tips on this data layer to be closable then add the close button\n // and add padding to the tooltip to accommodate it\n if (this.layout.tooltip.closable) {\n this.tooltips[id].selector.insert('button', ':first-child')\n .attr('class', 'lz-tooltip-close-button')\n .attr('title', 'Close')\n .text('×')\n .on('click', function() {\n this.destroyTooltip(id);\n }.bind(this));\n }\n // Apply data directly to the tool tip for easier retrieval by custom UI elements inside the tool tip\n this.tooltips[id].selector.data([d]);\n // Reposition and draw a new arrow\n this.positionTooltip(id);\n return this;\n};\n\n/**\n * Destroy tool tip - remove the tool tip element from the DOM and delete the tool tip's record on the data layer\n * @param {String|Object} element_or_id The element (or id) associated with the tooltip\n * @param {boolean} [temporary=false] Whether this is temporary (not to be tracked in state). Differentiates\n * \"recreate tooltips on re-render\" (which is temporary) from \"user has closed this tooltip\" (permanent)\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.destroyTooltip = function(element_or_id, temporary) {\n var id;\n if (typeof element_or_id == 'string') {\n id = element_or_id;\n } else {\n id = this.getElementId(element_or_id);\n }\n if (this.tooltips[id]) {\n if (typeof this.tooltips[id].selector == 'object') {\n this.tooltips[id].selector.remove();\n }\n delete this.tooltips[id];\n }\n // When a tooltip is removed, also remove the reference from the state\n if (!temporary) {\n var state = this.state[this.state_id]['has_tooltip'];\n var label_mark_position = state.indexOf(id);\n state.splice(label_mark_position, 1);\n }\n return this;\n};\n\n/**\n * Loop through and destroy all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.destroyAllTooltips = function() {\n for (var id in this.tooltips) {\n this.destroyTooltip(id, true);\n }\n return this;\n};\n\n//\n/**\n * Position tool tip - naïve function to place a tool tip to the lower right of the current mouse element\n * Most data layers reimplement this method to position tool tips specifically for the data they display\n * @param {String} id The identifier of the tooltip to position\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n // Position the div itself\n this.tooltips[id].selector\n .style('left', (d3.event.pageX) + 'px')\n .style('top', (d3.event.pageY) + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!this.tooltips[id].arrow) {\n this.tooltips[id].arrow = this.tooltips[id].selector.append('div')\n .style('position', 'absolute')\n .attr('class', 'lz-data_layer-tooltip-arrow_top_left');\n }\n this.tooltips[id].arrow\n .style('left', '-1px')\n .style('top', '-1px');\n return this;\n};\n\n/**\n * Loop through and position all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.positionAllTooltips = function() {\n for (var id in this.tooltips) {\n this.positionTooltip(id);\n }\n return this;\n};\n\n/**\n * Show or hide a tool tip by ID depending on directives in the layout and state values relative to the ID\n * @param {String|Object} element The element associated with the tooltip\n * @param {boolean} first_time Because panels can re-render, the rules for showing a tooltip\n * depend on whether this is the first time a status change affecting display has been applied.\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.showOrHideTooltip = function(element, first_time) {\n if (typeof this.layout.tooltip != 'object') { return; }\n var id = this.getElementId(element);\n\n /**\n * Apply rules and decide whether to show or hide the tooltip\n * @param {Object} statuses All statuses that apply to an element\n * @param {String[]|object} directive A layout directive object\n * @param operator\n * @returns {null|bool}\n */\n var resolveStatus = function(statuses, directive, operator) {\n var status = null;\n if (typeof statuses != 'object' || statuses === null) { return null; }\n if (Array.isArray(directive)) {\n // This happens when the function is called on the inner part of the directive\n operator = operator || 'and';\n if (directive.length === 1) {\n status = statuses[directive[0]];\n } else {\n status = directive.reduce(function(previousValue, currentValue) {\n if (operator === 'and') {\n return statuses[previousValue] && statuses[currentValue];\n } else if (operator === 'or') {\n return statuses[previousValue] || statuses[currentValue];\n }\n return null;\n });\n }\n } else if (typeof directive == 'object') {\n var sub_status;\n for (var sub_operator in directive) {\n sub_status = resolveStatus(statuses, directive[sub_operator], sub_operator);\n if (status === null) {\n status = sub_status;\n } else if (operator === 'and') {\n status = status && sub_status;\n } else if (operator === 'or') {\n status = status || sub_status;\n }\n }\n } else {\n return false;\n }\n return status;\n };\n\n var show_directive = {};\n if (typeof this.layout.tooltip.show == 'string') {\n show_directive = { and: [ this.layout.tooltip.show ] };\n } else if (typeof this.layout.tooltip.show == 'object') {\n show_directive = this.layout.tooltip.show;\n }\n\n var hide_directive = {};\n if (typeof this.layout.tooltip.hide == 'string') {\n hide_directive = { and: [ this.layout.tooltip.hide ] };\n } else if (typeof this.layout.tooltip.hide == 'object') {\n hide_directive = this.layout.tooltip.hide;\n }\n\n // Find all the statuses that apply to just this single element\n var layer_state = this.state[this.state_id];\n var statuses = {}; // {status_name: bool}\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function(status) {\n var antistatus = 'un' + status;\n statuses[status] = (layer_state[status].indexOf(id) !== -1);\n statuses[antistatus] = !statuses[status];\n });\n\n // Decide whether to show/hide the tooltip based solely on the underlying element\n var show_resolved = resolveStatus(statuses, show_directive);\n var hide_resolved = resolveStatus(statuses, hide_directive);\n\n // Most of the tooltip display logic depends on behavior layouts: was point (un)selected, (un)highlighted, etc.\n // But sometimes, a point is selected, and the user then closes the tooltip. If the panel is re-rendered for\n // some outside reason (like state change), we must track this in the create/destroy events as tooltip state.\n var has_tooltip = (layer_state['has_tooltip'].indexOf(id) !== -1);\n var tooltip_was_closed = first_time ? false : !has_tooltip;\n if (show_resolved && !tooltip_was_closed && !hide_resolved) {\n this.createTooltip(element);\n } else {\n this.destroyTooltip(element);\n }\n\n return this;\n};\n\n/**\n * Find the elements (or indices) that match any of a set of provided filters\n * @protected\n * @param {Array[]} filters A list of filter entries: [field, value] (for equivalence testing) or\n * [field, operator, value] for other operators\n * @param {('indexes'|'elements')} [return_type='indexes'] Specify whether to return either the indices of the matching\n * elements, or references to the elements themselves\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filter = function(filters, return_type) {\n if (typeof return_type == 'undefined' || ['indexes','elements'].indexOf(return_type) === -1) {\n return_type = 'indexes';\n }\n if (!Array.isArray(filters)) { return []; }\n var test = function(element, filter) {\n var operators = {\n '=': function(a,b) { return a === b; },\n // eslint-disable-next-line eqeqeq\n '!=': function(a,b) { return a != b; }, // For absence of a value, deliberately allow weak comparisons (eg undefined/null)\n '<': function(a,b) { return a < b; },\n '<=': function(a,b) { return a <= b; },\n '>': function(a,b) { return a > b; },\n '>=': function(a,b) { return a >= b; },\n '%': function(a,b) { return a % b; }\n };\n if (!Array.isArray(filter)) { return false; }\n if (filter.length === 2) {\n return element[filter[0]] === filter[1];\n } else if (filter.length === 3 && operators[filter[1]]) {\n return operators[filter[1]](element[filter[0]], filter[2]);\n } else {\n return false;\n }\n };\n var matches = [];\n this.data.forEach(function(element, idx) {\n var match = true;\n filters.forEach(function(filter) {\n if (!test(element, filter)) { match = false; }\n });\n if (match) { matches.push(return_type === 'indexes' ? idx : element); }\n });\n return matches;\n};\n\n/**\n * @param filters\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filterIndexes = function(filters) { return this.filter(filters, 'indexes'); };\n/**\n * @param filters\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filterElements = function(filters) { return this.filter(filters, 'elements'); };\n\nLocusZoom.DataLayer.Statuses.verbs.forEach(function(verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset a single element's status\n // TODO: Improve documentation for dynamically generated methods/properties\n LocusZoom.DataLayer.prototype[verb + 'Element'] = function(element, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n this.setElementStatus(adjective, element, true, exclusive);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'Element'] = function(element, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n this.setElementStatus(adjective, element, false, exclusive);\n return this;\n };\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.DataLayer.prototype[verb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.DataLayer.prototype[antiverb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.DataLayer.prototype[verb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n});\n\n/**\n * Toggle a status (e.g. highlighted, selected, identified) on an element\n * @param {String} status The name of a recognized status to be added/removed on an appropriate element\n * @param {String|Object} element The data bound to the element of interest\n * @param {Boolean} active True to add the status (and associated CSS styles); false to remove it\n * @param {Boolean} exclusive Whether to only allow a state for a single element at a time\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setElementStatus = function(status, element, active, exclusive) {\n if (status === 'has_tooltip') {\n // This is a special adjective that exists solely to track tooltip state. It has no CSS and never gets set\n // directly. It is invisible to the official enums.\n return this;\n }\n\n // Sanity checks\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatus()');\n }\n if (typeof element == 'undefined') {\n throw new Error('Invalid element passed to DataLayer.setElementStatus()');\n }\n if (typeof active == 'undefined') {\n active = true;\n }\n\n // Get an ID for the element or return having changed nothing\n try {\n var element_id = this.getElementId(element);\n } catch (get_element_id_error) {\n return this;\n }\n\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !active);\n }\n\n // Set/unset the proper status class on the appropriate DOM element(s)\n d3.select('#' + element_id).classed('lz-data_layer-' + this.layout.type + '-' + status, active);\n var element_status_node_id = this.getElementStatusNodeId(element);\n if (element_status_node_id !== null) {\n d3.select('#' + element_status_node_id).classed('lz-data_layer-' + this.layout.type + '-statusnode-' + status, active);\n }\n\n // Track element ID in the proper status state array\n var element_status_idx = this.state[this.state_id][status].indexOf(element_id);\n var added_status = (element_status_idx === -1); // On a re-render, existing statuses will be reapplied.\n if (active && added_status) {\n this.state[this.state_id][status].push(element_id);\n }\n if (!active && !added_status) {\n this.state[this.state_id][status].splice(element_status_idx, 1);\n }\n\n // Trigger tool tip show/hide logic\n this.showOrHideTooltip(element, added_status);\n\n // Trigger layout changed event hook\n if (added_status) {\n this.parent.emit('layout_changed', true);\n }\n\n var is_selected = (status === 'selected');\n if (is_selected && (added_status || !active)) {\n // Notify parents that an element has changed selection status (either active, or inactive)\n this.parent.emit('element_selection', { element: element, active: active }, true);\n }\n\n var value_to_broadcast = (this.layout.match && this.layout.match.send);\n if (is_selected && value_to_broadcast && (added_status || !active)) {\n this.parent.emit(\n 'match_requested',\n { value: element[value_to_broadcast], active: active },\n true\n );\n }\n return this;\n};\n\n/**\n * Toggle a status on elements in the data layer based on a set of filters\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setElementStatusByFilters = function(status, toggle, filters, exclusive) {\n\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatusByFilters()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; } else { toggle = !!toggle; }\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n if (!Array.isArray(filters)) { filters = []; }\n\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !toggle);\n }\n\n // Apply statuses\n this.filterElements(filters).forEach(function(element) {\n this.setElementStatus(status, element, toggle);\n }.bind(this));\n\n return this;\n};\n\n/**\n * Toggle a status on all elements in the data layer\n * @param {String} status\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setAllElementStatus = function(status, toggle) {\n\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; }\n\n // Apply statuses\n if (toggle) {\n this.data.forEach(function(element) {\n this.setElementStatus(status, element, true);\n }.bind(this));\n } else {\n var status_ids = this.state[this.state_id][status].slice();\n status_ids.forEach(function(id) {\n var element = this.getElementById(id);\n if (typeof element == 'object' && element !== null) {\n this.setElementStatus(status, element, false);\n }\n }.bind(this));\n this.state[this.state_id][status] = [];\n }\n\n // Update global status flag\n this.global_statuses[status] = toggle;\n\n return this;\n};\n\n/**\n * Apply all layout-defined behaviors (DOM event handlers) to a selection of elements\n * @param {d3.selection} selection\n */\nLocusZoom.DataLayer.prototype.applyBehaviors = function(selection) {\n if (typeof this.layout.behaviors != 'object') { return; }\n Object.keys(this.layout.behaviors).forEach(function(directive) {\n var event_match = /(click|mouseover|mouseout)/.exec(directive);\n if (!event_match) { return; }\n selection.on(event_match[0] + '.' + directive, this.executeBehaviors(directive, this.layout.behaviors[directive]));\n }.bind(this));\n};\n\n/**\n * Generate a function that executes an arbitrary list of behaviors on an element during an event\n * @param {String} directive The name of the event, as described in layout.behaviors for this datalayer\n * @param {Object} behaviors An object describing the behavior to attach to this single element\n * @param {string} behaviors.action The name of the action that would trigger this behavior (eg click, mouseover, etc)\n * @param {string} behaviors.status What status to apply to the element when this behavior is triggered (highlighted,\n * selected, etc)\n * @param {string} [behaviors.exclusive] Whether triggering the event for this element should unset the relevant status\n * for all other elements. Useful for, eg, click events that exclusively highlight one thing.\n * @returns {function(this:LocusZoom.DataLayer)} Return a function that handles the event in context with the behavior\n * and the element- can be attached as an event listener\n */\nLocusZoom.DataLayer.prototype.executeBehaviors = function(directive, behaviors) {\n\n // Determine the required state of control and shift keys during the event\n var requiredKeyStates = {\n 'ctrl': (directive.indexOf('ctrl') !== -1),\n 'shift': (directive.indexOf('shift') !== -1)\n };\n\n return function(element) {\n\n // Do nothing if the required control and shift key presses (or lack thereof) doesn't match the event\n if (requiredKeyStates.ctrl !== !!d3.event.ctrlKey || requiredKeyStates.shift !== !!d3.event.shiftKey) { return; }\n\n // Loop through behaviors making each one go in succession\n behaviors.forEach(function(behavior) {\n\n // Route first by the action, if defined\n if (typeof behavior != 'object' || behavior === null) { return; }\n\n switch (behavior.action) {\n\n // Set a status (set to true regardless of current status, optionally with exclusivity)\n case 'set':\n this.setElementStatus(behavior.status, element, true, behavior.exclusive);\n break;\n\n // Unset a status (set to false regardless of current status, optionally with exclusivity)\n case 'unset':\n this.setElementStatus(behavior.status, element, false, behavior.exclusive);\n break;\n\n // Toggle a status\n case 'toggle':\n var current_status_boolean = (this.state[this.state_id][behavior.status].indexOf(this.getElementId(element)) !== -1);\n var exclusive = behavior.exclusive && !current_status_boolean;\n this.setElementStatus(behavior.status, element, !current_status_boolean, exclusive);\n break;\n\n // Link to a dynamic URL\n case 'link':\n if (typeof behavior.href == 'string') {\n var url = LocusZoom.parseFields(element, behavior.href);\n if (typeof behavior.target == 'string') {\n window.open(url, behavior.target);\n } else {\n window.location.href = url;\n }\n }\n break;\n\n // Action not defined, just return\n default:\n break;\n\n }\n\n return;\n\n }.bind(this));\n\n }.bind(this);\n\n};\n\n/**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\nLocusZoom.DataLayer.prototype.getPageOrigin = function() {\n var panel_origin = this.parent.getPageOrigin();\n return {\n x: panel_origin.x + this.parent.layout.margin.left,\n y: panel_origin.y + this.parent.layout.margin.top\n };\n};\n\n/**\n * Get a data layer's current underlying data in a standard format (e.g. JSON or CSV)\n * @param {('csv'|'tsv'|'json')} format How to export the data\n * @returns {*}\n */\nLocusZoom.DataLayer.prototype.exportData = function(format) {\n var default_format = 'json';\n format = format || default_format;\n format = (typeof format == 'string' ? format.toLowerCase() : default_format);\n if (['json','csv','tsv'].indexOf(format) === -1) { format = default_format; }\n var ret;\n switch (format) {\n case 'json':\n try {\n ret = JSON.stringify(this.data);\n } catch (e) {\n ret = null;\n console.warn('Unable to export JSON data from data layer: ' + this.getBaseId());\n console.error(e);\n }\n break;\n case 'tsv':\n case 'csv':\n try {\n var jsonified = JSON.parse(JSON.stringify(this.data));\n if (typeof jsonified != 'object') {\n ret = jsonified.toString();\n } else if (!Array.isArray(jsonified)) {\n ret = 'Object';\n } else {\n var delimiter = (format === 'tsv') ? '\\t' : ',';\n var header = this.layout.fields.map(function(header) {\n return JSON.stringify(header);\n }).join(delimiter) + '\\n';\n ret = header + jsonified.map(function(record) {\n return this.layout.fields.map(function(field) {\n if (typeof record[field] == 'undefined') {\n return JSON.stringify(null);\n } else if (typeof record[field] == 'object' && record[field] !== null) {\n return Array.isArray(record[field]) ? '\"[Array(' + record[field].length + ')]\"' : '\"[Object]\"';\n } else {\n return JSON.stringify(record[field]);\n }\n }).join(delimiter);\n }.bind(this)).join('\\n');\n }\n } catch (e) {\n ret = null;\n console.error('Unable to export CSV data from data layer: ' + this.getBaseId() + ';', e);\n }\n break;\n }\n return ret;\n};\n\n/**\n * Position the datalayer and all tooltips\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.draw = function() {\n this.svg.container.attr('transform', 'translate(' + this.parent.layout.cliparea.origin.x + ',' + this.parent.layout.cliparea.origin.y + ')');\n this.svg.clipRect\n .attr('width', this.parent.layout.cliparea.width)\n .attr('height', this.parent.layout.cliparea.height);\n this.positionAllTooltips();\n return this;\n};\n\n\n/**\n * Re-Map a data layer to reflect changes in the state of a plot (such as viewing region/ chromosome range)\n * @return {Promise}\n */\nLocusZoom.DataLayer.prototype.reMap = function() {\n this.destroyAllTooltips(); // hack - only non-visible tooltips should be destroyed\n // and then recreated if returning to visibility\n\n // Fetch new data. Datalayers are only given access to the final consolidated data from the chain (not headers or raw payloads)\n var promise = this.parent_plot.lzd.getData(this.state, this.layout.fields);\n promise.then(function(new_data) {\n this.data = new_data.body;\n this.applyDataMethods();\n this.initialized = true;\n }.bind(this));\n\n return promise;\n};\n\n\n/**\n * The central registry of known data layer definitions (which may be stored in separate files due to length)\n * @namespace\n */\nLocusZoom.DataLayers = (function() {\n var obj = {};\n var datalayers = {};\n /**\n * @name LocusZoom.DataLayers.get\n * @param {String} name The name of the datalayer\n * @param {Object} layout The configuration object for this data layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n * @returns {LocusZoom.DataLayer}\n */\n obj.get = function(name, layout, parent) {\n if (!name) {\n return null;\n } else if (datalayers[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for data layer [' + name + ']');\n } else {\n return new datalayers[name](layout, parent);\n }\n } else {\n throw new Error('data layer [' + name + '] not found');\n }\n };\n\n /**\n * @name LocusZoom.DataLayers.set\n * @protected\n * @param {String} name\n * @param {Function} datalayer Constructor for the datalayer\n */\n obj.set = function(name, datalayer) {\n if (datalayer) {\n if (typeof datalayer != 'function') {\n throw new Error('unable to set data layer [' + name + '], argument provided is not a function');\n } else {\n datalayers[name] = datalayer;\n datalayers[name].prototype = new LocusZoom.DataLayer();\n }\n } else {\n delete datalayers[name];\n }\n };\n\n /**\n * Add a new type of datalayer to the registry of known layer types\n * @name LocusZoom.DataLayers.add\n * @param {String} name The name of the data layer to register\n * @param {Function} datalayer\n */\n obj.add = function(name, datalayer) {\n if (datalayers[name]) {\n throw new Error('data layer already exists with name: ' + name);\n } else {\n obj.set(name, datalayer);\n }\n };\n\n /**\n * Register a new datalayer that inherits and extends basic behaviors from a known datalayer\n * @param {String} parent_name The name of the parent data layer whose behavior is to be extended\n * @param {String} name The name of the new datalayer to register\n * @param {Object} [overrides] Object of properties and methods to combine with the prototype of the parent datalayer\n * @returns {Function} The constructor for the new child class\n */\n obj.extend = function(parent_name, name, overrides) {\n // TODO: Consider exposing additional constructor argument, if there is a use case for very granular extension\n overrides = overrides || {};\n\n var parent = datalayers[parent_name];\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered datalayer type');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n // Bypass .set() because we want a layer of inheritance below `DataLayer`\n datalayers[name] = child;\n return child;\n };\n\n /**\n * List the names of all known datalayers\n * @name LocusZoom.DataLayers.list\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(datalayers);\n };\n\n return obj;\n})();\n","'use strict';\n\n/**\n * Create a single continuous 2D track that provides information about each datapoint\n *\n * For example, this can be used to color by membership in a group, alongside information in other panels\n *\n * @class LocusZoom.DataLayers.annotation_track\n * @augments LocusZoom.DataLayer\n * @param {Object} layout\n * @param {Object|String} [layout.color]\n * @param {Array[]} An array of filter entries specifying which points to draw annotations for.\n * See `LocusZoom.DataLayer.filter` for details\n */\nLocusZoom.DataLayers.add('annotation_track', function(layout) {\n // In the future we may add additional options for controlling marker size/ shape, based on user feedback\n this.DefaultLayout = {\n color: '#000000',\n filters: [],\n tooltip_positioning: 'middle', // Allowed values: top, middle, bottom\n hit_area_width: 8,\n };\n\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n if (!Array.isArray(layout.filters)) {\n throw new Error('Annotation track must specify array of filters for selecting points to annotate');\n }\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n this.render = function() {\n var self = this;\n // Only render points that currently satisfy all provided filter conditions.\n var trackData = this.filter(this.layout.filters, 'elements');\n\n // Put the containing visible lines before the one containing hit areas, so that the hit areas will be on top.\n var visible_lines_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-visible_lines');\n if (visible_lines_group.size() === 0) {\n visible_lines_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-visible_lines');\n }\n var selection = visible_lines_group.selectAll('rect.lz-data_layer-' + self.layout.type)\n .data(trackData, function (d) { return d[self.layout.id_field]; });\n\n // Draw rectangles (visual and tooltip positioning)\n selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function (d) { return self.getElementId(d); });\n\n var width = 1;\n selection\n .attr('x', function (d) {return self.parent['x_scale'](d[self.layout.x_axis.field]) - width / 2; })\n .attr('width', width)\n .attr('height', self.parent.layout.height)\n .attr('fill', function(d) { return self.resolveScalableParameter(self.layout.color, d); });\n\n // Remove unused elements\n selection.exit()\n .remove();\n\n var hit_areas_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-hit_areas');\n if (hit_areas_group.size() === 0) {\n hit_areas_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-hit_areas');\n }\n var hit_areas_selection = hit_areas_group.selectAll('rect.lz-data_layer-' + self.layout.type)\n .data(trackData, function (d) { return d[self.layout.id_field]; });\n\n // Add new elements as needed\n hit_areas_selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function (d) { return self.getElementId(d); });\n\n // Update the set of elements to reflect new data\n\n var _getX = function (d, i) { // Helper for position calcs below\n var x_center = self.parent['x_scale'](d[self.layout.x_axis.field]);\n var x_left = x_center - self.layout.hit_area_width / 2;\n if (i >= 1) {\n // This assumes that the data are in sorted order.\n var left_node = trackData[i - 1];\n var left_node_x_center = self.parent['x_scale'](left_node[self.layout.x_axis.field]);\n x_left = Math.max(x_left, (x_center + left_node_x_center) / 2);\n }\n return [x_left, x_center];\n };\n hit_areas_selection\n .attr('height', self.parent.layout.height)\n .attr('opacity', 0)\n .attr('x', function (d, i) {\n var crds = _getX(d,i);\n return crds[0];\n }).attr('width', function (d, i) {\n var crds = _getX(d,i);\n return (crds[1] - crds[0]) + self.layout.hit_area_width / 2;\n });\n\n // Remove unused elements\n hit_areas_selection.exit().remove();\n\n // Set up tooltips and mouse interaction\n this.applyBehaviors(hit_areas_selection);\n };\n\n // Reimplement the positionTooltip() method to be annotation-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var offset = stroke_width / 2;\n var page_origin = this.getPageOrigin();\n\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_center = data_layer_height / 2;\n\n // Tooltip should be horizontally centered above the point to be annotated. (or below if space is limited)\n var offset_right = Math.max((tooltip_box.width / 2) - x_center, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - (tooltip_box.width / 2) - offset_left + offset_right;\n arrow_left = (tooltip_box.width / 2) - (arrow_width) + offset_left - offset_right - offset;\n\n var top_offset = 0;\n switch(this.layout.tooltip_positioning) {\n case 'top':\n arrow_type = 'down';\n break;\n case 'bottom':\n top_offset = data_layer_height;\n arrow_type = 'up';\n break;\n case 'middle':\n default:\n var position = d3.mouse(this.svg.container.node());\n // Position the tooltip so that it does not overlap the mouse pointer\n top_offset = y_center;\n if (position[1] > (data_layer_height / 2)) {\n arrow_type = 'down';\n } else {\n arrow_type = 'up';\n }\n }\n\n if (arrow_type === 'up') {\n top = page_origin.y + top_offset + stroke_width + arrow_width;\n arrow_top = 0 - stroke_width - arrow_width;\n } else if (arrow_type === 'down') {\n top = page_origin.y + top_offset - (tooltip_box.height + stroke_width + arrow_width);\n arrow_top = tooltip_box.height - stroke_width;\n }\n\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n return this;\n});\n","'use strict';\n\n/**\n * Forest Data Layer\n * Implements a standard forest plot. In order to space out points, any layout using this must specify axis ticks\n * and extent in advance.\n *\n * If you are using dynamically fetched data, consider using `category_forest` instead.\n *\n * @class LocusZoom.DataLayers.forest\n */\nLocusZoom.DataLayers.add('forest', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'square',\n color: '#888888',\n fill_opacity: 1,\n y_axis: {\n axis: 2\n },\n id_field: 'id',\n confidence_intervals: {\n start_field: 'ci_start',\n end_field: 'ci_end'\n },\n show_no_significance_line: true\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Reimplement the positionTooltip() method to be forest-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n var offset = Math.sqrt(point_size / Math.PI);\n var left, arrow_type, arrow_left;\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var top, arrow_top;\n if (y_center - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + y_center - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (y_center + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + y_center - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Implement the main render function\n this.render = function() {\n\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n // Generate confidence interval paths if fields are defined\n if (this.layout.confidence_intervals\n && this.layout.fields.indexOf(this.layout.confidence_intervals.start_field) !== -1\n && this.layout.fields.indexOf(this.layout.confidence_intervals.end_field) !== -1) {\n // Generate a selection for all forest plot confidence intervals\n var ci_selection = this.svg.group\n .selectAll('rect.lz-data_layer-forest.lz-data_layer-forest-ci')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n // Create confidence interval rect elements\n ci_selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-forest lz-data_layer-forest-ci')\n .attr('id', function(d) { return this.getElementId(d) + '_ci'; }.bind(this))\n .attr('transform', 'translate(0,' + (isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height) + ')');\n // Apply position and size parameters using transition if necessary\n var ci_transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var ci_width = function(d) {\n return this.parent[x_scale](d[this.layout.confidence_intervals.end_field])\n - this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n }.bind(this);\n var ci_height = 1;\n if (this.canTransition()) {\n ci_selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', ci_transform)\n .attr('width', ci_width).attr('height', ci_height);\n } else {\n ci_selection\n .attr('transform', ci_transform)\n .attr('width', ci_width).attr('height', ci_height);\n }\n // Remove old elements as needed\n ci_selection.exit().remove();\n }\n\n // Generate a selection for all forest plot points\n var points_selection = this.svg.group\n .selectAll('path.lz-data_layer-forest.lz-data_layer-forest-point')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n points_selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-forest lz-data_layer-forest-point')\n .attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .attr('transform', 'translate(0,' + initial_y + ')');\n\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n\n var fill = function(d) { return this.resolveScalableParameter(this.layout.color, d); }.bind(this);\n var fill_opacity = function(d) { return this.resolveScalableParameter(this.layout.fill_opacity, d); }.bind(this);\n\n var shape = d3.svg.symbol()\n .size(function(d) { return this.resolveScalableParameter(this.layout.point_size, d); }.bind(this))\n .type(function(d) { return this.resolveScalableParameter(this.layout.point_shape, d); }.bind(this));\n\n // Apply position and color, using a transition if necessary\n if (this.canTransition()) {\n points_selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n } else {\n points_selection\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n }\n\n // Remove old elements as needed\n points_selection.exit().remove();\n\n // Apply default event emitters to selection\n points_selection.on('click.event_emitter', function(element_data) {\n this.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n\n // Apply behaviors to points\n this.applyBehaviors(points_selection);\n };\n return this;\n\n});\n\n/**\n * A y-aligned forest plot in which the y-axis represents item labels, which are dynamically chosen when data is loaded.\n * Each item is assumed to include both data and confidence intervals.\n * This allows generating forest plots without defining the layout in advance.\n *\n * @class LocusZoom.DataLayers.category_forest\n * @augments LocusZoom.DataLayers.forest\n */\nLocusZoom.DataLayers.extend('forest', 'category_forest', {\n _getDataExtent: function(data, axis_config) {\n // In a forest plot, the data range is determined by *three* fields (beta + CI start/end)\n var ci_config = this.layout.confidence_intervals;\n if (ci_config\n && this.layout.fields.indexOf(ci_config.start_field) !== -1\n && this.layout.fields.indexOf(ci_config.end_field) !== -1) {\n var min = function(d) {\n var f = new LocusZoom.Data.Field(ci_config.start_field);\n return +f.resolve(d);\n };\n\n var max = function(d) {\n var f = new LocusZoom.Data.Field(ci_config.end_field);\n return +f.resolve(d);\n };\n\n return [d3.min(data, min), d3.max(data, max)];\n }\n\n // If there are no confidence intervals set, then range must depend only on a single field\n return LocusZoom.DataLayer.prototype._getDataExtent.call(this, data, axis_config);\n },\n\n getTicks: function(dimension, config) { // Overrides parent method\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier' + dimension);\n }\n\n // Design assumption: one axis (y1 or y2) has the ticks, and the layout says which to use\n // Also assumes that every tick gets assigned a unique matching label\n var axis_num = this.layout.y_axis.axis;\n if (dimension === ('y' + axis_num)) {\n var category_field = this.layout.y_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n\n return this.data.map(function (item, index) {\n return {\n y: index + 1,\n text: item[category_field]\n };\n });\n } else {\n return [];\n }\n },\n\n applyCustomDataMethods: function () {\n // Add a synthetic yaxis field to ensure data is spread out on plot. Then, set axis floor and ceiling to\n // correct extents.\n var field_to_add = this.layout.y_axis.field;\n if (!field_to_add) {\n throw new Error('Layout for ' + this.layout.id + ' must specify yaxis.field');\n }\n\n this.data = this.data.map(function (item, index) {\n item[field_to_add] = index + 1;\n return item;\n });\n // Update axis extents based on one label for every point (with a bit of padding above and below)\n this.layout.y_axis.floor = 0;\n this.layout.y_axis.ceiling = this.data.length + 1;\n return this;\n }\n});\n","'use strict';\n\n/*********************\n * Genes Data Layer\n * Implements a data layer that will render gene tracks\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('genes', function(layout) {\n /**\n * Define a default layout for this DataLayer type and merge it with the passed argument\n * @protected\n * @member {Object}\n * */\n this.DefaultLayout = {\n // Optionally specify different fill and stroke properties\n stroke: 'rgb(54, 54, 150)',\n color: '#363696',\n label_font_size: 12,\n label_exon_spacing: 4,\n exon_height: 16,\n bounding_box_padding: 6,\n track_vertical_spacing: 10\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * Generate a statusnode ID for a given element\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function(element) {\n return this.getElementId(element) + '-statusnode';\n };\n\n /**\n * Helper function to sum layout values to derive total height for a single gene track\n * @returns {number}\n */\n this.getTrackHeight = function() {\n return 2 * this.layout.bounding_box_padding\n + this.layout.label_font_size\n + this.layout.label_exon_spacing\n + this.layout.exon_height\n + this.layout.track_vertical_spacing;\n };\n\n /**\n * A gene may have arbitrarily many transcripts, but this data layer isn't set up to render them yet.\n * Stash a transcript_idx to point to the first transcript and use that for all transcript refs.\n * @member {number}\n * @type {number}\n */\n this.transcript_idx = 0;\n\n /**\n * An internal counter for the number of tracks in the data layer. Used as an internal counter for looping\n * over positions / assignments\n * @protected\n * @member {number}\n */\n this.tracks = 1;\n\n /**\n * Store information about genes in dataset, in a hash indexed by track number: {track_number: [gene_indices]}\n * @member {Object.}\n */\n this.gene_track_index = { 1: [] };\n\n /**\n * Ensure that genes in overlapping chromosome regions are positioned so that parts of different genes do not\n * overlap in the view. A track is a row used to vertically separate overlapping genes.\n * @returns {LocusZoom.DataLayer}\n */\n this.assignTracks = function() {\n /**\n * Function to get the width in pixels of a label given the text and layout attributes\n * TODO: Move to outer scope?\n * @param {String} gene_name\n * @param {number|string} font_size\n * @returns {number}\n */\n this.getLabelWidth = function(gene_name, font_size) {\n try {\n var temp_text = this.svg.group.append('text')\n .attr('x', 0).attr('y', 0).attr('class', 'lz-data_layer-genes lz-label')\n .style('font-size', font_size)\n .text(gene_name + '→');\n var label_width = temp_text.node().getBBox().width;\n temp_text.remove();\n return label_width;\n } catch (e) {\n return 0;\n }\n };\n\n // Reinitialize some metadata\n this.tracks = 1;\n this.gene_track_index = { 1: [] };\n\n this.data.map(function(d, g) {\n\n // If necessary, split combined gene id / version fields into discrete fields.\n // NOTE: this may be an issue with CSG's genes data source that may eventually be solved upstream.\n if (this.data[g].gene_id && this.data[g].gene_id.indexOf('.')) {\n var split = this.data[g].gene_id.split('.');\n this.data[g].gene_id = split[0];\n this.data[g].gene_version = split[1];\n }\n\n // Stash the transcript ID on the parent gene\n this.data[g].transcript_id = this.data[g].transcripts[this.transcript_idx].transcript_id;\n\n // Determine display range start and end, based on minimum allowable gene display width, bounded by what we can see\n // (range: values in terms of pixels on the screen)\n this.data[g].display_range = {\n start: this.parent.x_scale(Math.max(d.start, this.state.start)),\n end: this.parent.x_scale(Math.min(d.end, this.state.end))\n };\n this.data[g].display_range.label_width = this.getLabelWidth(this.data[g].gene_name, this.layout.label_font_size);\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n // Determine label text anchor (default to middle)\n this.data[g].display_range.text_anchor = 'middle';\n if (this.data[g].display_range.width < this.data[g].display_range.label_width) {\n if (d.start < this.state.start) {\n this.data[g].display_range.end = this.data[g].display_range.start\n + this.data[g].display_range.label_width\n + this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'start';\n } else if (d.end > this.state.end) {\n this.data[g].display_range.start = this.data[g].display_range.end\n - this.data[g].display_range.label_width\n - this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n var centered_margin = ((this.data[g].display_range.label_width - this.data[g].display_range.width) / 2)\n + this.layout.label_font_size;\n if ((this.data[g].display_range.start - centered_margin) < this.parent.x_scale(this.state.start)) {\n this.data[g].display_range.start = this.parent.x_scale(this.state.start);\n this.data[g].display_range.end = this.data[g].display_range.start + this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'start';\n } else if ((this.data[g].display_range.end + centered_margin) > this.parent.x_scale(this.state.end)) {\n this.data[g].display_range.end = this.parent.x_scale(this.state.end);\n this.data[g].display_range.start = this.data[g].display_range.end - this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n this.data[g].display_range.start -= centered_margin;\n this.data[g].display_range.end += centered_margin;\n }\n }\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n }\n // Add bounding box padding to the calculated display range start, end, and width\n this.data[g].display_range.start -= this.layout.bounding_box_padding;\n this.data[g].display_range.end += this.layout.bounding_box_padding;\n this.data[g].display_range.width += 2 * this.layout.bounding_box_padding;\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[g].display_domain = {\n start: this.parent.x_scale.invert(this.data[g].display_range.start),\n end: this.parent.x_scale.invert(this.data[g].display_range.end)\n };\n this.data[g].display_domain.width = this.data[g].display_domain.end - this.data[g].display_domain.start;\n\n // Using display range/domain data generated above cast each gene to tracks such that none overlap\n this.data[g].track = null;\n var potential_track = 1;\n while (this.data[g].track === null) {\n var collision_on_potential_track = false;\n this.gene_track_index[potential_track].map(function(placed_gene) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_gene.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_gene.display_range.end, this.display_range.end);\n if ((max_end - min_start) < (placed_gene.display_range.width + this.display_range.width)) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[g]));\n if (!collision_on_potential_track) {\n this.data[g].track = potential_track;\n this.gene_track_index[potential_track].push(this.data[g]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.gene_track_index[potential_track] = [];\n }\n }\n }\n\n // Stash parent references on all genes, trascripts, and exons\n this.data[g].parent = this;\n this.data[g].transcripts.map(function(d, t) {\n this.data[g].transcripts[t].parent = this.data[g];\n this.data[g].transcripts[t].exons.map(function(d, e) {\n this.data[g].transcripts[t].exons[e].parent = this.data[g].transcripts[t];\n }.bind(this));\n }.bind(this));\n\n }.bind(this));\n return this;\n };\n\n /**\n * Main render function\n */\n this.render = function() {\n\n var self = this;\n this.assignTracks();\n\n var width, height, x, y;\n\n // Render gene groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-genes')\n .data(this.data, function(d) { return d.gene_name; });\n\n selection.enter().append('g')\n .attr('class', 'lz-data_layer-genes');\n\n selection.attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .each(function(gene) {\n\n var data_layer = gene.parent;\n\n // Render gene bounding boxes (status nodes to show selected/highlighted)\n var bboxes = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-data_layer-genes-statusnode')\n .data([gene], function(d) { return data_layer.getElementStatusNodeId(d); });\n\n bboxes.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-data_layer-genes-statusnode');\n\n bboxes\n .attr('id', function(d) {\n return data_layer.getElementStatusNodeId(d);\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n bboxes\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n bboxes\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n bboxes.exit().remove();\n\n // Render gene boundaries\n var boundary_fill = function(d) { return self.resolveScalableParameter(self.layout.color, d); };\n var boundary_stroke = function(d) { return self.resolveScalableParameter(self.layout.stroke, d); };\n var boundaries = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-boundary')\n .data([gene], function(d) { return d.gene_name + '_boundary'; })\n .style({ fill: boundary_fill, stroke: boundary_stroke });\n\n boundaries.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-boundary');\n\n width = function(d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function() {\n return 1; // TODO: scale dynamically?\n };\n x = function(d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size\n + data_layer.layout.label_exon_spacing\n + (Math.max(data_layer.layout.exon_height, 3) / 2);\n };\n if (data_layer.canTransition()) {\n boundaries\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n boundaries\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n boundaries.exit().remove();\n\n // Render gene labels\n var labels = d3.select(this).selectAll('text.lz-data_layer-genes.lz-label')\n .data([gene], function(d) { return d.gene_name + '_label'; });\n\n labels.enter().append('text')\n .attr('class', 'lz-data_layer-genes lz-label');\n\n labels\n .attr('text-anchor', function(d) {\n return d.display_range.text_anchor;\n })\n .text(function(d) {\n return (d.strand === '+') ? d.gene_name + '→' : '←' + d.gene_name;\n })\n .style('font-size', gene.parent.layout.label_font_size);\n\n x = function(d) {\n if (d.display_range.text_anchor === 'middle') {\n return d.display_range.start + (d.display_range.width / 2);\n } else if (d.display_range.text_anchor === 'start') {\n return d.display_range.start + data_layer.layout.bounding_box_padding;\n } else if (d.display_range.text_anchor === 'end') {\n return d.display_range.end - data_layer.layout.bounding_box_padding;\n }\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size;\n };\n if (data_layer.canTransition()) {\n labels\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('x', x).attr('y', y);\n } else {\n labels\n .attr('x', x).attr('y', y);\n }\n\n labels.exit().remove();\n\n // Render exon rects (first transcript only, for now)\n // Exons: by default color on gene properties for consistency with the gene boundary track- hence color uses d.parent.parent\n var exon_fill = function(d) { return self.resolveScalableParameter(self.layout.color, d.parent.parent); };\n var exon_stroke = function(d) { return self.resolveScalableParameter(self.layout.stroke, d.parent.parent); };\n\n var exons = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-exon')\n .data(gene.transcripts[gene.parent.transcript_idx].exons, function(d) { return d.exon_id; });\n\n exons.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-exon');\n\n exons\n .style({ fill: exon_fill, stroke: exon_stroke });\n\n width = function(d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function() {\n return data_layer.layout.exon_height;\n };\n x = function(d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function() {\n return ((gene.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size\n + data_layer.layout.label_exon_spacing;\n };\n if (data_layer.canTransition()) {\n exons\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n exons\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n exons.exit().remove();\n\n // Render gene click area\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-clickarea')\n .data([gene], function(d) { return d.gene_name + '_clickarea'; });\n\n clickareas.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-clickarea');\n\n clickareas\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '_clickarea';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n clickareas\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n // Remove old clickareas as needed\n clickareas.exit().remove();\n\n // Apply default event emitters to clickareas\n clickareas.on('click.event_emitter', function(element) {\n element.parent.parent.emit('element_clicked', element, true);\n });\n\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n\n });\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n /**\n * Reimplement the positionTooltip() method to be gene-specific\n * @param {String} id\n */\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var gene_bbox_id = this.getElementStatusNodeId(tooltip.data);\n var gene_bbox = d3.select('#' + gene_bbox_id).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the gene that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var gene_center_x = ((tooltip.data.display_range.start + tooltip.data.display_range.end) / 2) - (this.layout.bounding_box_padding / 2);\n var offset_right = Math.max((tooltip_box.width / 2) - gene_center_x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + gene_center_x - data_layer_width, 0);\n var left = page_origin.x + gene_center_x - (tooltip_box.width / 2) - offset_left + offset_right;\n var arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right;\n // Position vertically below the gene unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (gene_bbox.y + gene_bbox.height)) {\n top = page_origin.y + gene_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + gene_bbox.y + gene_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n return this;\n\n});\n","'use strict';\n\n/*********************\n Genome Legend Data Layer\n Implements a data layer that will render a genome legend\n*/\n\n// Build a custom data layer for a genome legend\nLocusZoom.DataLayers.add('genome_legend', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n chromosome_fill_colors: {\n light: 'rgb(155, 155, 188)',\n dark: 'rgb(95, 95, 128)'\n },\n chromosome_label_colors: {\n light: 'rgb(120, 120, 186)',\n dark: 'rgb(0, 0, 66)'\n }\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Implement the main render function\n this.render = function() {\n\n // Iterate over data to generate genome-wide start/end values for each chromosome\n var position = 0;\n this.data.forEach(function(d, i) {\n this.data[i].genome_start = position;\n this.data[i].genome_end = position + d['genome:base_pairs'];\n position += d['genome:base_pairs'];\n }.bind(this));\n\n var chromosomes = this.svg.group\n .selectAll('rect.lz-data_layer-genome_legend')\n .data(this.data, function(d) { return d['genome:chr']; });\n\n // Create chromosome elements, apply class\n chromosomes.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-genome_legend');\n\n // Position and fill chromosome rects\n var data_layer = this;\n var panel = this.parent;\n\n chromosomes\n .attr('fill', function(d) { return (d['genome:chr'] % 2 ? data_layer.layout.chromosome_fill_colors.light : data_layer.layout.chromosome_fill_colors.dark); })\n .attr('x', function(d) { return panel.x_scale(d.genome_start); })\n .attr('y', 0)\n .attr('width', function(d) { return panel.x_scale(d['genome:base_pairs']); })\n .attr('height', panel.layout.cliparea.height);\n\n // Remove old elements as needed\n chromosomes.exit().remove();\n\n // Parse current state variant into a position\n // Assumes that variant string is of the format 10:123352136_C/T or 10:123352136\n var variant_parts = /([^:]+):(\\d+)(?:_.*)?/.exec(this.state.variant);\n if (!variant_parts) {\n throw new Error('Genome legend cannot understand the specified variant position');\n }\n var chr = variant_parts[1];\n var offset = variant_parts[2];\n // TODO: How does this handle representation of X or Y chromosomes?\n position = +this.data[chr - 1].genome_start + +offset;\n\n // Render the position\n var region = this.svg.group\n .selectAll('rect.lz-data_layer-genome_legend-marker')\n .data([{ start: position, end: position + 1 }]);\n\n region.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-genome_legend-marker');\n\n region\n .transition()\n .duration(500)\n .style({\n 'fill': 'rgba(255, 250, 50, 0.8)',\n 'stroke': 'rgba(255, 250, 50, 0.8)',\n 'stroke-width': '3px'\n })\n .attr('x', function(d) { return panel.x_scale(d.start); })\n .attr('y', 0)\n .attr('width', function(d) { return panel.x_scale(d.end - d.start); })\n .attr('height', panel.layout.cliparea.height);\n\n region.exit().remove();\n\n };\n\n return this;\n\n});\n","'use strict';\n\n/**\n * Intervals Data Layer\n * Implements a data layer that will render interval annotation tracks (intervals must provide start and end values)\n * @class LocusZoom.DataLayers.intervals\n * @augments LocusZoom.DataLayer\n */\nLocusZoom.DataLayers.add('intervals', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n start_field: 'start',\n end_field: 'end',\n track_split_field: 'state_id',\n track_split_order: 'DESC',\n track_split_legend_to_y_axis: 2,\n split_tracks: true,\n track_height: 15,\n track_vertical_spacing: 3,\n bounding_box_padding: 2,\n always_hide_legend: false,\n color: '#B8B8B8',\n fill_opacity: 1\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * To define shared highlighting on the track split field define the status node id override\n * to generate an ID common to the track when we're actively splitting data out to separate tracks\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function(element) {\n if (this.layout.split_tracks) {\n return (this.getBaseId() + '-statusnode-' + element[this.layout.track_split_field]).replace(/[:.[\\],]/g, '_');\n }\n return this.getElementId(element) + '-statusnode';\n }.bind(this);\n\n // Helper function to sum layout values to derive total height for a single interval track\n this.getTrackHeight = function() {\n return this.layout.track_height\n + this.layout.track_vertical_spacing\n + (2 * this.layout.bounding_box_padding);\n };\n\n this.tracks = 1;\n this.previous_tracks = 1;\n\n // track-number-indexed object with arrays of interval indexes in the dataset\n this.interval_track_index = { 1: [] };\n\n // After we've loaded interval data interpret it to assign\n // each to a track so that they do not overlap in the view\n this.assignTracks = function() {\n\n // Reinitialize some metadata\n this.previous_tracks = this.tracks;\n this.tracks = 0;\n this.interval_track_index = { 1: [] };\n this.track_split_field_index = {};\n\n // If splitting tracks by a field's value then do a first pass determine\n // a value/track mapping that preserves the order of possible values\n if (this.layout.track_split_field && this.layout.split_tracks) {\n this.data.map(function(d) {\n this.track_split_field_index[d[this.layout.track_split_field]] = null;\n }.bind(this));\n var index = Object.keys(this.track_split_field_index);\n if (this.layout.track_split_order === 'DESC') { index.reverse(); }\n index.forEach(function(val) {\n this.track_split_field_index[val] = this.tracks + 1;\n this.interval_track_index[this.tracks + 1] = [];\n this.tracks++;\n }.bind(this));\n }\n\n this.data.map(function(d, i) {\n\n // Stash a parent reference on the interval\n this.data[i].parent = this;\n\n // Determine display range start and end, based on minimum allowable interval display width,\n // bounded by what we can see (range: values in terms of pixels on the screen)\n this.data[i].display_range = {\n start: this.parent.x_scale(Math.max(d[this.layout.start_field], this.state.start)),\n end: this.parent.x_scale(Math.min(d[this.layout.end_field], this.state.end))\n };\n this.data[i].display_range.width = this.data[i].display_range.end - this.data[i].display_range.start;\n\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[i].display_domain = {\n start: this.parent.x_scale.invert(this.data[i].display_range.start),\n end: this.parent.x_scale.invert(this.data[i].display_range.end)\n };\n this.data[i].display_domain.width = this.data[i].display_domain.end - this.data[i].display_domain.start;\n\n // If splitting to tracks based on the value of the designated track split field\n // then don't bother with collision detection (intervals will be grouped on tracks\n // solely by the value of track_split_field)\n if (this.layout.track_split_field && this.layout.split_tracks) {\n var val = this.data[i][this.layout.track_split_field];\n this.data[i].track = this.track_split_field_index[val];\n this.interval_track_index[this.data[i].track].push(i);\n } else {\n // If not splitting to tracks based on a field value then do so based on collision\n // detection (as how it's done for genes). Use display range/domain data generated\n // above and cast each interval to tracks such that none overlap\n this.tracks = 1;\n this.data[i].track = null;\n var potential_track = 1;\n while (this.data[i].track === null) {\n var collision_on_potential_track = false;\n this.interval_track_index[potential_track].map(function(placed_interval) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_interval.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_interval.display_range.end, this.display_range.end);\n if ((max_end - min_start) < (placed_interval.display_range.width + this.display_range.width)) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[i]));\n if (!collision_on_potential_track) {\n this.data[i].track = potential_track;\n this.interval_track_index[potential_track].push(this.data[i]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.interval_track_index[potential_track] = [];\n }\n }\n }\n\n }\n\n }.bind(this));\n\n return this;\n };\n\n // Implement the main render function\n this.render = function() {\n\n this.assignTracks();\n\n // Remove any shared highlight nodes and re-render them if we're splitting on tracks\n // At most there will only be dozen or so nodes here (one per track) and each time\n // we render data we may have new tracks, so wiping/redrawing all is reasonable.\n this.svg.group.selectAll('.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-shared').remove();\n Object.keys(this.track_split_field_index).forEach(function(key) {\n // Make a psuedo-element so that we can generate an id for the shared node\n var psuedoElement = {};\n psuedoElement[this.layout.track_split_field] = key;\n // Insert the shared node\n var sharedstatusnode_style = {display: (this.layout.split_tracks ? null : 'none')};\n this.svg.group.insert('rect', ':first-child')\n .attr('id', this.getElementStatusNodeId(psuedoElement))\n .attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-shared')\n .attr('rx', this.layout.bounding_box_padding).attr('ry', this.layout.bounding_box_padding)\n .attr('width', this.parent.layout.cliparea.width)\n .attr('height', this.getTrackHeight() - this.layout.track_vertical_spacing)\n .attr('x', 0)\n .attr('y', (this.track_split_field_index[key] - 1) * this.getTrackHeight())\n .style(sharedstatusnode_style);\n }.bind(this));\n\n var width, height, x, y, fill, fill_opacity;\n\n // Render interval groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-intervals')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n selection.enter().append('g')\n .attr('class', 'lz-data_layer-intervals');\n\n selection.attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .each(function(interval) {\n\n var data_layer = interval.parent;\n\n // Render interval status nodes (displayed behind intervals to show highlight\n // without needing to modify interval display element(s))\n var statusnode_style = {display: (data_layer.layout.split_tracks ? 'none' : null)};\n var statusnodes = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-statusnode-discrete')\n .data([interval], function(d) { return data_layer.getElementId(d) + '-statusnode'; });\n statusnodes.enter().insert('rect', ':first-child')\n .attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-statusnode-discrete');\n statusnodes\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '-statusnode';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .style(statusnode_style);\n width = function(d) {\n return d.display_range.width + (2 * data_layer.layout.bounding_box_padding);\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start - data_layer.layout.bounding_box_padding;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n statusnodes\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n statusnodes\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n statusnodes.exit().remove();\n\n // Render primary interval rects\n var rects = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-interval_rect')\n .data([interval], function(d) { return d[data_layer.layout.id_field] + '_interval_rect'; });\n\n rects.enter().append('rect')\n .attr('class', 'lz-data_layer-intervals lz-interval_rect');\n\n height = data_layer.layout.track_height;\n width = function(d) {\n return d.display_range.width;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding;\n };\n fill = function(d) {\n return data_layer.resolveScalableParameter(data_layer.layout.color, d);\n };\n fill_opacity = function(d) {\n return data_layer.resolveScalableParameter(data_layer.layout.fill_opacity, d);\n };\n\n\n if (data_layer.canTransition()) {\n rects\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height)\n .attr('x', x).attr('y', y)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity);\n } else {\n rects\n .attr('width', width).attr('height', height)\n .attr('x', x).attr('y', y)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity);\n }\n\n rects.exit().remove();\n\n // Render interval click areas\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-clickarea')\n .data([interval], function(d) { return d.interval_name + '_clickarea'; });\n\n clickareas.enter().append('rect')\n .attr('class', 'lz-data_layer-intervals lz-clickarea');\n\n clickareas\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '_clickarea';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n clickareas\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n // Remove old clickareas as needed\n clickareas.exit().remove();\n\n // Apply default event emitters to clickareas\n clickareas.on('click', function(element_data) {\n element_data.parent.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n\n });\n\n // Remove old elements as needed\n selection.exit().remove();\n\n // Update the legend axis if the number of ticks changed\n if (this.previous_tracks !== this.tracks) {\n this.updateSplitTrackAxis();\n }\n\n return this;\n\n };\n\n // Reimplement the positionTooltip() method to be interval-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var interval_bbox = d3.select('#' + this.getElementStatusNodeId(tooltip.data)).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the interval that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var interval_center_x = ((tooltip.data.display_range.start + tooltip.data.display_range.end) / 2) - (this.layout.bounding_box_padding / 2);\n var offset_right = Math.max((tooltip_box.width / 2) - interval_center_x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + interval_center_x - data_layer_width, 0);\n var left = page_origin.x + interval_center_x - (tooltip_box.width / 2) - offset_left + offset_right;\n var arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right;\n // Position vertically below the interval unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (interval_bbox.y + interval_bbox.height)) {\n top = page_origin.y + interval_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + interval_bbox.y + interval_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Redraw split track axis or hide it, and show/hide the legend, as determined\n // by current layout parameters and data\n this.updateSplitTrackAxis = function() {\n var legend_axis = this.layout.track_split_legend_to_y_axis ? 'y' + this.layout.track_split_legend_to_y_axis : false;\n if (this.layout.split_tracks) {\n var tracks = +this.tracks || 0;\n var track_height = +this.layout.track_height || 0;\n var track_spacing = 2 * (+this.layout.bounding_box_padding || 0) + (+this.layout.track_vertical_spacing || 0);\n var target_height = (tracks * track_height) + ((tracks - 1) * track_spacing);\n this.parent.scaleHeightToData(target_height);\n if (legend_axis && this.parent.legend) {\n this.parent.legend.hide();\n this.parent.layout.axes[legend_axis] = {\n render: true,\n ticks: [],\n range: {\n start: (target_height - (this.layout.track_height / 2)),\n end: (this.layout.track_height / 2)\n }\n };\n this.layout.legend.forEach(function(element) {\n var key = element[this.layout.track_split_field];\n var track = this.track_split_field_index[key];\n if (track) {\n if (this.layout.track_split_order === 'DESC') {\n track = Math.abs(track - tracks - 1);\n }\n this.parent.layout.axes[legend_axis].ticks.push({\n y: track,\n text: element.label\n });\n }\n }.bind(this));\n this.layout.y_axis = {\n axis: this.layout.track_split_legend_to_y_axis,\n floor: 1,\n ceiling: tracks\n };\n this.parent.render();\n }\n this.parent_plot.positionPanels();\n } else {\n if (legend_axis && this.parent.legend) {\n if (!this.layout.always_hide_legend) { this.parent.legend.show(); }\n this.parent.layout.axes[legend_axis] = { render: false };\n this.parent.render();\n }\n }\n return this;\n };\n\n // Method to not only toggle the split tracks boolean but also update\n // necessary display values to animate a complete merge/split\n this.toggleSplitTracks = function() {\n this.layout.split_tracks = !this.layout.split_tracks;\n if (this.parent.legend && !this.layout.always_hide_legend) {\n this.parent.layout.margin.bottom = 5 + (this.layout.split_tracks ? 0 : this.parent.legend.layout.height + 5);\n }\n this.render();\n this.updateSplitTrackAxis();\n return this;\n };\n\n return this;\n\n});\n","'use strict';\n\n/*********************\n * Line Data Layer\n * Implements a standard line plot, representing either a trace or a filled curve.\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('line', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n /** @member {Object} */\n this.DefaultLayout = {\n style: {\n fill: 'none',\n 'stroke-width': '2px'\n },\n interpolate: 'linear',\n x_axis: { field: 'x' },\n y_axis: { field: 'y', axis: 1 },\n hitarea_width: 5\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Var for storing mouse events for use in tool tip positioning\n /** @member {String} */\n this.mouse_event = null;\n\n /**\n * Var for storing the generated line function itself\n * @member {d3.svg.line}\n * */\n this.line = null;\n\n /**\n * The timeout identifier returned by setTimeout\n * @member {Number}\n */\n this.tooltip_timeout = null;\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n\n /**\n * Helper function to get display and data objects representing\n * the x/y coordinates of the current mouse event with respect to the line in terms of the display\n * and the interpolated values of the x/y fields with respect to the line\n * @returns {{display: {x: *, y: null}, data: {}, slope: null}}\n */\n this.getMouseDisplayAndData = function() {\n var ret = {\n display: {\n x: d3.mouse(this.mouse_event)[0],\n y: null\n },\n data: {},\n slope: null\n };\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n ret.data[x_field] = this.parent[x_scale].invert(ret.display.x);\n var bisect = d3.bisector(function(datum) { return +datum[x_field]; }).left;\n var index = bisect(this.data, ret.data[x_field]) - 1;\n var startDatum = this.data[index];\n var endDatum = this.data[index + 1];\n var interpolate = d3.interpolateNumber(+startDatum[y_field], +endDatum[y_field]);\n var range = +endDatum[x_field] - +startDatum[x_field];\n ret.data[y_field] = interpolate((ret.data[x_field] % range) / range);\n ret.display.y = this.parent[y_scale](ret.data[y_field]);\n if (this.layout.tooltip.x_precision) {\n ret.data[x_field] = ret.data[x_field].toPrecision(this.layout.tooltip.x_precision);\n }\n if (this.layout.tooltip.y_precision) {\n ret.data[y_field] = ret.data[y_field].toPrecision(this.layout.tooltip.y_precision);\n }\n ret.slope = (this.parent[y_scale](endDatum[y_field]) - this.parent[y_scale](startDatum[y_field]))\n / (this.parent[x_scale](endDatum[x_field]) - this.parent[x_scale](startDatum[x_field]));\n return ret;\n };\n\n /**\n * Reimplement the positionTooltip() method to be line-specific\n * @param {String} id Identify the tooltip to be positioned\n */\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var arrow_width = 7; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var stroke_width = parseFloat(this.layout.style['stroke-width']) || 1;\n var page_origin = this.getPageOrigin();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n var top, left, arrow_top, arrow_left, arrow_type;\n\n // Determine x/y coordinates for display and data\n var dd = this.getMouseDisplayAndData();\n\n // If the absolute value of the slope of the line at this point is above 1 (including Infinity)\n // then position the tool tip left/right. Otherwise position top/bottom.\n if (Math.abs(dd.slope) > 1) {\n\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (dd.display.x <= this.parent.layout.width / 2) {\n left = page_origin.x + dd.display.x + stroke_width + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + dd.display.x - tooltip_box.width - stroke_width - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n if (dd.display.y - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + dd.display.y - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (dd.display.y + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + dd.display.y + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + dd.display.y - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n\n } else {\n\n // Position horizontally: attempt to center on the mouse's x coordinate\n // pad to either side if bumping up against the edge of the data layer\n var offset_right = Math.max((tooltip_box.width / 2) - dd.display.x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + dd.display.x - data_layer_width, 0);\n left = page_origin.x + dd.display.x - (tooltip_box.width / 2) - offset_left + offset_right;\n var min_arrow_left = arrow_width / 2;\n var max_arrow_left = tooltip_box.width - (2.5 * arrow_width);\n arrow_left = (tooltip_box.width / 2) - arrow_width + offset_left - offset_right;\n arrow_left = Math.min(Math.max(arrow_left, min_arrow_left), max_arrow_left);\n\n // Position vertically above the line unless there's insufficient space\n if (tooltip_box.height + stroke_width + arrow_width > dd.display.y) {\n top = page_origin.y + dd.display.y + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n } else {\n top = page_origin.y + dd.display.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n }\n }\n\n // Apply positions to the main div\n tooltip.selector.style({ left: left + 'px', top: top + 'px' });\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style({ 'left': arrow_left + 'px', top: arrow_top + 'px' });\n\n };\n\n /**\n * Implement the main render function\n */\n this.render = function() {\n\n // Several vars needed to be in scope\n var data_layer = this;\n var panel = this.parent;\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n // Join data to the line selection\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-line')\n .data([this.data]);\n\n // Create path element, apply class\n this.path = selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line');\n\n // Generate the line\n if (this.layout.style.fill && this.layout.style.fill !== 'none') {\n // Filled curve: define the line as a filled boundary\n this.line = d3.svg.area()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y0(function(d) {return parseFloat(panel[y_scale](0));})\n .y1(function(d) { return parseFloat(panel[y_scale](d[y_field])); });\n } else {\n // Basic line\n this.line = d3.svg.line()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y(function(d) { return parseFloat(panel[y_scale](d[y_field])); })\n .interpolate(this.layout.interpolate);\n }\n\n // Apply line and style\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('d', this.line)\n .style(this.layout.style);\n } else {\n selection\n .attr('d', this.line)\n .style(this.layout.style);\n }\n\n // Apply tooltip, etc\n if (this.layout.tooltip) {\n // Generate an overlaying transparent \"hit area\" line for more intuitive mouse events\n var hitarea_width = parseFloat(this.layout.hitarea_width).toString() + 'px';\n var hitarea = this.svg.group\n .selectAll('path.lz-data_layer-line-hitarea')\n .data([this.data]);\n hitarea.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line-hitarea')\n .style('stroke-width', hitarea_width);\n var hitarea_line = d3.svg.line()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y(function(d) { return parseFloat(panel[y_scale](d[y_field])); })\n .interpolate(this.layout.interpolate);\n hitarea\n .attr('d', hitarea_line)\n .on('mouseover', function() {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.createTooltip(dd.data);\n })\n .on('mousemove', function() {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.updateTooltip(dd.data);\n data_layer.positionTooltip(data_layer.getElementId());\n })\n .on('mouseout', function() {\n data_layer.tooltip_timeout = setTimeout(function() {\n data_layer.mouse_event = null;\n data_layer.destroyTooltip(data_layer.getElementId());\n }, 300);\n });\n hitarea.exit().remove();\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n /**\n * Redefine setElementStatus family of methods as line data layers will only ever have a single path element\n * @param {String} status A member of `LocusZoom.DataLayer.Statuses.adjectives`\n * @param {String|Object} element\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\n this.setElementStatus = function(status, element, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setElementStatusByFilters = function(status, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setAllElementStatus = function(status, toggle) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; }\n\n // Update global status flag\n this.global_statuses[status] = toggle;\n\n // Apply class to path based on global status flags\n var path_class = 'lz-data_layer-line';\n Object.keys(this.global_statuses).forEach(function(global_status) {\n if (this.global_statuses[global_status]) { path_class += ' lz-data_layer-line-' + global_status; }\n }.bind(this));\n this.path.attr('class', path_class);\n\n // Trigger layout changed event hook\n this.parent.emit('layout_changed', true);\n return this;\n };\n\n return this;\n\n});\n\n\n/***************************\n * Orthogonal Line Data Layer\n * Implements a horizontal or vertical line given an orientation and an offset in the layout\n * Does not require a data source\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('orthogonal_line', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n style: {\n 'stroke': '#D3D3D3',\n 'stroke-width': '3px',\n 'stroke-dasharray': '10px 10px'\n },\n orientation: 'horizontal',\n x_axis: {\n axis: 1,\n decoupled: true\n },\n y_axis: {\n axis: 1,\n decoupled: true\n },\n offset: 0\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Require that orientation be \"horizontal\" or \"vertical\" only\n if (['horizontal','vertical'].indexOf(layout.orientation) === -1) {\n layout.orientation = 'horizontal';\n }\n\n // Vars for storing the data generated line\n /** @member {Array} */\n this.data = [];\n /** @member {d3.svg.line} */\n this.line = null;\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * Implement the main render function\n */\n this.render = function() {\n\n // Several vars needed to be in scope\n var panel = this.parent;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var x_extent = 'x_extent';\n var y_extent = 'y' + this.layout.y_axis.axis + '_extent';\n var x_range = 'x_range';\n\n // Generate data using extents depending on orientation\n if (this.layout.orientation === 'horizontal') {\n this.data = [\n { x: panel[x_extent][0], y: this.layout.offset },\n { x: panel[x_extent][1], y: this.layout.offset }\n ];\n } else if (this.layout.orientation === 'vertical') {\n this.data = [\n { x: this.layout.offset, y: panel[y_extent][0] },\n { x: this.layout.offset, y: panel[y_extent][1] }\n ];\n } else {\n throw new Error('Unrecognized vertical line type. Must be \"vertical\" or \"horizontal\"');\n }\n\n // Join data to the line selection\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-line')\n .data([this.data]);\n\n // Create path element, apply class\n this.path = selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line');\n\n // In some cases, a vertical line may overlay a track that has no inherent y-values (extent)\n // When that happens, provide a default height based on the current panel dimensions (accounting\n // for any resizing that happened after the panel was created)\n var default_y = [panel.layout.cliparea.height, 0];\n\n // Generate the line\n this.line = d3.svg.line()\n .x(function(d, i) {\n var x = parseFloat(panel[x_scale](d['x']));\n return isNaN(x) ? panel[x_range][i] : x;\n })\n .y(function(d, i) {\n var y = parseFloat(panel[y_scale](d['y']));\n return isNaN(y) ? default_y[i] : y;\n })\n .interpolate('linear');\n\n // Apply line and style\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('d', this.line)\n .style(this.layout.style);\n } else {\n selection\n .attr('d', this.line)\n .style(this.layout.style);\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n return this;\n\n});\n","'use strict';\n\n/**\n * Scatter Data Layer\n * Implements a standard scatter plot\n * @class LocusZoom.DataLayers.scatter\n */\nLocusZoom.DataLayers.add('scatter', function(layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'circle',\n tooltip_positioning: 'horizontal',\n color: '#888888',\n fill_opacity: 1,\n y_axis: {\n axis: 1\n },\n id_field: 'id'\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Extra default for layout spacing\n // Not in default layout since that would make the label attribute always present\n if (layout.label && isNaN(layout.label.spacing)) {\n layout.label.spacing = 4;\n }\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Reimplement the positionTooltip() method to be scatter-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var offset = Math.sqrt(point_size / Math.PI);\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n if (this.layout.tooltip_positioning === 'vertical') {\n // Position horizontally centered above the point\n var offset_right = Math.max((tooltip_box.width / 2) - x_center, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - (tooltip_box.width / 2) - offset_left + offset_right;\n arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right - offset;\n // Position vertically above the point unless there's insufficient space, then go below\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (y_center + offset)) {\n top = page_origin.y + y_center - (offset + tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + y_center + offset + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n } else {\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n if (y_center - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + y_center - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (y_center + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + y_center - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Function to flip labels from being anchored at the start of the text to the end\n // Both to keep labels from running outside the data layer and also as a first\n // pass on recursive separation\n this.flip_labels = function() {\n var data_layer = this;\n var point_size = data_layer.resolveScalableParameter(data_layer.layout.point_size, {});\n var spacing = data_layer.layout.label.spacing;\n var handle_lines = Boolean(data_layer.layout.label.lines);\n var min_x = 2 * spacing;\n var max_x = data_layer.parent.layout.width - data_layer.parent.layout.margin.left - data_layer.parent.layout.margin.right - (2 * spacing);\n var flip = function(dn, dnl) {\n var dnx = +dn.attr('x');\n var text_swing = (2 * spacing) + (2 * Math.sqrt(point_size));\n if (handle_lines) {\n var dnlx2 = +dnl.attr('x2');\n var line_swing = spacing + (2 * Math.sqrt(point_size));\n }\n if (dn.style('text-anchor') === 'start') {\n dn.style('text-anchor', 'end');\n dn.attr('x', dnx - text_swing);\n if (handle_lines) { dnl.attr('x2', dnlx2 - line_swing); }\n } else {\n dn.style('text-anchor', 'start');\n dn.attr('x', dnx + text_swing);\n if (handle_lines) { dnl.attr('x2', dnlx2 + line_swing); }\n }\n };\n // Flip any going over the right edge from the right side to the left side\n // (all labels start on the right side)\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n if (dax + abound.width + spacing > max_x) {\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n flip(da, dal);\n }\n });\n // Second pass to flip any others that haven't flipped yet if they collide with another label\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n if (da.style('text-anchor') === 'end') {\n return;\n }\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n data_layer.label_texts.each(function () {\n var b = this;\n var db = d3.select(b);\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + (2 * spacing) &&\n abound.left + abound.width + (2 * spacing) > bbound.left &&\n abound.top < bbound.top + bbound.height + (2 * spacing) &&\n abound.height + abound.top + (2 * spacing) > bbound.top;\n if (collision) {\n flip(da, dal);\n // Double check that this flip didn't push the label past min_x. If it did, immediately flip back.\n dax = +da.attr('x');\n if (dax - abound.width - spacing < min_x) {\n flip(da, dal);\n }\n }\n return;\n });\n });\n };\n\n // Recursive function to space labels apart immediately after initial render\n // Adapted from thudfactor's fiddle here: https://jsfiddle.net/thudfactor/HdwTH/\n // TODO: Make labels also aware of data elements\n this.separate_labels = function() {\n this.seperate_iterations++;\n var data_layer = this;\n var alpha = 0.5;\n if (!this.layout.label) {\n // Guard against layout changing in the midst of iterative rerender\n return;\n }\n var spacing = this.layout.label.spacing;\n var again = false;\n data_layer.label_texts.each(function () {\n var a = this;\n var da = d3.select(a);\n var y1 = da.attr('y');\n data_layer.label_texts.each(function () {\n var b = this;\n // a & b are the same element and don't collide.\n if (a === b) {\n return;\n }\n var db = d3.select(b);\n // a & b are on opposite sides of the chart and\n // don't collide\n if (da.attr('text-anchor') !== db.attr('text-anchor')) {\n return;\n }\n // Determine if the bounding rects for the two text elements collide\n var abound = da.node().getBoundingClientRect();\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + (2 * spacing) &&\n abound.left + abound.width + (2 * spacing) > bbound.left &&\n abound.top < bbound.top + bbound.height + (2 * spacing) &&\n abound.height + abound.top + (2 * spacing) > bbound.top;\n if (!collision) {\n return;\n }\n again = true;\n // If the labels collide, we'll push each\n // of the two labels up and down a little bit.\n var y2 = db.attr('y');\n var sign = abound.top < bbound.top ? 1 : -1;\n var adjust = sign * alpha;\n var new_a_y = +y1 - adjust;\n var new_b_y = +y2 + adjust;\n // Keep new values from extending outside the data layer\n var min_y = 2 * spacing;\n var max_y = data_layer.parent.layout.height - data_layer.parent.layout.margin.top - data_layer.parent.layout.margin.bottom - (2 * spacing);\n var delta;\n if (new_a_y - (abound.height / 2) < min_y) {\n delta = +y1 - new_a_y;\n new_a_y = +y1;\n new_b_y += delta;\n } else if (new_b_y - (bbound.height / 2) < min_y) {\n delta = +y2 - new_b_y;\n new_b_y = +y2;\n new_a_y += delta;\n }\n if (new_a_y + (abound.height / 2) > max_y) {\n delta = new_a_y - +y1;\n new_a_y = +y1;\n new_b_y -= delta;\n } else if (new_b_y + (bbound.height / 2) > max_y) {\n delta = new_b_y - +y2;\n new_b_y = +y2;\n new_a_y -= delta;\n }\n da.attr('y',new_a_y);\n db.attr('y',new_b_y);\n });\n });\n if (again) {\n // Adjust lines to follow the labels\n if (data_layer.layout.label.lines) {\n var label_elements = data_layer.label_texts[0];\n data_layer.label_lines.attr('y2',function(d,i) {\n var label_line = d3.select(label_elements[i]);\n return label_line.attr('y');\n });\n }\n // After ~150 iterations we're probably beyond diminising returns, so stop recursing\n if (this.seperate_iterations < 150) {\n setTimeout(function() {\n this.separate_labels();\n }.bind(this), 1);\n }\n }\n };\n\n // Implement the main render function\n this.render = function() {\n\n var data_layer = this;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n if (this.layout.label) {\n // Apply filters to generate a filtered data set\n var filtered_data = this.data.filter(function(d) {\n if (!data_layer.layout.label.filters) {\n return true;\n } else {\n // Start by assuming a match, run through all filters to test if not a match on any one\n var match = true;\n data_layer.layout.label.filters.forEach(function(filter) {\n var field_value = (new LocusZoom.Data.Field(filter.field)).resolve(d);\n if (['!=', '='].indexOf(filter.operator) === -1 && isNaN(field_value)) {\n // If the filter can only be used with numbers, then the value must be numeric.\n match = false;\n } else {\n switch (filter.operator) {\n case '<':\n if (!(field_value < filter.value)) { match = false; }\n break;\n case '<=':\n if (!(field_value <= filter.value)) { match = false; }\n break;\n case '>':\n if (!(field_value > filter.value)) { match = false; }\n break;\n case '>=':\n if (!(field_value >= filter.value)) { match = false; }\n break;\n case '=':\n if (!(field_value === filter.value)) { match = false; }\n break;\n case '!=':\n // Deliberately allow weak comparisons to test for \"anything with a value present\" (null or undefined)\n // eslint-disable-next-line eqeqeq\n if (field_value == filter.value) { match = false; }\n break;\n default:\n // If we got here the operator is not valid, so the filter should fail\n match = false;\n break;\n }\n }\n });\n return match;\n }\n });\n // Render label groups\n var self = this;\n this.label_groups = this.svg.group\n .selectAll('g.lz-data_layer-' + this.layout.type + '-label')\n .data(filtered_data, function(d) { return d[self.layout.id_field] + '_label'; });\n this.label_groups.enter()\n .append('g')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n // Render label texts\n if (this.label_texts) { this.label_texts.remove(); }\n this.label_texts = this.label_groups.append('text')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_texts\n .text(function(d) {\n return LocusZoom.parseFields(d, data_layer.layout.label.text || '');\n })\n .style(data_layer.layout.label.style || {})\n .attr({\n 'x': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field])\n + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d))\n + data_layer.layout.label.spacing;\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n },\n 'text-anchor': function() {\n return 'start';\n }\n });\n // Render label lines\n if (data_layer.layout.label.lines) {\n if (this.label_lines) { this.label_lines.remove(); }\n this.label_lines = this.label_groups.append('line')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_lines\n .style(data_layer.layout.label.lines.style || {})\n .attr({\n 'x1': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]);\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y1': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n },\n 'x2': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field])\n + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d))\n + (data_layer.layout.label.spacing / 2);\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y2': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n }\n });\n }\n // Remove labels when they're no longer in the filtered data set\n this.label_groups.exit().remove();\n } else {\n // If the layout definition has changed (& no longer specifies labels), strip any previously rendered\n if (this.label_groups) { this.label_groups.remove(); }\n if (this.label_lines) { this.label_lines.remove(); }\n }\n\n // Generate main scatter data elements\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-' + this.layout.type)\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .attr('transform', 'translate(0,' + initial_y + ')');\n\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n\n var fill = function(d) { return this.resolveScalableParameter(this.layout.color, d); }.bind(this);\n var fill_opacity = function(d) { return this.resolveScalableParameter(this.layout.fill_opacity, d); }.bind(this);\n\n var shape = d3.svg.symbol()\n .size(function(d) { return this.resolveScalableParameter(this.layout.point_size, d); }.bind(this))\n .type(function(d) { return this.resolveScalableParameter(this.layout.point_shape, d); }.bind(this));\n\n // Apply position and color, using a transition if necessary\n\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n } else {\n selection\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n // Apply default event emitters to selection\n selection.on('click.event_emitter', function(element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n\n // Apply mouse behaviors\n this.applyBehaviors(selection);\n\n // Apply method to keep labels from overlapping each other\n if (this.layout.label) {\n this.flip_labels();\n this.seperate_iterations = 0;\n this.separate_labels();\n // Apply default event emitters to selection\n this.label_texts.on('click.event_emitter', function(element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n // Extend mouse behaviors to labels\n this.applyBehaviors(this.label_texts);\n }\n\n };\n\n // Method to set a passed element as the LD reference in the plot-level state\n this.makeLDReference = function(element) {\n var ref = null;\n if (typeof element == 'undefined') {\n throw new Error('makeLDReference requires one argument of any type');\n } else if (typeof element == 'object') {\n if (this.layout.id_field && typeof element[this.layout.id_field] != 'undefined') {\n ref = element[this.layout.id_field].toString();\n } else if (typeof element['id'] != 'undefined') {\n ref = element['id'].toString();\n } else {\n ref = element.toString();\n }\n } else {\n ref = element.toString();\n }\n this.parent_plot.applyState({ ldrefvar: ref });\n };\n\n return this;\n\n});\n\n/**\n * A scatter plot in which the x-axis represents categories, rather than individual positions.\n * For example, this can be used by PheWAS plots to show related groups. This plot allows the categories to be\n * determined dynamically when data is first loaded.\n *\n * @class LocusZoom.DataLayers.category_scatter\n * @augments LocusZoom.DataLayers.scatter\n */\nLocusZoom.DataLayers.extend('scatter', 'category_scatter', {\n /**\n * This plot layer makes certain assumptions about the data passed in. Transform the raw array of records from\n * the datasource to prepare it for plotting, as follows:\n * 1. The scatter plot assumes that all records are given in sequence (pre-grouped by `category_field`)\n * 2. It assumes that all records have an x coordinate for individual plotting\n * @private\n */\n _prepareData: function() {\n var xField = this.layout.x_axis.field || 'x';\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n // Sort the data so that things in the same category are adjacent (case-insensitive by specified field)\n var sourceData = this.data\n .sort(function(a, b) {\n var ak = a[category_field];\n var bk = b[category_field];\n var av = (typeof ak === 'string') ? ak.toLowerCase() : ak;\n var bv = (typeof bk === 'string') ? bk.toLowerCase() : bk;\n return (av === bv) ? 0 : (av < bv ? -1 : 1);});\n sourceData.forEach(function(d, i) {\n // Implementation detail: Scatter plot requires specifying an x-axis value, and most datasources do not\n // specify plotting positions. If a point is missing this field, fill in a synthetic value.\n d[xField] = d[xField] || i;\n });\n return sourceData;\n },\n\n /**\n * Identify the unique categories on the plot, and update the layout with an appropriate color scheme.\n * Also identify the min and max x value associated with the category, which will be used to generate ticks\n * @private\n * @returns {Object.} Series of entries used to build category name ticks {category_name: [min_x, max_x]}\n */\n _generateCategoryBounds: function() {\n // TODO: API may return null values in category_field; should we add placeholder category label?\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n var xField = this.layout.x_axis.field || 'x';\n var uniqueCategories = {};\n this.data.forEach(function(item) {\n var category = item[category_field];\n var x = item[xField];\n var bounds = uniqueCategories[category] || [x, x];\n uniqueCategories[category] = [Math.min(bounds[0], x), Math.max(bounds[1], x)];\n });\n\n var categoryNames = Object.keys(uniqueCategories);\n this._setDynamicColorScheme(categoryNames);\n\n return uniqueCategories;\n },\n\n /**\n * This layer relies on defining its own category-based color scheme. Find the correct color config object to\n * be modified.\n * @param [from_source]\n * @returns {Object} A mutable reference to the layout configuration object\n * @private\n */\n _getColorScale: function(from_source) {\n from_source = from_source || this.layout;\n // If the layout does not use a supported coloring scheme, or is already complete, this method should do nothing\n\n // For legacy reasons, layouts can specify color as an object (only one way to set color), as opposed to the\n // preferred mechanism of array (multiple coloring options)\n var color_params = from_source.color || []; // Object or scalar, no other options allowed\n if (Array.isArray(color_params)) {\n color_params = color_params.find(function(item) { return item.scale_function === 'categorical_bin'; });\n }\n if (!color_params || color_params.scale_function !== 'categorical_bin') {\n throw new Error('This layer requires that color options be provided as a `categorical_bin`');\n }\n return color_params;\n },\n\n /**\n * Automatically define a color scheme for the layer based on data returned from the server.\n * If part of the color scheme has been specified, it will fill in remaining missing information.\n *\n * There are three scenarios:\n * 1. The layout does not specify either category names or (color) values. Dynamically build both based on\n * the data and update the layout.\n * 2. The layout specifies colors, but not categories. Use that exact color information provided, and dynamically\n * determine what categories are present in the data. (cycle through the available colors, reusing if there\n * are a lot of categories)\n * 3. The layout specifies exactly what colors and categories to use (and they match the data!). This is useful to\n * specify an explicit mapping between color scheme and category names, when you want to be sure that the\n * plot matches a standard color scheme.\n * (If the layout specifies categories that do not match the data, the user specified categories will be ignored)\n *\n * This method will only act if the layout defines a `categorical_bin` scale function for coloring. It may be\n * overridden in a subclass to suit other types of coloring methods.\n *\n * @param {String[]} categoryNames\n * @private\n */\n _setDynamicColorScheme: function(categoryNames) {\n var colorParams = this._getColorScale(this.layout).parameters;\n var baseParams = this._getColorScale(this._base_layout).parameters;\n\n if (baseParams.categories.length && baseParams.values.length) {\n // If there are preset category/color combos, make sure that they apply to the actual dataset\n var parameters_categories_hash = {};\n baseParams.categories.forEach(function (category) { parameters_categories_hash[category] = 1; });\n if (categoryNames.every(function (name) { return parameters_categories_hash.hasOwnProperty(name); })) {\n // The layout doesn't have to specify categories in order, but make sure they are all there\n colorParams.categories = baseParams.categories;\n } else {\n colorParams.categories = categoryNames;\n }\n } else {\n colorParams.categories = categoryNames;\n }\n // Prefer user-specified colors if provided. Make sure that there are enough colors for all the categories.\n var colors;\n if (baseParams.values.length) {\n colors = baseParams.values;\n } else {\n var color_scale = categoryNames.length <= 10 ? d3.scale.category10 : d3.scale.category20;\n colors = color_scale().range();\n }\n while (colors.length < categoryNames.length) { colors = colors.concat(colors); }\n colors = colors.slice(0, categoryNames.length); // List of hex values, should be of same length as categories array\n colorParams.values = colors;\n },\n\n /**\n *\n * @param dimension\n * @param {Object} [config] Parameters that customize how ticks are calculated (not style)\n * @param {('left'|'center'|'right')} [config.position='left'] Align ticks with the center or edge of category\n * @returns {Array}\n */\n getTicks: function(dimension, config) { // Overrides parent method\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier');\n }\n var position = config.position || 'left';\n if (['left', 'center', 'right'].indexOf(position) === -1) {\n throw new Error('Invalid tick position');\n }\n\n var categoryBounds = this._categories;\n if (!categoryBounds || !Object.keys(categoryBounds).length) {\n return [];\n }\n\n if (dimension === 'y') {\n return [];\n }\n\n if (dimension === 'x') {\n // If colors have been defined by this layer, use them to make tick colors match scatterplot point colors\n var colors = this._getColorScale(this.layout);\n var knownCategories = colors.parameters.categories || [];\n var knownColors = colors.parameters.values || [];\n\n return Object.keys(categoryBounds).map(function (category, index) {\n var bounds = categoryBounds[category];\n var xPos;\n\n switch(position) {\n case 'left':\n xPos = bounds[0];\n break;\n case 'center':\n // Center tick under one or many elements as appropriate\n var diff = bounds[1] - bounds[0];\n xPos = bounds[0] + (diff !== 0 ? diff : bounds[0]) / 2;\n break;\n case 'right':\n xPos = bounds[1];\n break;\n }\n return {\n x: xPos,\n text: category,\n style: {\n 'fill': knownColors[knownCategories.indexOf(category)] || '#000000'\n }\n };\n });\n }\n },\n\n applyCustomDataMethods: function() {\n this.data = this._prepareData();\n /**\n * Define category names and extents (boundaries) for plotting. TODO: properties in constructor\n * @member {Object.} Category names and extents, in the form {category_name: [min_x, max_x]}\n */\n this._categories = this._generateCategoryBounds();\n return this;\n }\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n *\n * LocusZoom has various singleton objects that are used for registering functions or classes.\n * These objects provide safe, standard methods to redefine or delete existing functions/classes\n * as well as define new custom functions/classes to be used in a plot.\n *\n * @namespace Singletons\n */\n\n\n/*\n * The Collection of \"Known\" Data Sources. This registry is used internally by the `DataSources` class\n * @class\n * @static\n */\nLocusZoom.KnownDataSources = (function() {\n /** @lends LocusZoom.KnownDataSources */\n var obj = {};\n /* @member {function[]} */\n var sources = [];\n\n var findSourceByName = function(x) {\n for(var i = 0; i < sources.length; i++) {\n if (!sources[i].SOURCE_NAME) {\n throw new Error('KnownDataSources at position ' + i + \" does not have a 'SOURCE_NAME' static property\");\n }\n if (sources[i].SOURCE_NAME === x) {\n return sources[i];\n }\n }\n return null;\n };\n\n /**\n * Identify the datasource associated with a given name\n * @param {String} name\n * @returns {function} The constructor for the data source; will usually extend `Data.Source`\n */\n obj.get = function(name) {\n return findSourceByName(name);\n };\n\n /**\n * Register a data source constructor so that it may be located by name\n * @param {function} source A constructor function for a data source; will usually extend `Data.Source`,\n * and should have a `SOURCE_NAME` property\n */\n obj.add = function(source) {\n if (!source.SOURCE_NAME) {\n console.warn('Data source added does not have a SOURCE_NAME');\n }\n sources.push(source);\n };\n\n /**\n * Create a custom source type that extends the behavior of an existing source, and registers that\n * source by the provided name\n * @param {String} parent_name The name of a previously registered data source type to use as a template\n * @param {String} source_name The new name to use when registering this data source\n * @param {Object} overrides An object of additional properties and methods to add/override behavior\n * @returns {LocusZoom.Data.Source} The newly defined class for this source\n */\n obj.extend = function(parent_name, source_name, overrides) {\n var parent = findSourceByName(parent_name);\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered data source');\n }\n if (!source_name) {\n throw new Error('Must provide a name for the new data source');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n child.SOURCE_NAME = source_name;\n sources.push(child);\n return child;\n };\n\n /** @deprecated */\n obj.push = function(source) {\n console.warn('Warning: KnownDataSources.push() is deprecated. Use .add() instead');\n obj.add(source);\n };\n\n /**\n * List the names of all registered datasources\n * @returns {String[]}\n */\n obj.list = function() {\n return sources.map(function(x) {return x.SOURCE_NAME;});\n };\n\n /**\n * Create a datasource instance\n * @param {String} name The name of the desired datasource to instantiate (must be defined in the registry)\n * @returns {LocusZoom.Data.Source}\n */\n obj.create = function(name) {\n //create new object (pass additional parameters to constructor)\n var newObj = findSourceByName(name);\n if (newObj) {\n var params = arguments;\n params[0] = null;\n return new (Function.prototype.bind.apply(newObj, params));\n } else {\n throw new Error('Unable to find data source for name: ' + name);\n }\n };\n\n /**\n * Get the array of all registered constructors\n * Generally only used for unit tests internally\n * @private\n * @returns {function[]}\n */\n obj.getAll = function() {\n return sources;\n };\n\n /**\n * Register an entire collection of data sources\n * Generally only used for unit tests internally\n * @private\n * @param {function[]} x An array of datasource constructors\n */\n obj.setAll = function(x) {\n sources = x;\n };\n\n /**\n * Unregister all known data sources\n * Generally only used for unit tests internally\n * @private\n */\n obj.clear = function() {\n sources = [];\n };\n\n return obj;\n})();\n\n/**************************\n * Transformation Functions\n *\n * Singleton for formatting or transforming a single input, for instance turning raw p values into negative log10 form\n * Transformation functions are chainable with a pipe on a field name, like so: \"pvalue|neglog10\"\n *\n * NOTE: Because these functions are chainable the FUNCTION is returned by get(), not the result of that function.\n *\n * All transformation functions must accept an object of parameters and a value to process.\n * @class\n */\nLocusZoom.TransformationFunctions = (function() {\n /** @lends LocusZoom.TransformationFunctions */\n var obj = {};\n var transformations = {};\n\n var getTrans = function(name) {\n if (!name) {\n return null;\n }\n var fun = transformations[name];\n if (fun) {\n return fun;\n } else {\n throw new Error('transformation ' + name + ' not found');\n }\n };\n\n //a single transformation with any parameters\n //(parameters not currently supported)\n var parseTrans = function(name) {\n return getTrans(name);\n };\n\n //a \"raw\" transformation string with a leading pipe\n //and one or more transformations\n var parseTransString = function(x) {\n var funs = [];\n var re = /\\|([^|]+)/g;\n var result;\n while((result = re.exec(x)) !== null) {\n funs.push(result[1]);\n }\n if (funs.length === 1) {\n return parseTrans(funs[0]);\n } else if (funs.length > 1) {\n return function(x) {\n var val = x;\n for(var i = 0; i < funs.length; i++) {\n val = parseTrans(funs[i])(val);\n }\n return val;\n };\n }\n return null;\n };\n\n /**\n * Retrieve a transformation function by name\n * @param {String} name The name of the transformation function to retrieve. May optionally be prefixed with a\n * pipe (`|`) when chaining multiple transformation functions.\n * @returns {function} The constructor for the transformation function\n */\n obj.get = function(name) {\n if (name && name.substring(0,1) === '|') {\n return parseTransString(name);\n } else {\n return parseTrans(name);\n }\n };\n /**\n * Internal logic that registers a transformation function\n * @protected\n * @param {String} name\n * @param {function} fn\n */\n obj.set = function(name, fn) {\n if (name.substring(0,1) === '|') {\n throw new Error('transformation name should not start with a pipe');\n } else {\n if (fn) {\n transformations[name] = fn;\n } else {\n delete transformations[name];\n }\n }\n };\n\n /**\n * Register a transformation function\n * @param {String} name\n * @param {function} fn A transformation function (should accept one argument with the value)\n */\n obj.add = function(name, fn) {\n if (transformations[name]) {\n throw new Error('transformation already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n /**\n * List the names of all registered transformation functions\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(transformations);\n };\n\n return obj;\n})();\n\n/**\n * Return the -log (base 10)\n * @function neglog10\n */\nLocusZoom.TransformationFunctions.add('neglog10', function(x) {\n if (isNaN(x) || x <= 0) { return null; }\n return -Math.log(x) / Math.LN10;\n});\n\n/**\n * Convert a number from logarithm to scientific notation. Useful for, eg, a datasource that returns -log(p) by default\n * @function logtoscinotation\n */\nLocusZoom.TransformationFunctions.add('logtoscinotation', function(x) {\n if (isNaN(x)) { return 'NaN'; }\n if (x === 0) { return '1'; }\n var exp = Math.ceil(x);\n var diff = exp - x;\n var base = Math.pow(10, diff);\n if (exp === 1) {\n return (base / 10).toFixed(4);\n } else if (exp === 2) {\n return (base / 100).toFixed(3);\n } else {\n return base.toFixed(2) + ' × 10^-' + exp;\n }\n});\n\n/**\n * Represent a number in scientific notation\n * @function scinotation\n * @param {Number} x\n * @returns {String}\n */\nLocusZoom.TransformationFunctions.add('scinotation', function(x) {\n if (isNaN(x)) { return 'NaN'; }\n if (x === 0) { return '0'; }\n\n var abs = Math.abs(x);\n var log;\n if (abs > 1) {\n log = Math.ceil(Math.log(abs) / Math.LN10);\n } else { // 0...1\n log = Math.floor(Math.log(abs) / Math.LN10);\n }\n if (Math.abs(log) <= 3) {\n return x.toFixed(3);\n } else {\n return x.toExponential(2).replace('+', '').replace('e', ' × 10^');\n }\n});\n\n/**\n * URL-encode the provided text, eg for constructing hyperlinks\n * @function urlencode\n * @param {String} str\n */\nLocusZoom.TransformationFunctions.add('urlencode', function(str) {\n return encodeURIComponent(str);\n});\n\n/**\n * HTML-escape user entered values for use in constructed HTML fragments\n *\n * For example, this filter can be used on tooltips with custom HTML display\n * @function htmlescape\n * @param {String} str HTML-escape the provided value\n */\nLocusZoom.TransformationFunctions.add('htmlescape', function(str) {\n if ( !str ) {\n return '';\n }\n str = str + '';\n\n return str.replace( /['\"<>&`]/g, function( s ) {\n switch ( s ) {\n case \"'\":\n return ''';\n case '\"':\n return '"';\n case '<':\n return '<';\n case '>':\n return '>';\n case '&':\n return '&';\n case '`':\n return '`';\n }\n });\n});\n\n/**\n * Singleton for accessing/storing functions that will convert arbitrary data points to values in a given scale\n * Useful for anything that needs to scale discretely with data (e.g. color, point size, etc.)\n *\n * A Scale Function can be thought of as a modifier to a layout directive that adds extra logic to how a piece of data\n * can be resolved to a value.\n *\n * All scale functions must accept an object of parameters and a value to process.\n * @class\n * @static\n */\nLocusZoom.ScaleFunctions = (function() {\n /** @lends LocusZoom.ScaleFunctions */\n var obj = {};\n var functions = {};\n\n /**\n * Find a scale function and return it. If parameters and values are passed, calls the function directly; otherwise\n * returns a callable.\n * @param {String} name\n * @param {Object} [parameters] Configuration parameters specific to the specified scale function\n * @param {*} [value] The value to operate on\n * @returns {*}\n */\n obj.get = function(name, parameters, value) {\n if (!name) {\n return null;\n } else if (functions[name]) {\n if (typeof parameters === 'undefined' && typeof value === 'undefined') {\n return functions[name];\n } else {\n return functions[name](parameters, value);\n }\n } else {\n throw new Error('scale function [' + name + '] not found');\n }\n };\n\n /**\n * @protected\n * @param {String} name The name of the function to set/unset\n * @param {Function} [fn] The function to register. If blank, removes this function name from the registry.\n */\n obj.set = function(name, fn) {\n if (fn) {\n functions[name] = fn;\n } else {\n delete functions[name];\n }\n };\n\n /**\n * Add a new scale function to the registry\n * @param {String} name The name of the scale function\n * @param {function} fn A scale function that accepts two parameters: an object of configuration and a value\n */\n obj.add = function(name, fn) {\n if (functions[name]) {\n throw new Error('scale function already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n\n /**\n * List the names of all registered scale functions\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(functions);\n };\n\n return obj;\n})();\n\n/**\n * Basic conditional function to evaluate the value of the input field and return based on equality.\n * @param {Object} parameters\n * @param {*} parameters.field_value The value against which to test the input value.\n * @param {*} parameters.then The value to return if the input value matches the field value\n * @param {*} parameters.else The value to return if the input value does not match the field value. Optional. If not\n * defined this scale function will return null (or value of null_value parameter, if defined) when input value fails\n * to match field_value.\n * @param {*} input value\n */\nLocusZoom.ScaleFunctions.add('if', function(parameters, input) {\n if (typeof input == 'undefined' || parameters.field_value !== input) {\n if (typeof parameters.else != 'undefined') {\n return parameters.else;\n } else {\n return null;\n }\n } else {\n return parameters.then;\n }\n});\n\n/**\n * Function to sort numerical values into bins based on numerical break points. Will only operate on numbers and\n * return null (or value of null_value parameter, if defined) if provided a non-numeric input value. Parameters:\n * @function numerical_bin\n * @param {Object} parameters\n * @param {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter. If the input value is greater than or equal to break n and less than\n * or equal to break n+1 (or break n+1 doesn't exist) then returned value is the nth entry in the values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against break points. Must be of\n * equal length to breaks parameter. Each entry n represents the value to return if the input value is greater than\n * or equal to break n and less than or equal to break n+1 (or break n+1 doesn't exist).\n * @param {*} null_value\n * @param {*} input value\n * @returns\n */\nLocusZoom.ScaleFunctions.add('numerical_bin', function(parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n if (typeof input == 'undefined' || input === null || isNaN(+input)) {\n return (parameters.null_value ? parameters.null_value : null);\n }\n var threshold = breaks.reduce(function(prev, curr) {\n if (+input < prev || (+input >= prev && +input < curr)) {\n return prev;\n } else {\n return curr;\n }\n });\n return values[breaks.indexOf(threshold)];\n});\n\n/**\n * Function to sort values of any type into bins based on direct equality testing with a list of categories.\n * Will return null if provided an input value that does not match to a listed category.\n * @function categorical_bin\n * @param {Object} parameters\n * @param {Array} parameters.categories Array of values against which to evaluate the input value. Must be of equal\n * length to values parameter. If the input value is equal to category n then returned value is the nth entry in the\n * values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against categories. Must be of equal\n * length to categories parameter. Each entry n represents the value to return if the input value is equal to the nth\n * value in the categories parameter.\n * @param {*} parameters.null_value Value to return if the input value fails to match to any categories. Optional.\n */\nLocusZoom.ScaleFunctions.add('categorical_bin', function(parameters, value) {\n if (typeof value == 'undefined' || parameters.categories.indexOf(value) === -1) {\n return (parameters.null_value ? parameters.null_value : null);\n } else {\n return parameters.values[parameters.categories.indexOf(value)];\n }\n});\n\n/**\n * Function for continuous interpolation of numerical values along a gradient with arbitrarily many break points.\n * @function interpolate\n * @parameters {Object} parameters\n * @parameters {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter and contain at least two elements. Input value will be evaluated for\n * relative position between two break points n and n+1 and the returned value will be interpolated at a relative\n * position between values n and n+1.\n * @parameters {*[]} parameters.values Array of values to interpolate and return given evaluations against break\n * points. Must be of equal length to breaks parameter and contain at least two elements. Each entry n represents\n * the value to return if the input value matches the nth entry in breaks exactly. Note that this scale function\n * uses d3.interpolate to provide for effective interpolation of many different value types, including numbers,\n * colors, shapes, etc.\n * @parameters {*} parameters.null_value\n */\nLocusZoom.ScaleFunctions.add('interpolate', function(parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n var nullval = (parameters.null_value ? parameters.null_value : null);\n if (breaks.length < 2 || breaks.length !== values.length) { return nullval; }\n if (typeof input == 'undefined' || input === null || isNaN(+input)) { return nullval; }\n if (+input <= parameters.breaks[0]) {\n return values[0];\n } else if (+input >= parameters.breaks[parameters.breaks.length - 1]) {\n return values[breaks.length - 1];\n } else {\n var upper_idx = null;\n breaks.forEach(function(brk, idx) {\n if (!idx) { return; }\n if (breaks[idx - 1] <= +input && breaks[idx] >= +input) { upper_idx = idx; }\n });\n if (upper_idx === null) { return nullval; }\n var normalized_input = (+input - breaks[upper_idx - 1]) / (breaks[upper_idx] - breaks[upper_idx - 1]);\n if (!isFinite(normalized_input)) { return nullval; }\n return d3.interpolate(values[upper_idx - 1], values[upper_idx])(normalized_input);\n }\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A Dashboard is an HTML element used for presenting arbitrary user interface components. Dashboards are anchored\n * to either the entire Plot or to individual Panels.\n *\n * Each dashboard is an HTML-based (read: not SVG) collection of components used to display information or provide\n * user interface. Dashboards can exist on entire plots, where their visibility is permanent and vertically adjacent\n * to the plot, or on individual panels, where their visibility is tied to a behavior (e.g. a mouseover) and is as\n * an overlay.\n * @class\n */\nLocusZoom.Dashboard = function(parent) {\n // parent must be a locuszoom plot or panel\n if (!(parent instanceof LocusZoom.Plot) && !(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create dashboard, parent must be a locuszoom plot or panel');\n }\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.dashboard';\n /** @member {('plot'|'panel')} */\n this.type = (this.parent instanceof LocusZoom.Plot) ? 'plot' : 'panel';\n /** @member {LocusZoom.Plot} */\n this.parent_plot = this.type === 'plot' ? this.parent : this.parent.parent;\n\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {LocusZoom.Dashboard.Component[]} */\n this.components = [];\n /**\n * The timer identifier as returned by setTimeout\n * @member {Number}\n */\n this.hide_timeout = null;\n /**\n * Whether to hide the dashboard. Can be overridden by a child component. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n\n // TODO: Return value from constructor function?\n return this.initialize();\n};\n\n/**\n * Prepare the dashboard for first use: generate all component instances for this dashboard, based on the provided\n * layout of the parent. Connects event listeners and shows/hides as appropriate.\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.initialize = function() {\n // Parse layout to generate component instances\n if (Array.isArray(this.parent.layout.dashboard.components)) {\n this.parent.layout.dashboard.components.forEach(function(layout) {\n try {\n var component = LocusZoom.Dashboard.Components.get(layout.type, layout, this);\n this.components.push(component);\n } catch (e) {\n console.warn(e);\n }\n }.bind(this));\n }\n\n // Add mouseover event handlers to show/hide panel dashboard\n if (this.type === 'panel') {\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseover.' + this.id, function() {\n clearTimeout(this.hide_timeout);\n if (!this.selector || this.selector.style('visibility') === 'hidden') { this.show(); }\n }.bind(this));\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseout.' + this.id, function() {\n clearTimeout(this.hide_timeout);\n this.hide_timeout = setTimeout(function() { this.hide(); }.bind(this), 300);\n }.bind(this));\n }\n\n return this;\n\n};\n\n/**\n * Whether to persist the dashboard. Returns true if at least one component should persist, or if the panel is engaged\n * in an active drag event.\n * @returns {boolean}\n */\nLocusZoom.Dashboard.prototype.shouldPersist = function() {\n if (this.persist) { return true; }\n var persist = false;\n // Persist if at least one component should also persist\n this.components.forEach(function(component) {\n persist = persist || component.shouldPersist();\n });\n // Persist if in a parent drag event\n persist = persist || (this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.dragging);\n return !!persist;\n};\n\n/**\n * Make the dashboard appear. If it doesn't exist yet create it, including creating/positioning all components within,\n * and make sure it is set to be visible.\n */\nLocusZoom.Dashboard.prototype.show = function() {\n if (!this.selector) {\n switch (this.type) {\n case 'plot':\n this.selector = d3.select(this.parent.svg.node().parentNode)\n .insert('div',':first-child');\n break;\n case 'panel':\n this.selector = d3.select(this.parent.parent.svg.node().parentNode)\n .insert('div', '.lz-data_layer-tooltip, .lz-dashboard-menu, .lz-curtain').classed('lz-panel-dashboard', true);\n break;\n }\n this.selector.classed('lz-dashboard', true).classed('lz-' + this.type + '-dashboard', true).attr('id', this.id);\n }\n this.components.forEach(function(component) { component.show(); });\n this.selector.style({ visibility: 'visible' });\n return this.update();\n};\n\n/**\n * Update the dashboard and rerender all child components. This can be called whenever plot state changes.\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.update = function() {\n if (!this.selector) { return this; }\n this.components.forEach(function(component) { component.update(); });\n return this.position();\n};\n\n/**\n * Position the dashboard (and child components) within the panel\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.position = function() {\n if (!this.selector) { return this; }\n // Position the dashboard itself (panel only)\n if (this.type === 'panel') {\n var page_origin = this.parent.getPageOrigin();\n var top = (page_origin.y + 3.5).toString() + 'px';\n var left = page_origin.x.toString() + 'px';\n var width = (this.parent.layout.width - 4).toString() + 'px';\n this.selector.style({ position: 'absolute', top: top, left: left, width: width });\n }\n // Recursively position components\n this.components.forEach(function(component) { component.position(); });\n return this;\n};\n\n/**\n * Hide the dashboard (make invisible but do not destroy). Will do nothing if `shouldPersist` returns true.\n *\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.hide = function() {\n if (!this.selector || this.shouldPersist()) { return this; }\n this.components.forEach(function(component) { component.hide(); });\n this.selector.style({ visibility: 'hidden' });\n return this;\n};\n\n/**\n * Completely remove dashboard and all child components. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.destroy = function(force) {\n if (typeof force == 'undefined') { force = false; }\n if (!this.selector) { return this; }\n if (this.shouldPersist() && !force) { return this; }\n this.components.forEach(function(component) { component.destroy(true); });\n this.components = [];\n this.selector.remove();\n this.selector = null;\n return this;\n};\n\n/**\n *\n * A dashboard component is an empty div rendered on a dashboard that can display custom\n * html of user interface elements. LocusZoom.Dashboard.Components is a singleton used to\n * define and manage an extendable collection of dashboard components.\n * (e.g. by LocusZoom.Dashboard.Components.add())\n * @class\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @param {('left'|'right')} [layout.position='left'] Whether to float the component left or right.\n * @param {('start'|'middle'|'end')} [layout.group_position] Buttons can optionally be gathered into a visually\n * distinctive group whose elements are closer together. If a button is identified as the start or end of a group,\n * it will be drawn with rounded corners and an extra margin of spacing from any button not part of the group.\n * For example, the region_nav_plot dashboard is a defined as a group.\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple'} [layout.color='gray'] Color scheme for the\n * component. Applies to buttons and menus.\n * @param {LocusZoom.Dashboard} parent The dashboard that contains this component\n*/\nLocusZoom.Dashboard.Component = function(layout, parent) {\n /** @member {Object} */\n this.layout = layout || {};\n if (!this.layout.color) { this.layout.color = 'gray'; }\n\n /** @member {LocusZoom.Dashboard|*} */\n this.parent = parent || null;\n /**\n * Some dashboards are attached to a panel, rather than directly to a plot\n * @member {LocusZoom.Panel|null}\n */\n this.parent_panel = null;\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n /**\n * This is a reference to either the panel or the plot, depending on what the dashboard is\n * tied to. Useful when absolutely positioning dashboard components relative to their SVG anchor.\n * @member {LocusZoom.Plot|LocusZoom.Panel}\n */\n this.parent_svg = null;\n if (this.parent instanceof LocusZoom.Dashboard) {\n // TODO: when is the immediate parent *not* a dashboard?\n if (this.parent.type === 'panel') {\n this.parent_panel = this.parent.parent;\n this.parent_plot = this.parent.parent.parent;\n this.parent_svg = this.parent_panel;\n } else {\n this.parent_plot = this.parent.parent;\n this.parent_svg = this.parent_plot;\n }\n }\n /** @member {d3.selection} */\n this.selector = null;\n /**\n * If this is an interactive component, it will contain a button or menu instance that handles the interactivity.\n * There is a 1-to-1 relationship of dashboard component to button\n * @member {null|LocusZoom.Dashboard.Component.Button}\n */\n this.button = null;\n /**\n * If any single component is marked persistent, it will bubble up to prevent automatic hide behavior on a\n * component's parent dashboard. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n if (!this.layout.position) { this.layout.position = 'left'; }\n\n // TODO: Return value in constructor\n return this;\n};\n/**\n * Perform all rendering of component, including toggling visibility to true. Will initialize and create SVG element\n * if necessary, as well as updating with new data and performing layout actions.\n */\nLocusZoom.Dashboard.Component.prototype.show = function() {\n if (!this.parent || !this.parent.selector) { return; }\n if (!this.selector) {\n var group_position = (['start','middle','end'].indexOf(this.layout.group_position) !== -1 ? ' lz-dashboard-group-' + this.layout.group_position : '');\n this.selector = this.parent.selector.append('div')\n .attr('class', 'lz-dashboard-' + this.layout.position + group_position);\n if (this.layout.style) { this.selector.style(this.layout.style); }\n if (typeof this.initialize == 'function') { this.initialize(); }\n }\n if (this.button && this.button.status === 'highlighted') { this.button.menu.show(); }\n this.selector.style({ visibility: 'visible' });\n this.update();\n return this.position();\n};\n/**\n * Update the dashboard component with any new data or plot state as appropriate. This method performs all\n * necessary rendering steps.\n */\nLocusZoom.Dashboard.Component.prototype.update = function() { /* stub */ };\n/**\n * Place the component correctly in the plot\n * @returns {LocusZoom.Dashboard.Component}\n */\nLocusZoom.Dashboard.Component.prototype.position = function() {\n if (this.button) { this.button.menu.position(); }\n return this;\n};\n/**\n * Determine whether the component should persist (will bubble up to parent dashboard)\n * @returns {boolean}\n */\nLocusZoom.Dashboard.Component.prototype.shouldPersist = function() {\n if (this.persist) { return true; }\n if (this.button && this.button.persist) { return true; }\n return false;\n};\n/**\n * Toggle visibility to hidden, unless marked as persistent\n * @returns {LocusZoom.Dashboard.Component}\n */\nLocusZoom.Dashboard.Component.prototype.hide = function() {\n if (!this.selector || this.shouldPersist()) { return this; }\n if (this.button) { this.button.menu.hide(); }\n this.selector.style({ visibility: 'hidden' });\n return this;\n};\n/**\n * Completely remove component and button. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.Component.prototype.destroy = function(force) {\n if (typeof force == 'undefined') { force = false; }\n if (!this.selector) { return this; }\n if (this.shouldPersist() && !force) { return this; }\n if (this.button && this.button.menu) { this.button.menu.destroy(); }\n this.selector.remove();\n this.selector = null;\n this.button = null;\n return this;\n};\n\n/**\n * Singleton registry of all known components\n * @class\n * @static\n */\nLocusZoom.Dashboard.Components = (function() {\n /** @lends LocusZoom.Dashboard.Components */\n var obj = {};\n var components = {};\n\n /**\n * Create a new component instance by name\n * @param {String} name The string identifier of the desired component\n * @param {Object} layout The layout to use to create the component\n * @param {LocusZoom.Dashboard} parent The containing dashboard to use when creating the component\n * @returns {LocusZoom.Dashboard.Component}\n */\n obj.get = function(name, layout, parent) {\n if (!name) {\n return null;\n } else if (components[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for dashboard component [' + name + ']');\n } else {\n return new components[name](layout, parent);\n }\n } else {\n throw new Error('dashboard component [' + name + '] not found');\n }\n };\n /**\n * Add a new component constructor to the registry and ensure that it extends the correct parent class\n * @protected\n * @param name\n * @param component\n */\n obj.set = function(name, component) {\n if (component) {\n if (typeof component != 'function') {\n throw new Error('unable to set dashboard component [' + name + '], argument provided is not a function');\n } else {\n components[name] = component;\n components[name].prototype = new LocusZoom.Dashboard.Component();\n }\n } else {\n delete components[name];\n }\n };\n\n /**\n * Register a new component constructor by name\n * @param {String} name\n * @param {function} component The component constructor\n */\n obj.add = function(name, component) {\n if (components[name]) {\n throw new Error('dashboard component already exists with name: ' + name);\n } else {\n obj.set(name, component);\n }\n };\n\n /**\n * List the names of all registered components\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(components);\n };\n\n return obj;\n})();\n\n/**\n * Plots and panels may have a \"dashboard\" element suited for showing HTML components that may be interactive.\n * When components need to incorporate a generic button, or additionally a button that generates a menu, this\n * class provides much of the necessary framework.\n * @class\n * @param {LocusZoom.Dashboard.Component} parent\n */\nLocusZoom.Dashboard.Component.Button = function(parent) {\n\n if (!(parent instanceof LocusZoom.Dashboard.Component)) {\n throw new Error('Unable to create dashboard component button, invalid parent');\n }\n /** @member {LocusZoom.Dashboard.Component} */\n this.parent = parent;\n /** @member {LocusZoom.Dashboard.Panel} */\n this.parent_panel = this.parent.parent_panel;\n /** @member {LocusZoom.Dashboard.Plot} */\n this.parent_plot = this.parent.parent_plot;\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent_svg = this.parent.parent_svg;\n\n /** @member {LocusZoom.Dashboard|null|*} */\n this.parent_dashboard = this.parent.parent;\n /** @member {d3.selection} */\n this.selector = null;\n\n /**\n * Tag to use for the button (default: a)\n * @member {String}\n */\n this.tag = 'a';\n\n /**\n * TODO This method does not appear to be used anywhere\n * @param {String} tag\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTag = function(tag) {\n if (typeof tag != 'undefined') { this.tag = tag.toString(); }\n return this;\n };\n\n /**\n * HTML for the button to show.\n * @protected\n * @member {String}\n */\n this.html = '';\n /**\n * Specify the HTML content of this button.\n * WARNING: The string provided will be inserted into the document as raw markup; XSS mitigation is the\n * responsibility of each button implementation.\n * @param {String} html\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setHtml = function(html) {\n if (typeof html != 'undefined') { this.html = html.toString(); }\n return this;\n };\n /**\n * @deprecated since 0.5.6; use setHtml instead\n */\n this.setText = this.setHtml;\n\n /**\n * Mouseover title text for the button to show\n * @protected\n * @member {String}\n */\n this.title = '';\n /**\n * Set the mouseover title text for the button (if any)\n * @param {String} title Simple text to display\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTitle = function(title) {\n if (typeof title != 'undefined') { this.title = title.toString(); }\n return this;\n };\n\n /**\n * Color of the button\n * @member {String}\n */\n this.color = 'gray';\n\n /**\n * Set the color associated with this button\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple')} color Any selection not in the preset list\n * will be replaced with gray.\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setColor = function(color) {\n if (typeof color != 'undefined') {\n if (['gray', 'red', 'orange', 'yellow', 'green', 'blue', 'purple'].indexOf(color) !== -1) { this.color = color; }\n else { this.color = 'gray'; }\n }\n return this;\n };\n\n /**\n * Hash of arbitrary button styles to apply as {name: value} entries\n * @protected\n * @member {Object}\n */\n this.style = {};\n /**\n * Set a collection of custom styles to be used by the button\n * @param {Object} style Hash of {name:value} entries\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setStyle = function(style) {\n if (typeof style != 'undefined') { this.style = style; }\n return this;\n };\n\n //\n /**\n * Method to generate a CSS class string\n * @returns {string}\n */\n this.getClass = function() {\n var group_position = (['start','middle','end'].indexOf(this.parent.layout.group_position) !== -1 ? ' lz-dashboard-button-group-' + this.parent.layout.group_position : '');\n return 'lz-dashboard-button lz-dashboard-button-' + this.color + (this.status ? '-' + this.status : '') + group_position;\n };\n\n // Permanence\n /**\n * Track internal state on whether to keep showing the button/ menu contents at the moment\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n /**\n * Configuration when defining a button: track whether this component should be allowed to keep open\n * menu/button contents in response to certain events\n * @protected\n * @member {Boolean}\n */\n this.permanent = false;\n /**\n * Allow code to change whether the button is allowed to be `permanent`\n * @param {boolean} bool\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setPermanent = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n this.permanent = bool;\n if (this.permanent) { this.persist = true; }\n return this;\n };\n /**\n * Determine whether the button/menu contents should persist in response to a specific event\n * @returns {Boolean}\n */\n this.shouldPersist = function() {\n return this.permanent || this.persist;\n };\n\n /**\n * Button status (highlighted / disabled/ etc)\n * @protected\n * @member {String}\n */\n this.status = '';\n /**\n * Change button state\n * @param {('highlighted'|'disabled'|'')} status\n */\n this.setStatus = function(status) {\n if (typeof status != 'undefined' && ['', 'highlighted', 'disabled'].indexOf(status) !== -1) { this.status = status; }\n return this.update();\n };\n /**\n * Toggle whether the button is highlighted\n * @param {boolean} bool If provided, explicitly set highlighted state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.highlight = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n if (bool) { return this.setStatus('highlighted'); }\n else if (this.status === 'highlighted') { return this.setStatus(''); }\n return this;\n };\n /**\n * Toggle whether the button is disabled\n * @param {boolean} bool If provided, explicitly set disabled state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.disable = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n if (bool) { return this.setStatus('disabled'); }\n else if (this.status === 'disabled') { return this.setStatus(''); }\n return this;\n };\n\n // Mouse events\n /** @member {function} */\n this.onmouseover = function() {};\n this.setOnMouseover = function(onmouseover) {\n if (typeof onmouseover == 'function') { this.onmouseover = onmouseover; }\n else { this.onmouseover = function() {}; }\n return this;\n };\n /** @member {function} */\n this.onmouseout = function() {};\n this.setOnMouseout = function(onmouseout) {\n if (typeof onmouseout == 'function') { this.onmouseout = onmouseout; }\n else { this.onmouseout = function() {}; }\n return this;\n };\n /** @member {function} */\n this.onclick = function() {};\n this.setOnclick = function(onclick) {\n if (typeof onclick == 'function') { this.onclick = onclick; }\n else { this.onclick = function() {}; }\n return this;\n };\n\n // Primary behavior functions\n /**\n * Show the button, including creating DOM elements if necessary for first render\n */\n this.show = function() {\n if (!this.parent) { return; }\n if (!this.selector) {\n this.selector = this.parent.selector.append(this.tag).attr('class', this.getClass());\n }\n return this.update();\n };\n /**\n * Hook for any actions or state cleanup to be performed before rerendering\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.preUpdate = function() { return this; };\n /**\n * Update button state and contents, and fully rerender\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.update = function() {\n if (!this.selector) { return this; }\n this.preUpdate();\n this.selector\n .attr('class', this.getClass())\n .attr('title', this.title).style(this.style)\n .on('mouseover', (this.status === 'disabled') ? null : this.onmouseover)\n .on('mouseout', (this.status === 'disabled') ? null : this.onmouseout)\n .on('click', (this.status === 'disabled') ? null : this.onclick)\n .html(this.html);\n this.menu.update();\n this.postUpdate();\n return this;\n };\n /**\n * Hook for any behavior to be added/changed after the button has been re-rendered\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.postUpdate = function() { return this; };\n /**\n * Hide the button by removing it from the DOM (may be overridden by current persistence setting)\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.hide = function() {\n if (this.selector && !this.shouldPersist()) {\n this.selector.remove();\n this.selector = null;\n }\n return this;\n };\n\n /**\n * Button Menu Object\n * The menu is an HTML overlay that can appear below a button. It can contain arbitrary HTML and\n * has logic to be automatically positioned and sized to behave more or less like a dropdown menu.\n * @member {Object}\n */\n this.menu = {\n outer_selector: null,\n inner_selector: null,\n scroll_position: 0,\n hidden: true,\n /**\n * Show the button menu, including setting up any DOM elements needed for first rendering\n */\n show: function() {\n if (!this.menu.outer_selector) {\n this.menu.outer_selector = d3.select(this.parent_plot.svg.node().parentNode).append('div')\n .attr('class', 'lz-dashboard-menu lz-dashboard-menu-' + this.color)\n .attr('id', this.parent_svg.getBaseId() + '.dashboard.menu');\n this.menu.inner_selector = this.menu.outer_selector.append('div')\n .attr('class', 'lz-dashboard-menu-content');\n this.menu.inner_selector.on('scroll', function() {\n this.menu.scroll_position = this.menu.inner_selector.node().scrollTop;\n }.bind(this));\n }\n this.menu.outer_selector.style({ visibility: 'visible' });\n this.menu.hidden = false;\n return this.menu.update();\n }.bind(this),\n /**\n * Update the rendering of the menu\n */\n update: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.populate(); // This function is stubbed for all buttons by default and custom implemented in component definition\n if (this.menu.inner_selector) { this.menu.inner_selector.node().scrollTop = this.menu.scroll_position; }\n return this.menu.position();\n }.bind(this),\n position: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n // Unset any explicitly defined outer selector height so that menus dynamically shrink if content is removed\n this.menu.outer_selector.style({ height: null });\n var padding = 3;\n var scrollbar_padding = 20;\n var menu_height_padding = 14; // 14: 2x 6px padding, 2x 1px border\n var page_origin = this.parent_svg.getPageOrigin();\n var page_scroll_top = document.documentElement.scrollTop || document.body.scrollTop;\n var container_offset = this.parent_plot.getContainerOffset();\n var dashboard_client_rect = this.parent_dashboard.selector.node().getBoundingClientRect();\n var button_client_rect = this.selector.node().getBoundingClientRect();\n var menu_client_rect = this.menu.outer_selector.node().getBoundingClientRect();\n var total_content_height = this.menu.inner_selector.node().scrollHeight;\n var top = 0; var left = 0;\n if (this.parent_dashboard.type === 'panel') {\n top = (page_origin.y + dashboard_client_rect.height + (2 * padding));\n left = Math.max(page_origin.x + this.parent_svg.layout.width - menu_client_rect.width - padding, page_origin.x + padding);\n } else {\n top = button_client_rect.bottom + page_scroll_top + padding - container_offset.top;\n left = Math.max(button_client_rect.left + button_client_rect.width - menu_client_rect.width - container_offset.left, page_origin.x + padding);\n }\n var base_max_width = Math.max(this.parent_svg.layout.width - (2 * padding) - scrollbar_padding, scrollbar_padding);\n var container_max_width = base_max_width;\n var content_max_width = (base_max_width - (4 * padding));\n var base_max_height = Math.max(this.parent_svg.layout.height - (10 * padding) - menu_height_padding, menu_height_padding);\n var height = Math.min(total_content_height, base_max_height);\n var max_height = base_max_height;\n this.menu.outer_selector.style({\n 'top': top.toString() + 'px',\n 'left': left.toString() + 'px',\n 'max-width': container_max_width.toString() + 'px',\n 'max-height': max_height.toString() + 'px',\n 'height': height.toString() + 'px'\n });\n this.menu.inner_selector.style({ 'max-width': content_max_width.toString() + 'px' });\n this.menu.inner_selector.node().scrollTop = this.menu.scroll_position;\n return this.menu;\n }.bind(this),\n hide: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.outer_selector.style({ visibility: 'hidden' });\n this.menu.hidden = true;\n return this.menu;\n }.bind(this),\n destroy: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.inner_selector.remove();\n this.menu.outer_selector.remove();\n this.menu.inner_selector = null;\n this.menu.outer_selector = null;\n return this.menu;\n }.bind(this),\n /**\n * Internal method definition\n * By convention populate() does nothing and should be reimplemented with each dashboard button definition\n * Reimplement by way of Dashboard.Component.Button.menu.setPopulate to define the populate method and hook\n * up standard menu click-toggle behavior prototype.\n * @protected\n */\n populate: function() { /* stub */ }.bind(this),\n /**\n * Define how the menu is populated with items, and set up click and display properties as appropriate\n * @public\n */\n setPopulate: function(menu_populate_function) {\n if (typeof menu_populate_function == 'function') {\n this.menu.populate = menu_populate_function;\n this.setOnclick(function() {\n if (this.menu.hidden) {\n this.menu.show();\n this.highlight().update();\n this.persist = true;\n } else {\n this.menu.hide();\n this.highlight(false).update();\n if (!this.permanent) { this.persist = false; }\n }\n }.bind(this));\n } else {\n this.setOnclick();\n }\n return this;\n }.bind(this)\n };\n\n};\n\n/**\n * Renders arbitrary text with title formatting\n * @class LocusZoom.Dashboard.Components.title\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.title Text to render\n */\nLocusZoom.Dashboard.Components.add('title', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.show = function() {\n this.div_selector = this.parent.selector.append('div')\n .attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position);\n this.title_selector = this.div_selector.append('h3');\n return this.update();\n };\n this.update = function() {\n var title = layout.title.toString();\n if (this.layout.subtitle) { title += ' ' + this.layout.subtitle + ''; }\n this.title_selector.html(title);\n return this;\n };\n});\n\n/**\n * Renders text to display the current dimensions of the plot. Automatically updated as plot dimensions change\n * @class LocusZoom.Dashboard.Components.dimensions\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('dimensions', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n var display_width = this.parent_plot.layout.width.toString().indexOf('.') === -1 ? this.parent_plot.layout.width : this.parent_plot.layout.width.toFixed(2);\n var display_height = this.parent_plot.layout.height.toString().indexOf('.') === -1 ? this.parent_plot.layout.height : this.parent_plot.layout.height.toFixed(2);\n this.selector.html(display_width + 'px × ' + display_height + 'px');\n if (layout.class) { this.selector.attr('class', layout.class); }\n if (layout.style) { this.selector.style(layout.style); }\n return this;\n };\n});\n\n/**\n * Display the current scale of the genome region displayed in the plot, as defined by the difference between\n * `state.end` and `state.start`.\n * @class LocusZoom.Dashboard.Components.region_scale\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('region_scale', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (!isNaN(this.parent_plot.state.start) && !isNaN(this.parent_plot.state.end)\n && this.parent_plot.state.start !== null && this.parent_plot.state.end !== null) {\n this.selector.style('display', null);\n this.selector.html(LocusZoom.positionIntToString(this.parent_plot.state.end - this.parent_plot.state.start, null, true));\n } else {\n this.selector.style('display', 'none');\n }\n if (layout.class) { this.selector.attr('class', layout.class); }\n if (layout.style) { this.selector.style(layout.style); }\n return this;\n };\n});\n\n/**\n * Button to export current plot to an SVG image\n * @class LocusZoom.Dashboard.Components.download\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Download Image\"]\n * @param {string} [layout.button_title=\"Download image of the current plot as locuszoom.svg\"]\n */\nLocusZoom.Dashboard.Components.add('download', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html || 'Download Image')\n .setTitle(layout.button_title || 'Download image of the current plot as locuszoom.svg')\n .setOnMouseover(function() {\n this.button.selector\n .classed('lz-dashboard-button-gray-disabled', true)\n .html('Preparing Image');\n this.generateBase64SVG().then(function(url) {\n var old = this.button.selector.attr('href');\n if (old) { URL.revokeObjectURL(old); } // Clean up old url instance to prevent memory leaks\n this.button.selector\n .attr('href', url)\n .classed('lz-dashboard-button-gray-disabled', false)\n .classed('lz-dashboard-button-gray-highlighted', true)\n .html(layout.button_html || 'Download Image');\n }.bind(this));\n }.bind(this))\n .setOnMouseout(function() {\n this.button.selector.classed('lz-dashboard-button-gray-highlighted', false);\n }.bind(this));\n this.button.show();\n this.button.selector.attr('href-lang', 'image/svg+xml').attr('download', layout.filename || 'locuszoom.svg');\n return this;\n };\n this.css_string = '';\n for (var stylesheet in Object.keys(document.styleSheets)) {\n if ( document.styleSheets[stylesheet].href !== null\n && document.styleSheets[stylesheet].href.indexOf('locuszoom.css') !== -1) {\n // TODO: \"Download image\" button will render the image incorrectly if the stylesheet has been renamed or concatenated\n LocusZoom.createCORSPromise('GET', document.styleSheets[stylesheet].href)\n .then(function(response) {\n this.css_string = response.replace(/[\\r\\n]/g,' ').replace(/\\s+/g,' ');\n if (this.css_string.indexOf('/* ! LocusZoom HTML Styles */')) {\n this.css_string = this.css_string.substring(0, this.css_string.indexOf('/* ! LocusZoom HTML Styles */'));\n }\n }.bind(this));\n break;\n }\n }\n this.generateBase64SVG = function() {\n return new Promise(function (resolve, reject) {\n // Insert a hidden div, clone the node into that so we can modify it with d3\n var container = this.parent.selector.append('div').style('display', 'none')\n .html(this.parent_plot.svg.node().outerHTML);\n // Remove unnecessary elements\n container.selectAll('g.lz-curtain').remove();\n container.selectAll('g.lz-mouse_guide').remove();\n // Convert units on axis tick dy attributes from ems to pixels\n container.selectAll('g.tick text').each(function() {\n var dy = +(d3.select(this).attr('dy').substring(-2).slice(0,-2)) * 10;\n d3.select(this).attr('dy', dy);\n });\n // Pull the svg into a string and add the contents of the locuszoom stylesheet\n // Don't add this with d3 because it will escape the CDATA declaration incorrectly\n var initial_html = d3.select(container.select('svg').node().parentNode).html();\n var style_def = '';\n var insert_at = initial_html.indexOf('>') + 1;\n initial_html = initial_html.slice(0,insert_at) + style_def + initial_html.slice(insert_at);\n // Delete the container node\n container.remove();\n // Create an object URL based on the rendered markup\n var content = new Blob([initial_html], { type: 'image/svg+xml' });\n resolve(URL.createObjectURL(content));\n }.bind(this));\n };\n});\n\n/**\n * Button to remove panel from plot.\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.remove_panel\n * @augments LocusZoom.Dashboard.Component\n * @param {Boolean} [layout.suppress_confirm=false] If true, removes the panel without prompting user for confirmation\n */\nLocusZoom.Dashboard.Components.add('remove_panel', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('×')\n .setTitle('Remove panel')\n .setOnclick(function() {\n if (!layout.suppress_confirm && !confirm('Are you sure you want to remove this panel? This cannot be undone!')) {\n return false;\n }\n var panel = this.parent_panel;\n panel.dashboard.hide(true);\n d3.select(panel.parent.svg.node().parentNode).on('mouseover.' + panel.getBaseId() + '.dashboard', null);\n d3.select(panel.parent.svg.node().parentNode).on('mouseout.' + panel.getBaseId() + '.dashboard', null);\n return panel.parent.removePanel(panel.id);\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Button to move panel up relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_up\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('move_panel_up', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) {\n var is_at_top = (this.parent_panel.layout.y_index === 0);\n this.button.disable(is_at_top);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('▴')\n .setTitle('Move panel up')\n .setOnclick(function() {\n this.parent_panel.moveUp();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n});\n\n/**\n * Button to move panel down relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_down\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('move_panel_down', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) {\n var is_at_bottom = (this.parent_panel.layout.y_index === this.parent_plot.panel_ids_by_y_index.length - 1);\n this.button.disable(is_at_bottom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('▾')\n .setTitle('Move panel down')\n .setOnclick(function() {\n this.parent_panel.moveDown();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n});\n\n/**\n * Button to shift plot region forwards or back by a `step` increment provided in the layout\n * @class LocusZoom.Dashboard.Components.shift_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=50000] The stepsize to change the region by\n * @param {string} [layout.button_html]\n * @param {string} [layout.button_title]\n */\nLocusZoom.Dashboard.Components.add('shift_region', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function() {};\n console.warn('Unable to add shift_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) { layout.step = 50000; }\n if (typeof layout.button_html !== 'string') { layout.button_html = layout.step > 0 ? '>' : '<'; }\n if (typeof layout.button_title !== 'string') {\n layout.button_title = 'Shift region by ' + (layout.step > 0 ? '+' : '-') + LocusZoom.positionIntToString(Math.abs(layout.step),null,true);\n }\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start + layout.step, 1),\n end: this.parent_plot.state.end + layout.step\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Zoom in or out on the plot, centered on the middle of the plot region, by the specified amount\n * @class LocusZoom.Dashboard.Components.zoom_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=0.2] The amount to zoom in by (where 1 indicates 100%)\n */\nLocusZoom.Dashboard.Components.add('zoom_region', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function() {};\n console.warn('Unable to add zoom_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) { layout.step = 0.2; }\n if (typeof layout.button_html != 'string') { layout.button_html = layout.step > 0 ? 'z–' : 'z+'; }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Zoom region ' + (layout.step > 0 ? 'out' : 'in') + ' by ' + (Math.abs(layout.step) * 100).toFixed(1) + '%';\n }\n this.update = function() {\n if (this.button) {\n var can_zoom = true;\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n if (layout.step > 0 && !isNaN(this.parent_plot.layout.max_region_scale) && current_region_scale >= this.parent_plot.layout.max_region_scale) {\n can_zoom = false;\n }\n if (layout.step < 0 && !isNaN(this.parent_plot.layout.min_region_scale) && current_region_scale <= this.parent_plot.layout.min_region_scale) {\n can_zoom = false;\n }\n this.button.disable(!can_zoom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n var zoom_factor = 1 + layout.step;\n var new_region_scale = current_region_scale * zoom_factor;\n if (!isNaN(this.parent_plot.layout.max_region_scale)) {\n new_region_scale = Math.min(new_region_scale, this.parent_plot.layout.max_region_scale);\n }\n if (!isNaN(this.parent_plot.layout.min_region_scale)) {\n new_region_scale = Math.max(new_region_scale, this.parent_plot.layout.min_region_scale);\n }\n var delta = Math.floor((new_region_scale - current_region_scale) / 2);\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start - delta, 1),\n end: this.parent_plot.state.end + delta\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Renders button with arbitrary text that, when clicked, shows a dropdown containing arbitrary HTML\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @class LocusZoom.Dashboard.Components.menu\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n * @param {string} layout.menu_html The HTML content of the dropdown menu\n */\nLocusZoom.Dashboard.Components.add('menu', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title);\n this.button.menu.setPopulate(function() {\n this.button.menu.inner_selector.html(layout.menu_html);\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Special button/menu to allow model building by tracking individual covariants. Will track a list of covariate\n * objects and store them in the special `model.covariates` field of plot `state`.\n * @class LocusZoom.Dashboard.Components.covariates_model\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n */\nLocusZoom.Dashboard.Components.add('covariates_model', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n this.initialize = function() {\n // Initialize state.model.covariates\n this.parent_plot.state.model = this.parent_plot.state.model || {};\n this.parent_plot.state.model.covariates = this.parent_plot.state.model.covariates || [];\n // Create an object at the plot level for easy access to interface methods in custom client-side JS\n /**\n * When a covariates model dashboard element is present, create (one) object at the plot level that exposes\n * component data and state for custom interactions with other plot elements.\n * @class LocusZoom.Plot.CovariatesModel\n */\n this.parent_plot.CovariatesModel = {\n /** @member {LocusZoom.Dashboard.Component.Button} */\n button: this,\n /**\n * Add an element to the model and show a representation of it in the dashboard component menu. If the\n * element is already part of the model, do nothing (to avoid adding duplicates).\n * When plot state is changed, this will automatically trigger requests for new data accordingly.\n * @param {string|object} element_reference Can be any value that can be put through JSON.stringify()\n * to create a serialized representation of itself.\n */\n add: function(element_reference) {\n var element = JSON.parse(JSON.stringify(element_reference));\n if (typeof element_reference == 'object' && typeof element.html != 'string') {\n element.html = ( (typeof element_reference.toHTML == 'function') ? element_reference.toHTML() : element_reference.toString());\n }\n // Check if the element is already in the model covariates array and return if it is.\n for (var i = 0; i < this.state.model.covariates.length; i++) {\n if (JSON.stringify(this.state.model.covariates[i]) === JSON.stringify(element)) {\n return this;\n }\n }\n this.state.model.covariates.push(element);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Remove an element from `state.model.covariates` (and from the dashboard component menu's\n * representation of the state model). When plot state is changed, this will automatically trigger\n * requests for new data accordingly.\n * @param {number} idx Array index of the element, in the `state.model.covariates array`.\n */\n removeByIdx: function(idx) {\n if (typeof this.state.model.covariates[idx] == 'undefined') {\n throw new Error('Unable to remove model covariate, invalid index: ' + idx.toString());\n }\n this.state.model.covariates.splice(idx, 1);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Empty the `state.model.covariates` array (and dashboard component menu representation thereof) of all\n * elements. When plot state is changed, this will automatically trigger requests for new data accordingly\n */\n removeAll: function() {\n this.state.model.covariates = [];\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Manually trigger the update methods on the dashboard component's button and menu elements to force\n * display of most up-to-date content. Can be used to force the dashboard to reflect changes made, eg if\n * modifying `state.model.covariates` directly instead of via `plot.CovariatesModel`\n */\n updateComponent: function() {\n this.button.update();\n this.button.menu.update();\n }.bind(this)\n };\n }.bind(this);\n\n this.update = function() {\n\n if (this.button) { return this; }\n\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.button.menu.populate();\n }.bind(this));\n\n this.button.menu.setPopulate(function() {\n var selector = this.button.menu.inner_selector;\n selector.html('');\n // General model HTML representation\n if (typeof this.parent_plot.state.model.html != 'undefined') {\n selector.append('div').html(this.parent_plot.state.model.html);\n }\n // Model covariates table\n if (!this.parent_plot.state.model.covariates.length) {\n selector.append('i').html('no covariates in model');\n } else {\n selector.append('h5').html('Model Covariates (' + this.parent_plot.state.model.covariates.length + ')');\n var table = selector.append('table');\n this.parent_plot.state.model.covariates.forEach(function(covariate, idx) {\n var html = ( (typeof covariate == 'object' && typeof covariate.html == 'string') ? covariate.html : covariate.toString() );\n var row = table.append('tr');\n row.append('td').append('button')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color)\n .style({ 'margin-left': '0em' })\n .on('click', function() {\n this.parent_plot.CovariatesModel.removeByIdx(idx);\n }.bind(this))\n .html('×');\n row.append('td').html(html);\n }.bind(this));\n selector.append('button')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color)\n .style({ 'margin-left': '4px' }).html('× Remove All Covariates')\n .on('click', function() {\n this.parent_plot.CovariatesModel.removeAll();\n }.bind(this));\n }\n }.bind(this));\n\n this.button.preUpdate = function() {\n var html = 'Model';\n if (this.parent_plot.state.model.covariates.length) {\n var cov = this.parent_plot.state.model.covariates.length > 1 ? 'covariates' : 'covariate';\n html += ' (' + this.parent_plot.state.model.covariates.length + ' ' + cov + ')';\n }\n this.button.setHtml(html).disable(false);\n }.bind(this);\n\n this.button.show();\n\n return this;\n };\n});\n\n/**\n * Button to toggle split tracks\n * @class LocusZoom.Dashboard.Components.toggle_split_tracks\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('toggle_split_tracks', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (!layout.data_layer_id) { layout.data_layer_id = 'intervals'; }\n if (!this.parent_panel.data_layers[layout.data_layer_id]) {\n throw new Error('Dashboard toggle split tracks component missing valid data layer ID');\n }\n this.update = function() {\n var data_layer = this.parent_panel.data_layers[layout.data_layer_id];\n var html = data_layer.layout.split_tracks ? 'Merge Tracks' : 'Split Tracks';\n if (this.button) {\n this.button.setHtml(html);\n this.button.show();\n this.parent.position();\n return this;\n } else {\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(html)\n .setTitle('Toggle whether tracks are split apart or merged together')\n .setOnclick(function() {\n data_layer.toggleSplitTracks();\n if (this.scale_timeout) { clearTimeout(this.scale_timeout); }\n var timeout = data_layer.layout.transition ? +data_layer.layout.transition.duration || 0 : 0;\n this.scale_timeout = setTimeout(function() {\n this.parent_panel.scaleHeightToData();\n this.parent_plot.positionPanels();\n }.bind(this), timeout);\n this.update();\n }.bind(this));\n return this.update();\n }\n };\n});\n\n/**\n * Button to resize panel height to fit available data (eg when showing a list of tracks)\n * @class LocusZoom.Dashboard.Components.resize_to_data\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Resize to Data\"]\n * @param {string} [layout.button_title]\n */\nLocusZoom.Dashboard.Components.add('resize_to_data', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html || 'Resize to Data')\n .setTitle(layout.button_title || 'Automatically resize this panel to show all data available')\n .setOnclick(function() {\n this.parent_panel.scaleHeightToData();\n this.update();\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Button to toggle legend\n * @class LocusZoom.Dashboard.Components.toggle_legend\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('toggle_legend', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n var html = this.parent_panel.legend.layout.hidden ? 'Show Legend' : 'Hide Legend';\n if (this.button) {\n this.button.setHtml(html).show();\n this.parent.position();\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setTitle('Show or hide the legend for this panel')\n .setOnclick(function() {\n this.parent_panel.legend.layout.hidden = !this.parent_panel.legend.layout.hidden;\n this.parent_panel.legend.render();\n this.update();\n }.bind(this));\n return this.update();\n };\n});\n\n/**\n * Menu for manipulating multiple data layers in a single panel: show/hide, change order, etc.\n * @class LocusZoom.Dashboard.Components.data_layers\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('data_layers', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n this.update = function() {\n\n if (typeof layout.button_html != 'string') { layout.button_html = 'Data Layers'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Manipulate Data Layers (sort, dim, show/hide, etc.)'; }\n\n if (this.button) { return this; }\n\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.button.menu.populate();\n }.bind(this));\n\n this.button.menu.setPopulate(function() {\n this.button.menu.inner_selector.html('');\n var table = this.button.menu.inner_selector.append('table');\n this.parent_panel.data_layer_ids_by_z_index.slice().reverse().forEach(function(id, idx) {\n var data_layer = this.parent_panel.data_layers[id];\n var name = (typeof data_layer.layout.name != 'string') ? data_layer.id : data_layer.layout.name;\n var row = table.append('tr');\n // Layer name\n row.append('td').html(name);\n // Status toggle buttons\n layout.statuses.forEach(function(status_adj) {\n var status_idx = LocusZoom.DataLayer.Statuses.adjectives.indexOf(status_adj);\n var status_verb = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n var html, onclick, highlight;\n if (data_layer.global_statuses[status_adj]) {\n html = LocusZoom.DataLayer.Statuses.menu_antiverbs[status_idx];\n onclick = 'un' + status_verb + 'AllElements';\n highlight = '-highlighted';\n } else {\n html = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n onclick = status_verb + 'AllElements';\n highlight = '';\n }\n row.append('td').append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color + highlight)\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer[onclick](); this.button.menu.populate(); }.bind(this))\n .html(html);\n }.bind(this));\n // Sort layer buttons\n var at_top = (idx === 0);\n var at_bottom = (idx === (this.parent_panel.data_layer_ids_by_z_index.length - 1));\n var td = row.append('td');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-start lz-dashboard-button-' + this.layout.color + (at_bottom ? '-disabled' : ''))\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer.moveDown(); this.button.menu.populate(); }.bind(this))\n .html('▾').attr('title', 'Move layer down (further back)');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-middle lz-dashboard-button-' + this.layout.color + (at_top ? '-disabled' : ''))\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer.moveUp(); this.button.menu.populate(); }.bind(this))\n .html('▴').attr('title', 'Move layer up (further front)');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-end lz-dashboard-button-red')\n .style({ 'margin-left': '0em' })\n .on('click', function() {\n if (confirm('Are you sure you want to remove the ' + name + ' layer? This cannot be undone!')) {\n data_layer.parent.removeDataLayer(id);\n }\n return this.button.menu.populate();\n }.bind(this))\n .html('×').attr('title', 'Remove layer');\n }.bind(this));\n return this;\n }.bind(this));\n\n this.button.show();\n\n return this;\n };\n});\n\n/**\n * Dropdown menu allowing the user to choose between different display options for a single specific data layer\n * within a panel.\n *\n * This allows controlling how points on a datalayer can be displayed- any display options supported via the layout for the target datalayer. This includes point\n * size/shape, coloring, etc.\n *\n * This button intentionally limits display options it can control to those available on common plot types.\n * Although the list of options it sets can be overridden (to control very special custom plot types), this\n * capability should be used sparingly if at all.\n *\n * @class LocusZoom.Dashboard.Components.display_options\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Display options...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Control how plot items are displayed\"] Hover text for the toolbar button\n * @param {string} layout.layer_name Specify the datalayer that this button should affect\n * @param {string} [layout.default_config_display_name] Store the default configuration for this datalayer\n * configuration, and show a button to revert to the \"default\" (listing the human-readable display name provided)\n * @param {Array} [layout.fields_whitelist='see code'] The list of presentation fields that this button can control.\n * This can be overridden if this button needs to be used on a custom layer type with special options.\n * @typedef {{display_name: string, display: Object}} DisplayOptionsButtonConfigField\n * @param {DisplayOptionsButtonConfigField[]} layout.options Specify a label and set of layout directives associated\n * with this `display` option. Display field should include all changes to datalayer presentation options.\n */\nLocusZoom.Dashboard.Components.add('display_options', function (layout) {\n if (typeof layout.button_html != 'string') { layout.button_html = 'Display options...'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Control how plot items are displayed'; }\n\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n // List of layout fields that this button is allowed to control. This ensures that we don't override any other\n // information (like plot height etc) while changing point rendering\n var allowed_fields = layout.fields_whitelist || ['color', 'fill_opacity', 'label', 'legend',\n 'point_shape', 'point_size', 'tooltip', 'tooltip_positioning'];\n\n var dataLayer = this.parent_panel.data_layers[layout.layer_name];\n if (!dataLayer) {\n throw new Error(\"Display options could not locate the specified layer_name: '\" + layout.layer_name + \"'\");\n }\n var dataLayerLayout = dataLayer.layout;\n\n // Store default configuration for the layer as a clean deep copy, so we may revert later\n var defaultConfig = {};\n allowed_fields.forEach(function(name) {\n var configSlot = dataLayerLayout[name];\n if (configSlot !== undefined) {\n defaultConfig[name] = JSON.parse(JSON.stringify(configSlot));\n }\n });\n\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n this._selected_item = 'default';\n\n // Define the button + menu that provides the real functionality for this dashboard component\n var self = this;\n this.button = new LocusZoom.Dashboard.Component.Button(self)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 1e4).toString();\n\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n\n var menuLayout = self.layout;\n\n var renderRow = function(display_name, display_options, row_id) { // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td')\n .append('input')\n .attr({id: radioId, type: 'radio', name: 'display-option-' + uniqueID, value: row_id})\n .style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n .property('checked', (row_id === self._selected_item))\n .on('click', function () {\n // If an option is not specified in these display options, use the original defaults\n allowed_fields.forEach(function(field_name) {\n dataLayer.layout[field_name] = display_options[field_name] || defaultConfig[field_name];\n });\n\n self._selected_item = row_id;\n self.parent_panel.render();\n var legend = self.parent_panel.legend;\n if (legend) {\n legend.render();\n }\n });\n row.append('td').append('label')\n .style('font-weight', 'normal')\n .attr('for', radioId)\n .text(display_name);\n };\n // Render the \"display options\" menu: default and special custom options\n var defaultName = menuLayout.default_config_display_name || 'Default style';\n renderRow(defaultName, defaultConfig, 'default');\n menuLayout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.display, index);\n });\n return self;\n });\n\n this.update = function () {\n this.button.show();\n return this;\n };\n});\n\n\n/**\n * Dropdown menu allowing the user to set the value of a specific `state_field` in plot.state\n * This is useful for things (like datasources) that allow dynamic configuration based on global information in state\n *\n * For example, the LDLZ2 data source can use it to change LD reference population (for all panels) after render\n *\n * @class LocusZoom.Dashboard.Components.set_state\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Set option...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Choose an option to customize the plot\"] Hover text for the toolbar button\n * @param {bool} [layout.show_selected=false] Whether to append the selected value to the button label\n * @param {string} [layout.state_field] The name of the field in plot.state that will be set by this button\n * @typedef {{display_name: string, value: *}} SetStateOptionsConfigField\n * @param {SetStateOptionsConfigField[]} layout.options Specify human labels and associated values for the dropdown menu\n */\nLocusZoom.Dashboard.Components.add('set_state', function (layout) {\n var self = this;\n if (typeof layout.button_html != 'string') { layout.button_html = 'Set option...'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Choose an option to customize the plot'; }\n\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n if (this.parent_panel) {\n throw new Error('This widget is designed to set global options, so it can only be used at the top (plot) level');\n }\n if (!layout.state_field) {\n throw new Error('Must specify the `state_field` that this widget controls');\n }\n\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n // The first option listed is automatically assumed to be the default, unless a value exists in plot.state\n this._selected_item = this.parent_plot.state[layout.state_field] || layout.options[0].value;\n if (!layout.options.find(function(item) { return item.value === self._selected_item; })) {\n // Check only gets run at widget creation, but generally this widget is assumed to be an exclusive list of options\n throw new Error('There is an existing state value that does not match the known values in this widget');\n }\n\n // Define the button + menu that provides the real functionality for this dashboard component\n this.button = new LocusZoom.Dashboard.Component.Button(self)\n .setColor(layout.color)\n .setHtml(layout.button_html + (layout.show_selected ? this._selected_item : ''))\n .setTitle(layout.button_title)\n .setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 1e4).toString();\n\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n\n var renderRow = function(display_name, value, row_id) { // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td')\n .append('input')\n .attr({id: radioId, type: 'radio', name: 'set-state-' + uniqueID, value: row_id})\n .style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n .property('checked', (value === self._selected_item))\n .on('click', function () {\n var new_state = {};\n new_state[layout.state_field] = value;\n self._selected_item = value;\n self.parent_plot.applyState(new_state);\n self.button.setHtml(layout.button_html + (layout.show_selected ? self._selected_item : ''));\n });\n row.append('td').append('label')\n .style('font-weight', 'normal')\n .attr('for', radioId)\n .text(display_name);\n };\n layout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.value, index);\n });\n return self;\n });\n\n this.update = function () {\n this.button.show();\n return this;\n };\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * An SVG object used to display contextual information about a panel.\n * Panel layouts determine basic features of a legend - its position in the panel, orientation, title, etc.\n * Layouts of child data layers of the panel determine the actual content of the legend.\n *\n * @class\n * @param {LocusZoom.Panel} parent\n*/\nLocusZoom.Legend = function(parent) {\n if (!(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create legend, parent must be a locuszoom panel');\n }\n /** @member {LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.legend';\n\n this.parent.layout.legend = LocusZoom.Layouts.merge(this.parent.layout.legend || {}, LocusZoom.Legend.DefaultLayout);\n /** @member {Object} */\n this.layout = this.parent.layout.legend;\n\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {d3.selection} */\n this.background_rect = null;\n /** @member {d3.selection[]} */\n this.elements = [];\n /**\n * SVG selector for the group containing all elements in the legend\n * @protected\n * @member {d3.selection|null}\n */\n this.elements_group = null;\n\n /**\n * TODO: Not sure if this property is used; the external-facing methods are setting `layout.hidden` instead. Tentatively mark deprecated.\n * @deprecated\n * @protected\n * @member {Boolean}\n */\n this.hidden = false;\n\n // TODO Revisit constructor return value; see https://stackoverflow.com/a/3350364/1422268\n return this.render();\n};\n\n/**\n * The default layout used by legends (used internally)\n * @protected\n * @member {Object}\n */\nLocusZoom.Legend.DefaultLayout = {\n orientation: 'vertical',\n origin: { x: 0, y: 0 },\n width: 10,\n height: 10,\n padding: 5,\n label_size: 12,\n hidden: false\n};\n\n/**\n * Render the legend in the parent panel\n */\nLocusZoom.Legend.prototype.render = function() {\n\n // Get a legend group selector if not yet defined\n if (!this.selector) {\n this.selector = this.parent.svg.group.append('g')\n .attr('id', this.parent.getBaseId() + '.legend').attr('class', 'lz-legend');\n }\n\n // Get a legend background rect selector if not yet defined\n if (!this.background_rect) {\n this.background_rect = this.selector.append('rect')\n .attr('width', 100).attr('height', 100).attr('class', 'lz-legend-background');\n }\n\n // Get a legend elements group selector if not yet defined\n if (!this.elements_group) {\n this.elements_group = this.selector.append('g');\n }\n\n // Remove all elements from the document and re-render from scratch\n this.elements.forEach(function(element) {\n element.remove();\n });\n this.elements = [];\n\n // Gather all elements from data layers in order (top to bottom) and render them\n var padding = +this.layout.padding || 1;\n var x = padding;\n var y = padding;\n var line_height = 0;\n this.parent.data_layer_ids_by_z_index.slice().reverse().forEach(function(id) {\n if (Array.isArray(this.parent.data_layers[id].layout.legend)) {\n this.parent.data_layers[id].layout.legend.forEach(function(element) {\n var selector = this.elements_group.append('g')\n .attr('transform', 'translate(' + x + ',' + y + ')');\n var label_size = +element.label_size || +this.layout.label_size || 12;\n var label_x = 0;\n var label_y = (label_size / 2) + (padding / 2);\n line_height = Math.max(line_height, label_size + padding);\n // Draw the legend element symbol (line, rect, shape, etc)\n if (element.shape === 'line') {\n // Line symbol\n var length = +element.length || 16;\n var path_y = (label_size / 4) + (padding / 2);\n selector.append('path').attr('class', element.class || '')\n .attr('d', 'M0,' + path_y + 'L' + length + ',' + path_y)\n .style(element.style || {});\n label_x = length + padding;\n } else if (element.shape === 'rect') {\n // Rect symbol\n var width = +element.width || 16;\n var height = +element.height || width;\n selector.append('rect').attr('class', element.class || '')\n .attr('width', width).attr('height', height)\n .attr('fill', element.color || {})\n .style(element.style || {});\n label_x = width + padding;\n line_height = Math.max(line_height, height + padding);\n } else if (d3.svg.symbolTypes.indexOf(element.shape) !== -1) {\n // Shape symbol (circle, diamond, etc.)\n var size = +element.size || 40;\n var radius = Math.ceil(Math.sqrt(size / Math.PI));\n selector.append('path').attr('class', element.class || '')\n .attr('d', d3.svg.symbol().size(size).type(element.shape))\n .attr('transform', 'translate(' + radius + ',' + (radius + (padding / 2)) + ')')\n .attr('fill', element.color || {})\n .style(element.style || {});\n label_x = (2 * radius) + padding;\n label_y = Math.max((2 * radius) + (padding / 2), label_y);\n line_height = Math.max(line_height, (2 * radius) + padding);\n }\n // Draw the legend element label\n selector.append('text').attr('text-anchor', 'left').attr('class', 'lz-label')\n .attr('x', label_x).attr('y', label_y).style({'font-size': label_size}).text(element.label);\n // Position the legend element group based on legend layout orientation\n var bcr = selector.node().getBoundingClientRect();\n if (this.layout.orientation === 'vertical') {\n y += bcr.height + padding;\n line_height = 0;\n } else {\n // Ensure this element does not exceed the panel width\n // (E.g. drop to the next line if it does, but only if it's not the only element on this line)\n var right_x = this.layout.origin.x + x + bcr.width;\n if (x > padding && right_x > this.parent.layout.width) {\n y += line_height;\n x = padding;\n selector.attr('transform', 'translate(' + x + ',' + y + ')');\n }\n x += bcr.width + (3 * padding);\n }\n // Store the element\n this.elements.push(selector);\n }.bind(this));\n }\n }.bind(this));\n\n // Scale the background rect to the elements in the legend\n var bcr = this.elements_group.node().getBoundingClientRect();\n this.layout.width = bcr.width + (2 * this.layout.padding);\n this.layout.height = bcr.height + (2 * this.layout.padding);\n this.background_rect\n .attr('width', this.layout.width)\n .attr('height', this.layout.height);\n\n // Set the visibility on the legend from the \"hidden\" flag\n // TODO: `show()` and `hide()` call a full rerender; might be able to make this more lightweight?\n this.selector.style({ visibility: this.layout.hidden ? 'hidden' : 'visible' });\n\n // TODO: Annotate return type and make consistent\n return this.position();\n};\n\n/**\n * Place the legend in position relative to the panel, as specified in the layout configuration\n * @returns {LocusZoom.Legend | null}\n * TODO: should this always be chainable?\n */\nLocusZoom.Legend.prototype.position = function() {\n if (!this.selector) { return this; }\n var bcr = this.selector.node().getBoundingClientRect();\n if (!isNaN(+this.layout.pad_from_bottom)) {\n this.layout.origin.y = this.parent.layout.height - bcr.height - +this.layout.pad_from_bottom;\n }\n if (!isNaN(+this.layout.pad_from_right)) {\n this.layout.origin.x = this.parent.layout.width - bcr.width - +this.layout.pad_from_right;\n }\n this.selector.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n};\n\n/**\n * Hide the legend (triggers a re-render)\n * @public\n */\nLocusZoom.Legend.prototype.hide = function() {\n this.layout.hidden = true;\n this.render();\n};\n\n/**\n * Show the legend (triggers a re-render)\n * @public\n */\nLocusZoom.Legend.prototype.show = function() {\n this.layout.hidden = false;\n this.render();\n};\n","/* global LocusZoom */\n'use strict';\n\nfunction validateBuildSource(class_name, build, source) {\n // Build OR Source, not both\n if ((build && source) || !(build || source)) {\n throw new Error(class_name + ' must provide a parameter specifying either \"build\" or \"source\". It should not specify both.');\n }\n // If the build isn't recognized, our APIs can't transparently select a source to match\n if (build && ['GRCh37', 'GRCh38'].indexOf(build) === -1) {\n throw new Error(class_name + ' must specify a valid genome build number');\n }\n}\n\n/**\n * LocusZoom functionality used for data parsing and retrieval\n * @namespace\n * @public\n */\nLocusZoom.Data = LocusZoom.Data || {};\n\n/**\n * Create and coordinate an ensemble of (namespaced) data source instances\n * @public\n * @class\n */\nLocusZoom.DataSources = function() {\n /** @member {Object.} */\n this.sources = {};\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.addSource = function(ns, x) {\n console.warn('Warning: .addSource() is deprecated. Use .add() instead');\n return this.add(ns, x);\n};\n\n/**\n * Add a (namespaced) datasource to the plot\n * @public\n * @param {String} ns A namespace used for fields from this data source\n * @param {LocusZoom.Data.Source|Array|null} x An instantiated datasource, or an array of arguments that can be used to\n * create a known datasource type.\n */\nLocusZoom.DataSources.prototype.add = function(ns, x) {\n // FIXME: Some existing sites create sources with arbitrary names. This leads to subtle breakage\n // of namespaced fields in layouts. To avoid breaking existing usages outright, issue a deprecation warning.\n if (ns.match(/[^A-Za-z0-9_]/)) {\n console.warn(\"Deprecation warning: source name '\" + ns + \"' should contain only alphanumeric characters or underscores. Use of other characters may break layouts, and will be disallowed in the future.\");\n }\n return this.set(ns, x);\n};\n\n/** @protected */\nLocusZoom.DataSources.prototype.set = function(ns, x) {\n if (Array.isArray(x)) {\n // If passed array of source name and options, make the source\n var dsobj = LocusZoom.KnownDataSources.create.apply(null, x);\n // Each datasource in the chain should be aware of its assigned namespace\n dsobj.source_id = ns;\n this.sources[ns] = dsobj;\n } else {\n // If passed the already-created source object\n if (x !== null) {\n x.source_id = ns;\n this.sources[ns] = x;\n } else {\n delete this.sources[ns];\n }\n }\n return this;\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.getSource = function(ns) {\n console.warn('Warning: .getSource() is deprecated. Use .get() instead');\n return this.get(ns);\n};\n\n/**\n * Return the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n * @returns {LocusZoom.Data.Source}\n */\nLocusZoom.DataSources.prototype.get = function(ns) {\n return this.sources[ns];\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.removeSource = function(ns) {\n console.warn('Warning: .removeSource() is deprecated. Use .remove() instead');\n return this.remove(ns);\n};\n\n/**\n * Remove the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n */\nLocusZoom.DataSources.prototype.remove = function(ns) {\n return this.set(ns, null);\n};\n\n/**\n * Populate a list of datasources specified as a JSON object\n * @public\n * @param {String|Object} x An object or JSON representation containing {ns: configArray} entries\n * @returns {LocusZoom.DataSources}\n */\nLocusZoom.DataSources.prototype.fromJSON = function(x) {\n if (typeof x === 'string') {\n x = JSON.parse(x);\n }\n var ds = this;\n Object.keys(x).forEach(function(ns) {\n ds.set(ns, x[ns]);\n });\n return ds;\n};\n\n/**\n * Return the names of all currently recognized datasources\n * @public\n * @returns {Array}\n */\nLocusZoom.DataSources.prototype.keys = function() {\n return Object.keys(this.sources);\n};\n\n/**\n * Datasources can be instantiated from a JSON object instead of code. This represents existing sources in that format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n * @public\n */\nLocusZoom.DataSources.prototype.toJSON = function() {\n return this.sources;\n};\n\n/**\n * Represents an addressable unit of data from a namespaced datasource, subject to specified value transformations.\n *\n * When used by a data layer, fields will automatically be re-fetched from the appropriate data source whenever the\n * state of a plot fetches, eg pan or zoom operations that would affect what data is displayed.\n *\n * @public\n * @class\n * @param {String} field A string representing the namespace of the datasource, the name of the desired field to fetch\n * from that datasource, and arbitrarily many transformations to apply to the value. The namespace and\n * transformation(s) are optional and information is delimited according to the general syntax\n * `[namespace:]name[|transformation][|transformation]`. For example, `association:pvalue|neglog10`\n */\nLocusZoom.Data.Field = function(field) {\n\n var parts = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/.exec(field);\n /** @member {String} */\n this.full_name = field;\n /** @member {String} */\n this.namespace = parts[1] || null;\n /** @member {String} */\n this.name = parts[2] || null;\n /** @member {Array} */\n this.transformations = [];\n\n if (typeof parts[3] == 'string' && parts[3].length > 1) {\n this.transformations = parts[3].substring(1).split('|');\n this.transformations.forEach(function(transform, i) {\n this.transformations[i] = LocusZoom.TransformationFunctions.get(transform);\n }.bind(this));\n }\n\n this.applyTransformations = function(val) {\n this.transformations.forEach(function(transform) {\n val = transform(val);\n });\n return val;\n };\n\n // Resolve the field for a given data element.\n // First look for a full match with transformations already applied by the data requester.\n // Otherwise prefer a namespace match and fall back to just a name match, applying transformations on the fly.\n this.resolve = function(d) {\n if (typeof d[this.full_name] == 'undefined') {\n var val = null;\n if (typeof (d[this.namespace + ':' + this.name]) != 'undefined') { val = d[this.namespace + ':' + this.name]; }\n else if (typeof d[this.name] != 'undefined') { val = d[this.name]; }\n d[this.full_name] = this.applyTransformations(val);\n }\n return d[this.full_name];\n };\n\n};\n\n/**\n * The Requester manages fetching of data across multiple data sources. It is used internally by LocusZoom data layers.\n * It passes state information and ensures that data is formatted in the manner expected by the plot.\n *\n * It is also responsible for constructing a \"chain\" of dependent requests, by requesting each datasource\n * sequentially in the order specified in the datalayer `fields` array. Data sources are only chained within a\n * data layer, and only if that layer requests more than one kind of data source.\n * @param {LocusZoom.DataSources} sources An object of {ns: LocusZoom.Data.Source} instances\n * @class\n */\nLocusZoom.Data.Requester = function(sources) {\n\n function split_requests(fields) {\n // Given a fields array, return an object specifying what datasource names the data layer should make requests\n // to, and how to handle the returned data\n var requests = {};\n // Regular expression finds namespace:field|trans\n var re = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/;\n fields.forEach(function(raw) {\n var parts = re.exec(raw);\n var ns = parts[1] || 'base';\n var field = parts[2];\n var trans = LocusZoom.TransformationFunctions.get(parts[3]);\n if (typeof requests[ns] == 'undefined') {\n requests[ns] = {outnames:[], fields:[], trans:[]};\n }\n requests[ns].outnames.push(raw);\n requests[ns].fields.push(field);\n requests[ns].trans.push(trans);\n });\n return requests;\n }\n\n /**\n * Fetch data, and create a chain that only connects two data sources if they depend on each other\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields The list of data fields specified in the `layout` for a specific data layer\n * @returns {Promise}\n */\n this.getData = function(state, fields) {\n var requests = split_requests(fields);\n // Create an array of functions that, when called, will trigger the request to the specified datasource\n var request_handles = Object.keys(requests).map(function(key) {\n if (!sources.get(key)) {\n throw new Error('Datasource for namespace ' + key + ' not found');\n }\n return sources.get(key).getData(state, requests[key].fields,\n requests[key].outnames, requests[key].trans);\n });\n //assume the fields are requested in dependent order\n //TODO: better manage dependencies\n var ret = Promise.resolve({header:{}, body: [], discrete: {}});\n for(var i = 0; i < request_handles.length; i++) {\n // If a single datalayer uses multiple sources, perform the next request when the previous one completes\n ret = ret.then(request_handles[i]);\n }\n return ret;\n };\n};\n\n/**\n * Base class for LocusZoom data sources\n * This can be extended with .extend() to create custom data sources\n * @class\n * @public\n */\nLocusZoom.Data.Source = function() {\n /**\n * Whether this source should enable caching\n * @member {Boolean}\n */\n this.enableCache = true;\n /**\n * Whether this data source type is dependent on previous requests- for example, the LD source cannot annotate\n * association data if no data was found for that region.\n * @member {boolean}\n */\n this.dependentSource = false;\n};\n\n/**\n * A default constructor that can be used when creating new data sources\n * @param {String|Object} init Basic configuration- either a url, or a config object\n * @param {String} [init.url] The datasource URL\n * @param {String} [init.params] Initial config params for the datasource\n */\nLocusZoom.Data.Source.prototype.parseInit = function(init) {\n if (typeof init === 'string') {\n /** @member {String} */\n this.url = init;\n /** @member {String} */\n this.params = {};\n } else {\n this.url = init.url;\n this.params = init.params || {};\n }\n if (!this.url) {\n throw new Error('Source not initialized with required URL');\n }\n\n};\n\n/**\n * A unique identifier that indicates whether cached data is valid for this request\n * @protected\n * @param state\n * @param chain\n * @param fields\n * @returns {String|undefined}\n */\nLocusZoom.Data.Source.prototype.getCacheKey = function(state, chain, fields) {\n return this.getURL && this.getURL(state, chain, fields);\n};\n\n/**\n * Stub: build the URL for any requests made by this source.\n */\nLocusZoom.Data.Source.prototype.getURL = function(state, chain, fields) { return this.url; };\n\n/**\n * Perform a network request to fetch data for this source\n * @protected\n * @param {Object} state The state of the parent plot\n * @param chain\n * @param fields\n * @returns {Promise}\n */\nLocusZoom.Data.Source.prototype.fetchRequest = function(state, chain, fields) {\n var url = this.getURL(state, chain, fields);\n return LocusZoom.createCORSPromise('GET', url);\n};\n\n/**\n * Gets the data for just this source, typically via a network request (caching where possible)\n * @protected\n */\nLocusZoom.Data.Source.prototype.getRequest = function(state, chain, fields) {\n var req;\n var cacheKey = this.getCacheKey(state, chain, fields);\n if (this.enableCache && typeof(cacheKey) !== 'undefined' && cacheKey === this._cachedKey) {\n req = Promise.resolve(this._cachedResponse); // Resolve to the value of the current promise\n } else {\n req = this.fetchRequest(state, chain, fields);\n if (this.enableCache) {\n this._cachedKey = cacheKey;\n this._cachedResponse = req;\n }\n }\n return req;\n};\n\n/**\n * Fetch the data from the specified data source, and apply transformations requested by an external consumer.\n * This is the public-facing datasource method that will most commonly be called by external code.\n *\n * @public\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields Array of field names that the plot has requested from this data source. (without the \"namespace\" prefix)\n * @param {String[]} outnames Array describing how the output data should refer to this field. This represents the\n * originally requested field name, including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {function} A callable operation that can be used as part of the data chain\n */\nLocusZoom.Data.Source.prototype.getData = function(state, fields, outnames, trans) {\n if (this.preGetData) {\n var pre = this.preGetData(state, fields, outnames, trans);\n if(this.pre) {\n state = pre.state || state;\n fields = pre.fields || fields;\n outnames = pre.outnames || outnames;\n trans = pre.trans || trans;\n }\n }\n\n var self = this;\n return function (chain) {\n if (self.dependentSource && chain && chain.body && !chain.body.length) {\n // A \"dependent\" source should not attempt to fire a request if there is no data for it to act on.\n // Therefore, it should simply return the previous data chain.\n return Promise.resolve(chain);\n }\n\n return self.getRequest(state, chain, fields).then(function(resp) {\n return self.parseResponse(resp, chain, fields, outnames, trans);\n });\n };\n};\n\n/**\n * Ensure the server response is in a canonical form, an array of one object per record. [ {field: oneval} ].\n * If the server response contains columns, reformats the response from {column1: [], column2: []} to the above.\n *\n * Does not apply namespacing, transformations, or field extraction.\n *\n * May be overridden by data sources that inherently return more complex payloads, or that exist to annotate other\n * sources (eg, if the payload provides extra data rather than a series of records).\n *\n * @param {Object[]|Object} data The original parsed server response\n * @protected\n */\nLocusZoom.Data.Source.prototype.normalizeResponse = function (data) {\n if (Array.isArray(data)) {\n // Already in the desired form\n return data;\n }\n\n // Otherwise, assume the server response is an object representing columns of data.\n // Each array should have the same length (verify), and a given array index corresponds to a single row.\n var keys = Object.keys(data);\n var N = data[keys[0]].length;\n var sameLength = keys.every(function(key) {\n var item = data[key];\n return item.length === N;\n });\n if (!sameLength) {\n throw new Error(this.constructor.SOURCE_NAME + ' expects a response in which all arrays of data are the same length');\n }\n\n // Go down the rows, and create an object for each record\n var records = [];\n var fields = Object.keys(data);\n for(var i = 0; i < N; i++) {\n var record = {};\n for(var j = 0; j < fields.length; j++) {\n record[fields[j]] = data[fields[j]][i];\n }\n records.push(record);\n }\n return records;\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.prepareData = function (records) {\n console.warn('Warning: .prepareData() is deprecated. Use .annotateData() instead');\n return this.annotateData(records);\n};\n\n/**\n * Hook to post-process the data returned by this source with new, additional behavior.\n * (eg cleaning up API values or performing complex calculations on the returned data)\n *\n * @param {Object[]} records The parsed data from the source (eg standardized api response)\n * @param {Object} chain The data chain object. For example, chain.headers may provide useful annotation metadata\n * @returns {Object[]|Promise} The modified set of records\n */\nLocusZoom.Data.Source.prototype.annotateData = function(records, chain) {\n // Default behavior: no transformations\n return records;\n};\n\n/**\n * Clean up the server records for use by datalayers: extract only certain fields, with the specified names.\n * Apply per-field transformations as appropriate.\n *\n * This hook can be overridden, eg to create a source that always returns all records and ignores the \"fields\" array.\n * This is particularly common for sources at the end of a chain- many \"dependent\" sources do not allow\n * cherry-picking individual fields, in which case by **convention** the fields array specifies \"last_source_name:all\"\n *\n * @param {Object[]} data One record object per element\n * @param {String[]} fields The names of fields to extract (as named in the source data). Eg \"afield\"\n * @param {String[]} outnames How to represent the source fields in the output. Eg \"namespace:afield|atransform\"\n * @param {function[]} trans An array of transformation functions (if any). One function per data element, or null.\n * @protected\n */\nLocusZoom.Data.Source.prototype.extractFields = function (data, fields, outnames, trans) {\n //intended for an array of objects\n // [ {\"id\":1, \"val\":5}, {\"id\":2, \"val\":10}]\n // Since a number of sources exist that do not obey this format, we will provide a convenient pass-through\n if (!Array.isArray(data)) {\n return data;\n }\n\n if (!data.length) {\n // Sometimes there are regions that just don't have data- this should not trigger a missing field error message!\n return data;\n }\n\n var fieldFound = [];\n for (var k = 0; k < fields.length; k++) {\n fieldFound[k] = 0;\n }\n\n var records = data.map(function (item) {\n var output_record = {};\n for (var j = 0; j < fields.length; j++) {\n var val = item[fields[j]];\n if (typeof val != 'undefined') {\n fieldFound[j] = 1;\n }\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n output_record[outnames[j]] = val;\n }\n return output_record;\n });\n fieldFound.forEach(function(v, i) {\n if (!v) {throw new Error('field ' + fields[i] + ' not found in response for ' + outnames[i]);}\n });\n return records;\n};\n\n/**\n * Combine records from this source with others in the chain to yield final chain body.\n * Handles merging this data with other sources (if applicable).\n *\n * @param {Object[]} data The data That would be returned from this source alone\n * @param {Object} chain The data chain built up during previous requests\n * @param {String[]} fields\n * @param {String[]} outnames\n * @return {Promise|Object[]} The new chain body\n * @protected\n */\nLocusZoom.Data.Source.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n return data;\n};\n\n/**\n * Coordinates the work of parsing a response and returning records. This is broken into 4 steps, which may be\n * overridden separately for fine-grained control. Each step can return either raw data or a promise.\n *\n * @public\n * @param {String|Object} resp The raw data associated with the response\n * @param {Object} chain The combined parsed response data from this and all other requests made in the chain\n * @param {String[]} fields Array of requested field names (as they would appear in the response payload)\n * @param {String[]} outnames Array of field names as they will be represented in the data returned by this source,\n * including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {Promise|{header: ({}|*), discrete: {}, body: []}} A promise that resolves to an object containing\n * request metadata (headers), the consolidated data for plotting (body), and the individual responses that would be\n * returned by each source in the chain in isolation (discrete)\n */\nLocusZoom.Data.Source.prototype.parseResponse = function(resp, chain, fields, outnames, trans) {\n var source_id = this.source_id || this.constructor.SOURCE_NAME;\n if (!chain.discrete) {\n chain.discrete = {};\n }\n\n if (!resp) {\n // FIXME: Hack. Certain browser issues (such as mixed content warnings) are reported as a successful promise\n // resolution, even though the request was aborted. This is difficult to reliably detect, and is most likely\n // to occur for annotation sources (such as from ExAC). If empty response is received, skip parsing and log.\n // FIXME: Throw an error after pending, eg https://github.com/konradjk/exac_browser/issues/345\n console.error(\"No usable response was returned for source: '\" + source_id + \"'. Parsing will be skipped.\");\n return Promise.resolve(chain);\n }\n\n var json = typeof resp == 'string' ? JSON.parse(resp) : resp;\n\n var self = this;\n // Perform the 4 steps of parsing the payload and return a combined chain object\n return Promise.resolve(self.normalizeResponse(json.data || json))\n .then(function(standardized) {\n // Perform calculations on the data from just this source\n return Promise.resolve(self.annotateData(standardized, chain));\n }).then(function (data) {\n return Promise.resolve(self.extractFields(data, fields, outnames, trans));\n }).then(function (one_source_body) {\n // Store a copy of the data that would be returned by parsing this source in isolation (and taking the\n // fields array into account). This is useful when we want to re-use the source output in many ways.\n chain.discrete[source_id] = one_source_body;\n return Promise.resolve(self.combineChainBody(one_source_body, chain, fields, outnames, trans));\n }).then(function (new_body) {\n return { header: chain.header || {}, discrete: chain.discrete, body: new_body };\n });\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseArraysToObjects = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseArraysToObjects() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseObjectsToObjects = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseObjectsToObjects() is deprecated. Use .extractFields() instead');\n return this.extractFields(data, fields, outnames, trans);\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseData = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseData() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n};\n\n/**\n * Method to define new custom datasources based on a provided constructor. (does not allow registering any additional methods)\n * @public\n * @param {Function} constructorFun Constructor function that is used to create the specified class\n * @param {String} [uniqueName] The name by which the class should be listed in `KnownDataSources`\n * @param {String|Function} [base=LocusZoomData.Source] The name or constructor of a base class to use\n * @returns {*|Function}\n */\nLocusZoom.Data.Source.extend = function(constructorFun, uniqueName, base) {\n if (base) {\n if (Array.isArray(base)) {\n base = LocusZoom.KnownDataSources.create.apply(null, base);\n } else if (typeof base === 'string') {\n base = LocusZoom.KnownDataSources.get(base).prototype;\n } else if (typeof base === 'function') {\n base = base.prototype;\n }\n } else {\n base = new LocusZoom.Data.Source();\n }\n constructorFun = constructorFun || function() {};\n constructorFun.prototype = base;\n constructorFun.prototype.constructor = constructorFun;\n if (uniqueName) {\n /** @member {String} LocusZoom.Data.Source.SOURCENAME */\n constructorFun.SOURCE_NAME = uniqueName;\n LocusZoom.KnownDataSources.add(constructorFun);\n }\n return constructorFun;\n};\n\n/**\n * Datasources can be instantiated from a JSON object instead of code. This represents an existing source in that data format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n *\n * Custom sources with their own parameters may need to re-implement this method\n *\n * @public\n * @returns {Object}\n */\nLocusZoom.Data.Source.prototype.toJSON = function() {\n return [Object.getPrototypeOf(this).constructor.SOURCE_NAME,\n {url:this.url, params:this.params}];\n};\n\n/**\n * Data Source for Association Data, as fetched from the LocusZoom API server (or compatible)\n * @class\n * @public\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.AssociationSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'AssociationLZ');\n\nLocusZoom.Data.AssociationSource.prototype.preGetData = function(state, fields, outnames, trans) {\n var id_field = this.params.id_field || 'id';\n [id_field, 'position'].forEach(function(x) {\n if (fields.indexOf(x) === -1) {\n fields.unshift(x);\n outnames.unshift(x);\n trans.unshift(null);\n }\n });\n return {fields: fields, outnames:outnames, trans:trans};\n};\n\nLocusZoom.Data.AssociationSource.prototype.getURL = function(state, chain, fields) {\n var analysis = chain.header.analysis || this.params.source || this.params.analysis; // Old usages called this param \"analysis\"\n if (typeof analysis == 'undefined') {\n throw new Error('Association source must specify an analysis ID to plot');\n }\n return this.url + 'results/?filter=analysis in ' + analysis +\n \" and chromosome in '\" + state.chr + \"'\" +\n ' and position ge ' + state.start +\n ' and position le ' + state.end;\n};\n\nLocusZoom.Data.AssociationSource.prototype.normalizeResponse = function (data) {\n // Some association sources do not sort their data in a predictable order, which makes it hard to reliably\n // align with other sources (such as LD). For performance reasons, sorting is an opt-in argument.\n // TODO: Consider more fine grained sorting control in the future\n data = LocusZoom.Data.Source.prototype.normalizeResponse.call(this, data);\n if (this.params && this.params.sort && data.length && data[0]['position']) {\n data.sort(function (a, b) { return a['position'] - b['position']; });\n }\n return data;\n};\n\n/**\n * Data Source for LD Data, as fetched from the LocusZoom API server (or compatible)\n * This source is designed to connect its results to association data, and therefore depends on association data having\n * been loaded by a previous request in the data chain.\n *\n * This source is deprecated in favor of a new, standalone LD server. For new usages, see LDLZ2.\n *\n * @class\n * @deprecated\n * @public\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.LDSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n this.dependentSource = true;\n}, 'LDLZ');\n\nLocusZoom.Data.LDSource.prototype.preGetData = function(state, fields) {\n if (fields.length > 1) {\n if (fields.length !== 2 || fields.indexOf('isrefvar') === -1) {\n throw new Error('LD does not know how to get all fields: ' + fields.join(', '));\n }\n }\n};\n\nLocusZoom.Data.LDSource.prototype.findMergeFields = function(chain) {\n // Find the fields (as provided by a previous step in the chain, like an association source) that will be needed to\n // combine LD data with existing information\n\n // Since LD information may be shared across multiple assoc sources with different namespaces,\n // we use regex to find columns to join on, rather than requiring exact matches\n var exactMatch = function(arr) {return function() {\n var regexes = arguments;\n for(var i = 0; i < regexes.length; i++) {\n var regex = regexes[i];\n var m = arr.filter(function(x) {return x.match(regex);});\n if (m.length) {\n return m[0];\n }\n }\n return null;\n };};\n var dataFields = {\n id: this.params.id_field,\n position: this.params.position_field,\n pvalue: this.params.pvalue_field,\n _names_:null\n };\n if (chain && chain.body && chain.body.length > 0) {\n var names = Object.keys(chain.body[0]);\n var nameMatch = exactMatch(names);\n // Internally, fields are generally prefixed with the name of the source they come from.\n // If the user provides an id_field (like `variant`), it should work across data sources( `assoc1:variant`,\n // assoc2:variant), but not match fragments of other field names (assoc1:variant_thing)\n // Note: these lookups hard-code a couple of common fields that will work based on known APIs in the wild\n var id_match = dataFields.id && nameMatch(new RegExp(dataFields.id + '\\\\b'));\n dataFields.id = id_match || nameMatch(/\\bvariant\\b/) || nameMatch(/\\bid\\b/);\n dataFields.position = dataFields.position || nameMatch(/\\bposition\\b/i, /\\bpos\\b/i);\n dataFields.pvalue = dataFields.pvalue || nameMatch(/\\bpvalue\\b/i, /\\blog_pvalue\\b/i);\n dataFields._names_ = names;\n }\n return dataFields;\n};\n\nLocusZoom.Data.LDSource.prototype.findRequestedFields = function(fields, outnames) {\n // Assumption: all usages of this source will only ever ask for \"isrefvar\" or \"state\". This maps to output names.\n var obj = {};\n for(var i = 0; i < fields.length; i++) {\n if(fields[i] === 'isrefvar') {\n obj.isrefvarin = fields[i];\n obj.isrefvarout = outnames && outnames[i];\n } else {\n obj.ldin = fields[i];\n obj.ldout = outnames && outnames[i];\n }\n }\n return obj;\n};\n\nLocusZoom.Data.LDSource.prototype.normalizeResponse = function (data) { return data; };\n\n\n/**\n * Get the LD reference variant, which by default will be the most significant hit in the assoc results\n * This will be used in making the original query to the LD server for pairwise LD information\n * @returns {*|string} The marker id (expected to be in `chr:pos_ref/alt` format) of the reference variant\n */\nLocusZoom.Data.LDSource.prototype.getRefvar = function (state, chain, fields) {\n var findExtremeValue = function(records, pval_field) {\n // Finds the most significant hit (smallest pvalue, or largest -log10p). Will try to auto-detect the appropriate comparison.\n pval_field = pval_field || 'log_pvalue'; // The official LZ API returns log_pvalue\n var is_log = /log/.test(pval_field);\n var cmp;\n if (is_log) {\n cmp = function(a, b) { return a > b; };\n } else {\n cmp = function(a, b) { return a < b; };\n }\n var extremeVal = records[0][pval_field], extremeIdx = 0;\n for(var i = 1; i < records.length; i++) {\n if (cmp(records[i][pval_field], extremeVal)) {\n extremeVal = records[i][pval_field];\n extremeIdx = i;\n }\n }\n return extremeIdx;\n };\n\n var reqFields = this.findRequestedFields(fields);\n var refVar = reqFields.ldin;\n if (refVar === 'state') {\n refVar = state.ldrefvar || chain.header.ldrefvar || 'best';\n }\n if (refVar === 'best') {\n if (!chain.body) {\n throw new Error('No association data found to find best pvalue');\n }\n var keys = this.findMergeFields(chain);\n if (!keys.pvalue || !keys.id) {\n var columns = '';\n if (!keys.id) { columns += (columns.length ? ', ' : '') + 'id'; }\n if (!keys.pvalue) { columns += (columns.length ? ', ' : '') + 'pvalue'; }\n throw new Error('Unable to find necessary column(s) for merge: ' + columns + ' (available: ' + keys._names_ + ')');\n }\n refVar = chain.body[findExtremeValue(chain.body, keys.pvalue)][keys.id];\n }\n return refVar;\n};\n\nLocusZoom.Data.LDSource.prototype.getURL = function(state, chain, fields) {\n var refSource = state.ldrefsource || chain.header.ldrefsource || 1;\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n return this.url + 'results/?filter=reference eq ' + refSource +\n \" and chromosome2 eq '\" + state.chr + \"'\" +\n ' and position2 ge ' + state.start +\n ' and position2 le ' + state.end +\n \" and variant1 eq '\" + refVar + \"'\" +\n '&fields=chr,pos,rsquare';\n};\n\nLocusZoom.Data.LDSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n var keys = this.findMergeFields(chain);\n var reqFields = this.findRequestedFields(fields, outnames);\n if (!keys.position) {\n throw new Error('Unable to find position field for merge: ' + keys._names_);\n }\n var leftJoin = function(left, right, lfield, rfield) {\n var i = 0, j = 0;\n while (i < left.length && j < right.position2.length) {\n if (left[i][keys.position] === right.position2[j]) {\n left[i][lfield] = right[rfield][j];\n i++;\n j++;\n } else if (left[i][keys.position] < right.position2[j]) {\n i++;\n } else {\n j++;\n }\n }\n };\n var tagRefVariant = function(data, refvar, idfield, outrefname, outldname) {\n for(var i = 0; i < data.length; i++) {\n if (data[i][idfield] && data[i][idfield] === refvar) {\n data[i][outrefname] = 1;\n data[i][outldname] = 1; // For label/filter purposes, implicitly mark the ref var as LD=1 to itself\n } else {\n data[i][outrefname] = 0;\n }\n }\n };\n\n // LD servers vary slightly. Some report corr as \"rsquare\", others as \"correlation\"\n var corrField = data.rsquare ? 'rsquare' : 'correlation';\n leftJoin(chain.body, data, reqFields.ldout, corrField);\n if(reqFields.isrefvarin && chain.header.ldrefvar) {\n tagRefVariant(chain.body, chain.header.ldrefvar, keys.id, reqFields.isrefvarout, reqFields.ldout);\n }\n return chain.body;\n};\n\n/**\n * Fetch LD directly from the standalone Portal LD server\n *\n * @class\n * @public\n * @augments LocusZoom.Data.LDSource\n */\nLocusZoom.Data.LDSource2 = LocusZoom.KnownDataSources.extend('LDLZ', 'LDLZ2', {\n getURL: function(state, chain, fields) {\n // Accept the following params in this.params:\n // - method (r, rsquare, cov)\n // - source (aka panel)\n // - population (ALL, AFR, EUR, etc)\n // - build\n // The LD source/pop can be overridden from plot.state for dynamic layouts\n var build = state.genome_build || this.params.build || 'GRCh37';\n var source = state.ld_source || this.params.source || '1000G';\n var population = state.ld_pop || this.params.population || 'ALL'; // LDServer panels will always have an ALL\n var method = this.params.method || 'rsquare';\n\n validateBuildSource(this.constructor.SOURCE_NAME, build, null); // LD doesn't need to validate `source` option\n\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n\n return [\n this.url, 'genome_builds/', build, '/references/', source, '/populations/', population, '/variants',\n '?correlation=', method,\n '&variant=', encodeURIComponent(refVar),\n '&chrom=', encodeURIComponent(state.chr),\n '&start=', encodeURIComponent(state.start),\n '&stop=', encodeURIComponent(state.end)\n ].join('');\n },\n fetchRequest: function(state, chain, fields) {\n // The API is paginated, but we need all of the data to render a plot. Depaginate and combine where appropriate.\n var url = this.getURL(state, chain, fields);\n var combined = { data: {} };\n var chainRequests = function (url) {\n return LocusZoom.createCORSPromise('GET', url)\n .then(function(payload) {\n payload = JSON.parse(payload);\n Object.keys(payload.data).forEach(function (key) {\n combined.data[key] = (combined.data[key] || []).concat(payload.data[key]);\n });\n if (payload.next) {\n return chainRequests(payload.next);\n }\n return combined;\n });\n };\n\n return chainRequests(url);\n }\n});\n\n/**\n * Data source for GWAS catalogs of known variants\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object|String} init Configuration (URL or object)\n * @param {Object} [init.params] Optional configuration parameters\n * @param {Number} [init.params.source=2] The ID of the chosen catalog. Defaults to EBI GWAS catalog, GRCh37\n * @param {('strict'|'loose')} [init.params.match_type='strict'] Whether to match on exact variant, or just position.\n */\nLocusZoom.Data.GwasCatalog = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n this.dependentSource = true;\n}, 'GwasCatalogLZ');\n\nLocusZoom.Data.GwasCatalog.prototype.getURL = function(state, chain, fields) {\n // This is intended to be aligned with another source- we will assume they are always ordered by position, asc\n // (regardless of the actual match field)\n var build_option = state.genome_build || this.params.build;\n validateBuildSource(this.constructor.SOURCE_NAME, build_option, null); // Source can override build- not mutually exclusive\n\n // Most of our annotations will respect genome build before any other option.\n // But there can be more than one GWAS catalog for the same build, so an explicit config option will always take\n // precedence.\n var default_source = (build_option === 'GRCh38') ? 1 : 2; // EBI GWAS catalog\n var source = this.params.source || default_source;\n return this.url + '?format=objects&sort=pos&filter=id eq ' + source +\n \" and chrom eq '\" + state.chr + \"'\" +\n ' and pos ge ' + state.start +\n ' and pos le ' + state.end;\n};\n\nLocusZoom.Data.GwasCatalog.prototype.findMergeFields = function (records) {\n // Data from previous sources is already namespaced. Find the alignment field by matching.\n var knownFields = Object.keys(records);\n // Note: All API endoints involved only give results for 1 chromosome at a time; match is implied\n var posMatch = knownFields.find(function (item) { return item.match(/\\b(position|pos)\\b/i); });\n\n if (!posMatch) {\n throw new Error('Could not find data to align with GWAS catalog results');\n }\n return { 'pos': posMatch };\n};\n\n// Skip the \"individual field extraction\" step; extraction will be handled when building chain body instead\nLocusZoom.Data.GwasCatalog.prototype.extractFields = function (data, fields, outnames, trans) { return data; };\n\nLocusZoom.Data.GwasCatalog.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data.length) {\n return chain.body;\n }\n\n var decider = 'log_pvalue'; // TODO: Better reuse options in the future\n var decider_out = outnames[fields.indexOf(decider)];\n\n function leftJoin(left, right, fields, outnames, trans) { // Add `fields` from `right` to `left`\n // Add a synthetic, un-namespaced field to all matching records\n var n_matches = left['n_catalog_matches'] || 0;\n left['n_catalog_matches'] = n_matches + 1;\n if (decider && left[decider_out] && left[decider_out] > right[decider]) {\n // There may be more than one GWAS catalog entry for the same SNP. This source is intended for a 1:1\n // annotation scenario, so for now it only joins the catalog entry that has the best -log10 pvalue\n return;\n }\n\n for (var j = 0; j < fields.length; j++) {\n var fn = fields[j];\n var outn = outnames[j];\n\n var val = right[fn];\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n left[outn] = val;\n }\n }\n\n var chainNames = this.findMergeFields(chain.body[0]);\n var catNames = this.findMergeFields(data[0]);\n\n var i = 0, j = 0;\n while (i < chain.body.length && j < data.length) {\n var left = chain.body[i];\n var right = data[j];\n\n if (left[chainNames.pos] === right[catNames.pos]) {\n // There may be multiple catalog entries for each matching SNP; evaluate match one at a time\n leftJoin(left, right, fields, outnames, trans);\n j += 1;\n } else if (left[chainNames.pos] < right[catNames.pos]) {\n i += 1;\n } else {\n j += 1;\n }\n }\n return chain.body;\n};\n\n\n/**\n * Data Source for Gene Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.GeneSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'GeneLZ');\n\nLocusZoom.Data.GeneSource.prototype.getURL = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n\n if (build) { // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = (build === 'GRCh38') ? 1 : 3;\n }\n return this.url + '?filter=source in ' + source +\n \" and chrom eq '\" + state.chr + \"'\" +\n ' and start le ' + state.end +\n ' and end ge ' + state.start;\n};\n\n// Genes have a very complex internal data format. Bypass any record parsing, and provide the data layer with the\n// exact information returned by the API. (ignoring the fields array in the layout)\nLocusZoom.Data.GeneSource.prototype.normalizeResponse = function (data) { return data; };\nLocusZoom.Data.GeneSource.prototype.extractFields = function (data, fields, outnames, trans) { return data; };\n\n/**\n * Data Source for Gene Constraint Data, as fetched from the ExAC server (or compatible)\n *\n * FIXME: The ExAc server has been decommissioned. This source is kept here to avoid breaking existing layouts; we may\n * be able to restore this feature in the future once the gnomAD API is further developed\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n*/\nLocusZoom.Data.GeneConstraintSource = LocusZoom.Data.Source.extend(function(init) {\n console.warn('The gene constraint source depends on a server (ExAC) that is no longer active. This information may not be displayed.');\n this.parseInit(init);\n}, 'GeneConstraintLZ');\n\nLocusZoom.Data.GeneConstraintSource.prototype.getURL = function() {\n return this.url;\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.normalizeResponse = function (data) { return data; };\n\nLocusZoom.Data.GeneConstraintSource.prototype.getCacheKey = function(state, chain, fields) {\n return this.url + JSON.stringify(state);\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function(state, chain, fields) {\n var geneids = [];\n chain.body.forEach(function(gene) {\n var gene_id = gene.gene_id;\n if (gene_id.indexOf('.')) {\n gene_id = gene_id.substr(0, gene_id.indexOf('.'));\n }\n geneids.push(gene_id);\n });\n var url = this.getURL(state, chain, fields);\n var body = 'geneids=' + encodeURIComponent(JSON.stringify(geneids));\n var headers = {\n 'Content-Type': 'application/x-www-form-urlencoded'\n };\n return LocusZoom.createCORSPromise('POST', url, body, headers);\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data) {\n return chain;\n }\n var constraint_fields = ['bp', 'exp_lof', 'exp_mis', 'exp_syn', 'lof_z', 'mis_z', 'mu_lof', 'mu_mis','mu_syn', 'n_exons', 'n_lof', 'n_mis', 'n_syn', 'pLI', 'syn_z'];\n chain.body.forEach(function(gene, i) {\n var gene_id = gene.gene_id;\n if (gene_id.indexOf('.')) {\n gene_id = gene_id.substr(0, gene_id.indexOf('.'));\n }\n constraint_fields.forEach(function(field) {\n // Do not overwrite any fields defined in the original gene source\n if (typeof chain.body[i][field] != 'undefined') { return; }\n if (data[gene_id]) {\n var val = data[gene_id][field];\n if (typeof val == 'number' && val.toString().indexOf('.') !== -1) {\n val = parseFloat(val.toFixed(2));\n }\n chain.body[i][field] = val;\n } else {\n // If the gene did not come back in the response then set the same field with a null values\n chain.body[i][field] = null;\n }\n });\n });\n return chain.body;\n};\n\n/**\n * Data Source for Recombination Rate Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.RecombinationRateSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'RecombLZ');\n\nLocusZoom.Data.RecombinationRateSource.prototype.getURL = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n\n if (build) { // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = (build === 'GRCh38') ? 16 : 15;\n }\n return this.url + '?filter=id in ' + source +\n \" and chromosome eq '\" + state.chr + \"'\" +\n ' and position le ' + state.end +\n ' and position ge ' + state.start;\n};\n\n/**\n * Data Source for Interval Annotation Data (e.g. BED Tracks), as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.IntervalSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'IntervalLZ');\n\nLocusZoom.Data.IntervalSource.prototype.getURL = function(state, chain, fields) {\n var source = chain.header.bedtracksource || this.params.source;\n return this.url + '?filter=id in ' + source +\n \" and chromosome eq '\" + state.chr + \"'\" +\n ' and start le ' + state.end +\n ' and end ge ' + state.start;\n};\n\n/**\n * Data Source for static blobs of JSON Data. This does not perform additional parsing, and therefore it is the\n * responsibility of the user to pass information in a format that can be read and understood by the chosen plot.\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.StaticSource = LocusZoom.Data.Source.extend(function(data) {\n /** @member {Object} */\n this._data = data;\n},'StaticJSON');\n\nLocusZoom.Data.StaticSource.prototype.getRequest = function(state, chain, fields) {\n return Promise.resolve(this._data);\n};\n\nLocusZoom.Data.StaticSource.prototype.toJSON = function() {\n return [Object.getPrototypeOf(this).constructor.SOURCE_NAME, this._data];\n};\n\n/**\n * Data source for PheWAS data\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {String[]} init.params.build This datasource expects to be provided the name of the genome build that will\n * be used to provide pheWAS results for this position. Note positions may not translate between builds.\n */\nLocusZoom.Data.PheWASSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'PheWASLZ');\nLocusZoom.Data.PheWASSource.prototype.getURL = function(state, chain, fields) {\n var build = (state.genome_build ? [state.genome_build] : null) || this.params.build;\n if (!build || !Array.isArray(build) || !build.length) {\n throw new Error(['Data source', this.constructor.SOURCE_NAME, 'requires that you specify array of one or more desired genome build names'].join(' '));\n }\n var url = [\n this.url,\n \"?filter=variant eq '\", encodeURIComponent(state.variant), \"'&format=objects&\",\n build.map(function(item) {return 'build=' + encodeURIComponent(item);}).join('&')\n ];\n return url.join('');\n};\n\n/**\n * Base class for \"connectors\"- this is meant to be subclassed, rather than used directly.\n *\n * A connector is a source that makes no server requests and caches no data of its own. Instead, it decides how to\n * combine data from other sources in the chain. Connectors are useful when we want to request (or calculate) some\n * useful piece of information once, but apply it to many different kinds of record types.\n *\n * Typically, a subclass will implement the field merging logic in `combineChainBody`.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object} init Configuration for this source\n * @param {Object} init.sources Specify how the hard-coded logic should find the data it relies on in the chain,\n * as {internal_name: chain_source_id} pairs. This allows writing a reusable connector that does not need to make\n * assumptions about what namespaces a source is using.\n * @type {*|Function}\n */\nLocusZoom.Data.ConnectorSource = LocusZoom.Data.Source.extend(function(init) {\n if (!init || !init.sources) {\n throw new Error('Connectors must specify the data they require as init.sources = {internal_name: chain_source_id}} pairs');\n }\n\n /**\n * Tells the connector how to find the data it relies on\n *\n * For example, a connector that applies burden test information to the genes layer might specify:\n * {gene_ns: \"gene\", aggregation_ns: \"aggregation\"}\n *\n * @member {Object}\n */\n this._source_name_mapping = init.sources;\n\n // Validate that this source has been told how to find the required information\n var specified_ids = Object.keys(init.sources);\n var self = this;\n this.REQUIRED_SOURCES.forEach(function (k) {\n if (specified_ids.indexOf(k) === -1) {\n throw new Error('Configuration for ' + self.constructor.SOURCE_NAME + ' must specify a source ID corresponding to ' + k);\n }\n });\n this.parseInit(init);\n}, 'ConnectorSource');\n\n/** @property {String[]} Specifies the sources that must be provided in the original config object */\nLocusZoom.Data.ConnectorSource.prototype.REQUIRED_SOURCES = [];\n\nLocusZoom.Data.ConnectorSource.prototype.parseInit = function(init) {}; // Stub\n\nLocusZoom.Data.ConnectorSource.prototype.getRequest = function(state, chain, fields) {\n // Connectors do not request their own data by definition, but they *do* depend on other sources having been loaded\n // first. This method performs basic validation, and preserves the accumulated body from the chain so far.\n var self = this;\n Object.keys(this._source_name_mapping).forEach(function(ns) {\n var chain_source_id = self._source_name_mapping[ns];\n if (chain.discrete && !chain.discrete[chain_source_id]) {\n throw new Error(self.constructor.SOURCE_NAME + ' cannot be used before loading required data for: ' + chain_source_id);\n }\n });\n return Promise.resolve(chain.body || []);\n};\n\nLocusZoom.Data.ConnectorSource.prototype.parseResponse = function(data, chain, fields, outnames, trans) {\n // A connector source does not update chain.discrete, but it may use it. It bypasses data formatting\n // and field selection (both are assumed to have been done already, by the previous sources this draws from)\n\n // Because of how the chain works, connectors are not very good at applying new transformations or namespacing.\n // Typically connectors are called with `connector_name:all` in the fields array.\n return Promise.resolve(this.combineChainBody(data, chain, fields, outnames, trans))\n .then(function(new_body) {\n return {header: chain.header || {}, discrete: chain.discrete || {}, body: new_body};\n });\n};\n\nLocusZoom.Data.ConnectorSource.prototype.combineChainBody = function(records, chain) {\n // Stub method: specifies how to combine the data\n throw new Error('This method must be implemented in a subclass');\n};\n","/* global LocusZoom */\n'use strict';\n\n/**\n * An independent LocusZoom object that renders a unique set of data and subpanels.\n * Many such LocusZoom objects can exist simultaneously on a single page, each having its own layout.\n *\n * This creates a new plot instance, but does not immediately render it. For practical use, it may be more convenient\n * to use the `LocusZoom.populate` helper method.\n *\n * @class\n * @param {String} id The ID of the plot. Often corresponds to the ID of the container element on the page\n * where the plot is rendered..\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n*/\nLocusZoom.Plot = function(id, datasource, layout) {\n /** @member Boolean} */\n this.initialized = false;\n // TODO: This makes sense for all other locuszoom elements to have; determine whether this is interface boilerplate or something that can be removed\n this.parent_plot = this;\n\n /** @member {String} */\n this.id = id;\n\n /** @member {Element} */\n this.container = null;\n /**\n * Selector for a node that will contain the plot. (set externally by populate methods)\n * @member {d3.selection}\n */\n this.svg = null;\n\n /** @member {Object.} */\n this.panels = {};\n /**\n * TODO: This is currently used by external classes that manipulate the parent and may indicate room for a helper method in the api to coordinate boilerplate\n * @protected\n * @member {String[]}\n */\n this.panel_ids_by_y_index = [];\n\n /**\n * Notify each child panel of the plot of changes in panel ordering/ arrangement\n */\n this.applyPanelYIndexesToPanelLayouts = function() {\n this.panel_ids_by_y_index.forEach(function(pid, idx) {\n this.panels[pid].layout.y_index = idx;\n }.bind(this));\n };\n\n /**\n * Get the qualified ID pathname for the plot\n * @returns {String}\n */\n this.getBaseId = function() {\n return this.id;\n };\n\n /**\n * Track update operations (reMap) performed on all child panels, and notify the parent plot when complete\n * TODO: Reconsider whether we need to be tracking this as global state outside of context of specific operations\n * @protected\n * @member {Promise[]}\n */\n this.remap_promises = [];\n\n if (typeof layout == 'undefined') {\n /**\n * The layout is a serializable object used to describe the composition of the Plot\n * If no layout was passed, use the Standard Association Layout\n * Otherwise merge whatever was passed with the Default Layout\n * TODO: Review description; we *always* merge with default layout?\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge({}, LocusZoom.Layouts.get('plot', 'standard_association'));\n } else {\n this.layout = layout;\n }\n LocusZoom.Layouts.merge(this.layout, LocusZoom.Plot.DefaultLayout);\n\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original plot state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n\n\n /**\n * Create a shortcut to the state in the layout on the Plot. Tracking in the layout allows the plot to be created\n * with initial state/setup.\n *\n * Tracks state of the plot, eg start and end position\n * @member {Object}\n */\n this.state = this.layout.state;\n\n /** @member {LocusZoom.Data.Requester} */\n this.lzd = new LocusZoom.Data.Requester(datasource);\n\n /**\n * Window.onresize listener (responsive layouts only)\n * TODO: .on appears to return a selection, not a listener? Check logic here\n * https://github.com/d3/d3-selection/blob/00b904b9bcec4dfaf154ae0bbc777b1fc1d7bc08/test/selection/on-test.js#L11\n * @deprecated\n * @member {d3.selection}\n */\n this.window_onresize = null;\n\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [], // Select or unselect\n 'element_selection': [], // Element becomes active (only)\n 'match_requested': [], // A data layer is attempting to highlight matching points (internal use only)\n 'panel_removed': [],\n 'state_changed': [] // Only triggered when a state change causes rerender\n };\n\n /**\n * @callback eventCallback\n * @param {object} eventData A description of the event\n * @param {String|null} eventData.sourceID The unique identifier (eg plot or parent name) of the element that\n * triggered the event. Will be automatically filled in if not explicitly provided.\n * @param {Object|null} eventData.context Any additional information to be passed to the callback, eg the data\n * associated with a clicked plot element\n */\n\n /**\n * There are several events that a LocusZoom plot can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following plot-level events are currently supported:\n * - `layout_changed` - context: plot - Any aspect of the plot's layout (including dimensions or state) has changed.\n * - `data_requested` - context: plot - A request for new data from any data source used in the plot has been made.\n * - `data_rendered` - context: plot - Data from a request has been received and rendered in the plot.\n * - `element_clicked` - context: plot - A data element in any of the plot's data layers has been clicked.\n * - `element_selection` - context: plot - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `plot.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * plot itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} hook\n * @returns {function} The registered event listener\n */\n this.on = function(event, hook) {\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Plot}\n */\n this.off = function(event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n * @param {string} event A known event name\n * @param {*} eventData Data or event description that will be passed to the event listener\n * @returns {LocusZoom.Plot}\n */\n this.emit = function(event, eventData) {\n // TODO: there are small differences between the emit implementation between plots and panels. In the future,\n // DRY this code via mixins, and make sure to keep the interfaces compatible when refactoring.\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n var sourceID = this.getBaseId();\n var self = this;\n this.event_hooks[event].forEach(function(hookToRun) {\n var eventContext;\n if (eventData && eventData.sourceID) {\n // If we detect that an event originated elsewhere (via bubbling or externally), preserve the context\n // when re-emitting the event to plot-level listeners\n eventContext = eventData;\n } else {\n eventContext = {sourceID: sourceID, data: eventData || null};\n }\n // By default, any handlers fired here (either directly, or bubbled) will see the plot as the\n // value of `this`. If a bound function is registered as a handler, the previously bound `this` will\n // override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n return this;\n };\n\n /**\n * Get an object with the x and y coordinates of the plot's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the plot\n * @returns {{x: Number, y: Number, width: Number, height: Number}}\n */\n this.getPageOrigin = function() {\n var bounding_client_rect = this.svg.node().getBoundingClientRect();\n var x_offset = document.documentElement.scrollLeft || document.body.scrollLeft;\n var y_offset = document.documentElement.scrollTop || document.body.scrollTop;\n var container = this.svg.node();\n while (container.parentNode !== null) {\n container = container.parentNode;\n if (container !== document && d3.select(container).style('position') !== 'static') {\n x_offset = -1 * container.getBoundingClientRect().left;\n y_offset = -1 * container.getBoundingClientRect().top;\n break;\n }\n }\n return {\n x: x_offset + bounding_client_rect.left,\n y: y_offset + bounding_client_rect.top,\n width: bounding_client_rect.width,\n height: bounding_client_rect.height\n };\n };\n\n /**\n * Get the top and left offset values for the plot's container element (the div that was populated)\n * @returns {{top: number, left: number}}\n */\n this.getContainerOffset = function() {\n var offset = { top: 0, left: 0 };\n var container = this.container.offsetParent || null;\n while (container !== null) {\n offset.top += container.offsetTop;\n offset.left += container.offsetLeft;\n container = container.offsetParent || null;\n }\n return offset;\n };\n\n //\n /**\n * Event information describing interaction (e.g. panning and zooming) is stored on the plot\n * TODO: Add/ document details of interaction structure as we expand\n * @member {{panel_id: String, linked_panel_ids: Array, x_linked: *, dragging: *, zooming: *}}\n * @returns {LocusZoom.Plot}\n */\n this.interaction = {};\n\n /**\n * Track whether the target panel can respond to mouse interaction events\n * @param {String} panel_id\n * @returns {boolean}\n */\n this.canInteract = function(panel_id) {\n panel_id = panel_id || null;\n if (panel_id) {\n return ((typeof this.interaction.panel_id == 'undefined' || this.interaction.panel_id === panel_id) && !this.loading_data);\n } else {\n return !(this.interaction.dragging || this.interaction.zooming || this.loading_data);\n }\n };\n\n // Initialize the layout\n this.initializeLayout();\n return this;\n};\n\n/**\n * Default/ expected configuration parameters for basic plotting; most plots will override\n *\n * @protected\n * @static\n * @type {Object}\n */\nLocusZoom.Plot.DefaultLayout = {\n state: {},\n width: 1,\n height: 1,\n min_width: 1,\n min_height: 1,\n responsive_resize: false, // Allowed values: false, \"width_only\", \"both\" (synonym for true)\n aspect_ratio: 1,\n panels: [],\n dashboard: {\n components: []\n },\n panel_boundaries: true,\n mouse_guide: true\n};\n\n/**\n * Helper method to sum the proportional dimensions of panels, a value that's checked often as panels are added/removed\n * @param {('Height'|'Width')} dimension\n * @returns {number}\n */\nLocusZoom.Plot.prototype.sumProportional = function(dimension) {\n if (dimension !== 'height' && dimension !== 'width') {\n throw new Error('Bad dimension value passed to LocusZoom.Plot.prototype.sumProportional');\n }\n var total = 0;\n for (var id in this.panels) {\n // Ensure every panel contributing to the sum has a non-zero proportional dimension\n if (!this.panels[id].layout['proportional_' + dimension]) {\n this.panels[id].layout['proportional_' + dimension] = 1 / Object.keys(this.panels).length;\n }\n total += this.panels[id].layout['proportional_' + dimension];\n }\n return total;\n};\n\n/**\n * Resize the plot to fit the bounding container\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.rescaleSVG = function() {\n var clientRect = this.svg.node().getBoundingClientRect();\n this.setDimensions(clientRect.width, clientRect.height);\n return this;\n};\n\n/**\n * Prepare the plot for first use by performing parameter validation, setting up panels, and calculating dimensions\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.initializeLayout = function() {\n\n // Sanity check layout values\n if (isNaN(this.layout.width) || this.layout.width <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.height) || this.layout.height <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.aspect_ratio) || this.layout.aspect_ratio <= 0) {\n throw new Error('Plot layout parameter `aspect_ratio` must be a positive number');\n }\n if (this.layout.responsive_resize === true) {\n // Backwards compatible support\n console.warn('LocusZoom \"responsive_resize\" specifies a deprecated value. The new value should be \"both\". Please update your layout.');\n this.layout.responsive_resize = 'both';\n }\n var RESIZE_MODES = [false, 'both', 'width_only'];\n if (RESIZE_MODES.indexOf(this.layout.responsive_resize) === -1) {\n throw new Error('LocusZoom option \"responsive_resize\" should specify one of the following modes: ' + RESIZE_MODES.join(', '));\n }\n\n // If this is a responsive layout then set a namespaced/unique onresize event listener on the window\n if (this.layout.responsive_resize) {\n this.window_onresize = d3.select(window).on('resize.lz-' + this.id, function() {\n this.rescaleSVG();\n }.bind(this));\n // Forcing one additional setDimensions() call after the page is loaded clears up\n // any disagreements between the initial layout and the loaded responsive container's size\n d3.select(window).on('load.lz-' + this.id, function() {\n this.setDimensions();\n }.bind(this));\n }\n\n // Add panels\n this.layout.panels.forEach(function(panel_layout) {\n this.addPanel(panel_layout);\n }.bind(this));\n\n return this;\n};\n\n/**\n * Set the dimensions for a plot, and ensure that panels are sized and positioned correctly.\n *\n * If dimensions are provided, resizes each panel proportionally to match the new plot dimensions. Otherwise,\n * calculates the appropriate plot dimensions based on all panels.\n * @param {Number} [width] If provided and larger than minimum size, set plot to this width\n * @param {Number} [height] If provided and larger than minimum size, set plot to this height\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.setDimensions = function(width, height) {\n\n var id;\n\n // Update minimum allowable width and height by aggregating minimums from panels, then apply minimums to containing element.\n var min_width = parseFloat(this.layout.min_width) || 0;\n var min_height = parseFloat(this.layout.min_height) || 0;\n for (id in this.panels) {\n min_width = Math.max(min_width, this.panels[id].layout.min_width);\n if (parseFloat(this.panels[id].layout.min_height) > 0 && parseFloat(this.panels[id].layout.proportional_height) > 0) {\n min_height = Math.max(min_height, (this.panels[id].layout.min_height / this.panels[id].layout.proportional_height));\n }\n }\n this.layout.min_width = Math.max(min_width, 1);\n this.layout.min_height = Math.max(min_height, 1);\n d3.select(this.svg.node().parentNode).style({\n 'min-width': this.layout.min_width + 'px',\n 'min-height': this.layout.min_height + 'px'\n });\n\n // If width and height arguments were passed then adjust them against plot minimums if necessary.\n // Then resize the plot and proportionally resize panels to fit inside the new plot dimensions.\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n // Override discrete values if resizing responsively\n if (this.layout.responsive_resize) {\n // All resize modes will affect width\n if (this.svg) {\n this.layout.width = Math.max(this.svg.node().parentNode.getBoundingClientRect().width, this.layout.min_width);\n }\n\n if (this.layout.responsive_resize === 'both') { // Then also change the height\n this.layout.height = this.layout.width / this.layout.aspect_ratio;\n if (this.layout.height < this.layout.min_height) {\n this.layout.height = this.layout.min_height;\n this.layout.width = this.layout.height * this.layout.aspect_ratio;\n }\n }\n }\n // Resize/reposition panels to fit, update proportional origins if necessary\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n var panel_width = this.layout.width;\n var panel_height = this.panels[panel_id].layout.proportional_height * this.layout.height;\n this.panels[panel_id].setDimensions(panel_width, panel_height);\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n this.panels[panel_id].layout.proportional_origin.y = y_offset / this.layout.height;\n y_offset += panel_height;\n this.panels[panel_id].dashboard.update();\n }.bind(this));\n }\n\n // If width and height arguments were NOT passed (and panels exist) then determine the plot dimensions\n // by making it conform to panel dimensions, assuming panels are already positioned correctly.\n else if (Object.keys(this.panels).length) {\n this.layout.width = 0;\n this.layout.height = 0;\n for (id in this.panels) {\n this.layout.width = Math.max(this.panels[id].layout.width, this.layout.width);\n this.layout.height += this.panels[id].layout.height;\n }\n this.layout.width = Math.max(this.layout.width, this.layout.min_width);\n this.layout.height = Math.max(this.layout.height, this.layout.min_height);\n }\n\n // Keep aspect ratio in agreement with dimensions\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n\n // Apply layout width and height as discrete values or viewbox values\n if (this.svg !== null) {\n if (this.layout.responsive_resize === 'both') {\n this.svg\n .attr('viewBox', '0 0 ' + this.layout.width + ' ' + this.layout.height)\n .attr('preserveAspectRatio', 'xMinYMin meet');\n } else {\n this.svg.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n }\n\n // If the plot has been initialized then trigger some necessary render functions\n if (this.initialized) {\n this.panel_boundaries.position();\n this.dashboard.update();\n this.curtain.update();\n this.loader.update();\n }\n\n return this.emit('layout_changed');\n};\n\n/**\n * Create a new panel from a layout, and handle the work of initializing and placing the panel on the plot\n * @param {Object} layout\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Plot.prototype.addPanel = function(layout) {\n\n // Sanity checks\n if (typeof layout !== 'object') {\n throw new Error('Invalid panel layout passed to LocusZoom.Plot.prototype.addPanel()');\n }\n\n // Create the Panel and set its parent\n var panel = new LocusZoom.Panel(layout, this);\n\n // Store the Panel on the Plot\n this.panels[panel.id] = panel;\n\n // If a discrete y_index was set in the layout then adjust other panel y_index values to accommodate this one\n if (panel.layout.y_index !== null && !isNaN(panel.layout.y_index)\n && this.panel_ids_by_y_index.length > 0) {\n // Negative y_index values should count backwards from the end, so convert negatives to appropriate values here\n if (panel.layout.y_index < 0) {\n panel.layout.y_index = Math.max(this.panel_ids_by_y_index.length + panel.layout.y_index, 0);\n }\n this.panel_ids_by_y_index.splice(panel.layout.y_index, 0, panel.id);\n this.applyPanelYIndexesToPanelLayouts();\n } else {\n var length = this.panel_ids_by_y_index.push(panel.id);\n this.panels[panel.id].layout.y_index = length - 1;\n }\n\n // Determine if this panel was already in the layout.panels array.\n // If it wasn't, add it. Either way store the layout.panels array index on the panel.\n var layout_idx = null;\n this.layout.panels.forEach(function(panel_layout, idx) {\n if (panel_layout.id === panel.id) { layout_idx = idx; }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.panels.push(this.panels[panel.id].layout) - 1;\n }\n this.panels[panel.id].layout_idx = layout_idx;\n\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n this.positionPanels();\n // Initialize and load data into the new panel\n this.panels[panel.id].initialize();\n this.panels[panel.id].reMap();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n\n return this.panels[panel.id];\n};\n\n\n/**\n * Clear all state, tooltips, and other persisted data associated with one (or all) panel(s) in the plot\n *\n * This is useful when reloading an existing plot with new data, eg \"click for genome region\" links.\n * This is a utility method for custom usage. It is not fired automatically during normal rerender of existing panels\n * @param {String} [panelId] If provided, clear state for only this panel. Otherwise, clear state for all panels.\n * @param {('wipe'|'reset')} [mode='wipe'] Optionally specify how state should be cleared. `wipe` deletes all data\n * and is useful for when the panel is being removed; `reset` is best when the panel will be reused in place.\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.clearPanelData = function(panelId, mode) {\n mode = mode || 'wipe';\n\n // TODO: Add unit tests for this method\n var panelsList;\n if (panelId) {\n panelsList = [panelId];\n } else {\n panelsList = Object.keys(this.panels);\n }\n var self = this;\n panelsList.forEach(function(pid) {\n self.panels[pid].data_layer_ids_by_z_index.forEach(function(dlid) {\n var layer = self.panels[pid].data_layers[dlid];\n layer.destroyAllTooltips();\n\n delete self.layout.state[pid + '.' + dlid];\n if(mode === 'reset') {\n layer.setDefaultState();\n }\n });\n });\n return this;\n};\n\n/**\n * Remove the panel from the plot, and clear any state, tooltips, or other visual elements belonging to nested content\n * @param {String} id\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.removePanel = function(id) {\n if (!this.panels[id]) {\n throw new Error('Unable to remove panel, ID not found: ' + id);\n }\n\n // Hide all panel boundaries\n this.panel_boundaries.hide();\n\n // Destroy all tooltips and state vars for all data layers on the panel\n this.clearPanelData(id);\n\n // Remove all panel-level HTML overlay elements\n this.panels[id].loader.hide();\n this.panels[id].dashboard.destroy(true);\n this.panels[id].curtain.hide();\n\n // Remove the svg container for the panel if it exists\n if (this.panels[id].svg.container) {\n this.panels[id].svg.container.remove();\n }\n\n // Delete the panel and its presence in the plot layout and state\n this.layout.panels.splice(this.panels[id].layout_idx, 1);\n delete this.panels[id];\n delete this.layout.state[id];\n\n // Update layout_idx values for all remaining panels\n this.layout.panels.forEach(function(panel_layout, idx) {\n this.panels[panel_layout.id].layout_idx = idx;\n }.bind(this));\n\n // Remove the panel id from the y_index array\n this.panel_ids_by_y_index.splice(this.panel_ids_by_y_index.indexOf(id), 1);\n this.applyPanelYIndexesToPanelLayouts();\n\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n // Allow the plot to shrink when panels are removed, by forcing it to recalculate min dimensions from scratch\n this.layout.min_height = this._base_layout.min_height;\n this.layout.min_width = this._base_layout.min_width;\n\n this.positionPanels();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n\n this.emit('panel_removed', id);\n\n return this;\n};\n\n\n/**\n * Automatically position panels based on panel positioning rules and values.\n * Keep panels from overlapping vertically by adjusting origins, and keep the sum of proportional heights at 1.\n *\n * TODO: This logic currently only supports dynamic positioning of panels to prevent overlap in a VERTICAL orientation.\n * Some framework exists for positioning panels in horizontal orientations as well (width, proportional_width, origin.x, etc.)\n * but the logic for keeping these user-definable values straight approaches the complexity of a 2D box-packing algorithm.\n * That's complexity we don't need right now, and may not ever need, so it's on hiatus until a use case materializes.\n */\nLocusZoom.Plot.prototype.positionPanels = function() {\n\n var id;\n\n // We want to enforce that all x-linked panels have consistent horizontal margins\n // (to ensure that aligned items stay aligned despite inconsistent initial layout parameters)\n // NOTE: This assumes panels have consistent widths already. That should probably be enforced too!\n var x_linked_margins = { left: 0, right: 0 };\n\n // Proportional heights for newly added panels default to null unless explicitly set, so determine appropriate\n // proportional heights for all panels with a null value from discretely set dimensions.\n // Likewise handle default nulls for proportional widths, but instead just force a value of 1 (full width)\n for (id in this.panels) {\n if (this.panels[id].layout.proportional_height === null) {\n this.panels[id].layout.proportional_height = this.panels[id].layout.height / this.layout.height;\n }\n if (this.panels[id].layout.proportional_width === null) {\n this.panels[id].layout.proportional_width = 1;\n }\n if (this.panels[id].layout.interaction.x_linked) {\n x_linked_margins.left = Math.max(x_linked_margins.left, this.panels[id].layout.margin.left);\n x_linked_margins.right = Math.max(x_linked_margins.right, this.panels[id].layout.margin.right);\n }\n }\n\n // Sum the proportional heights and then adjust all proportionally so that the sum is exactly 1\n var total_proportional_height = this.sumProportional('height');\n if (!total_proportional_height) {\n return this;\n }\n var proportional_adjustment = 1 / total_proportional_height;\n for (id in this.panels) {\n this.panels[id].layout.proportional_height *= proportional_adjustment;\n }\n\n // Update origins on all panels without changing plot-level dimensions yet\n // Also apply x-linked margins to x-linked panels, updating widths as needed\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n y_offset += this.panels[panel_id].layout.height;\n if (this.panels[panel_id].layout.interaction.x_linked) {\n var delta = Math.max(x_linked_margins.left - this.panels[panel_id].layout.margin.left, 0)\n + Math.max(x_linked_margins.right - this.panels[panel_id].layout.margin.right, 0);\n this.panels[panel_id].layout.width += delta;\n this.panels[panel_id].layout.margin.left = x_linked_margins.left;\n this.panels[panel_id].layout.margin.right = x_linked_margins.right;\n this.panels[panel_id].layout.cliparea.origin.x = x_linked_margins.left;\n }\n }.bind(this));\n var calculated_plot_height = y_offset;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].layout.proportional_origin.y = this.panels[panel_id].layout.origin.y / calculated_plot_height;\n }.bind(this));\n\n // Update dimensions on the plot to accommodate repositioned panels\n this.setDimensions();\n\n // Set dimensions on all panels using newly set plot-level dimensions and panel-level proportional dimensions\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].setDimensions(this.layout.width * this.panels[panel_id].layout.proportional_width,\n this.layout.height * this.panels[panel_id].layout.proportional_height);\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Prepare the first rendering of the plot. This includes initializing the individual panels, but also creates shared\n * elements such as mouse events, panel guides/boundaries, and loader/curtain.\n *\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.initialize = function() {\n\n // Ensure proper responsive class is present on the containing node if called for\n if (this.layout.responsive_resize) {\n d3.select(this.container).classed('lz-container-responsive', true);\n }\n\n // Create an element/layer for containing mouse guides\n if (this.layout.mouse_guide) {\n var mouse_guide_svg = this.svg.append('g')\n .attr('class', 'lz-mouse_guide').attr('id', this.id + '.mouse_guide');\n var mouse_guide_vertical_svg = mouse_guide_svg.append('rect')\n .attr('class', 'lz-mouse_guide-vertical').attr('x',-1);\n var mouse_guide_horizontal_svg = mouse_guide_svg.append('rect')\n .attr('class', 'lz-mouse_guide-horizontal').attr('y',-1);\n this.mouse_guide = {\n svg: mouse_guide_svg,\n vertical: mouse_guide_vertical_svg,\n horizontal: mouse_guide_horizontal_svg\n };\n }\n\n // Add curtain and loader prototpyes to the plot\n this.curtain = LocusZoom.generateCurtain.call(this);\n this.loader = LocusZoom.generateLoader.call(this);\n\n // Create the panel_boundaries object with show/position/hide methods\n this.panel_boundaries = {\n parent: this,\n hide_timeout: null,\n showing: false,\n dragging: false,\n selectors: [],\n corner_selector: null,\n show: function() {\n // Generate panel boundaries\n if (!this.showing && !this.parent.curtain.showing) {\n this.showing = true;\n // Loop through all panels to create a horizontal boundary for each\n this.parent.panel_ids_by_y_index.forEach(function(panel_id, panel_idx) {\n var selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip')\n .attr('class', 'lz-panel-boundary')\n .attr('title', 'Resize panel');\n selector.append('span');\n var panel_resize_drag = d3.behavior.drag();\n panel_resize_drag.on('dragstart', function() { this.dragging = true; }.bind(this));\n panel_resize_drag.on('dragend', function() { this.dragging = false; }.bind(this));\n panel_resize_drag.on('drag', function() {\n // First set the dimensions on the panel we're resizing\n var this_panel = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]];\n var original_panel_height = this_panel.layout.height;\n this_panel.setDimensions(this_panel.layout.width, this_panel.layout.height + d3.event.dy);\n var panel_height_change = this_panel.layout.height - original_panel_height;\n var new_calculated_plot_height = this.parent.layout.height + panel_height_change;\n // Next loop through all panels.\n // Update proportional dimensions for all panels including the one we've resized using discrete heights.\n // Reposition panels with a greater y-index than this panel to their appropriate new origin.\n this.parent.panel_ids_by_y_index.forEach(function(loop_panel_id, loop_panel_idx) {\n var loop_panel = this.parent.panels[this.parent.panel_ids_by_y_index[loop_panel_idx]];\n loop_panel.layout.proportional_height = loop_panel.layout.height / new_calculated_plot_height;\n if (loop_panel_idx > panel_idx) {\n loop_panel.setOrigin(loop_panel.layout.origin.x, loop_panel.layout.origin.y + panel_height_change);\n loop_panel.dashboard.position();\n }\n }.bind(this));\n // Reset dimensions on the entire plot and reposition panel boundaries\n this.parent.positionPanels();\n this.position();\n }.bind(this));\n selector.call(panel_resize_drag);\n this.parent.panel_boundaries.selectors.push(selector);\n }.bind(this));\n // Create a corner boundary / resize element on the bottom-most panel that resizes the entire plot\n var corner_selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip')\n .attr('class', 'lz-panel-corner-boundary')\n .attr('title', 'Resize plot');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-outer');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-inner');\n var corner_drag = d3.behavior.drag();\n corner_drag.on('dragstart', function() { this.dragging = true; }.bind(this));\n corner_drag.on('dragend', function() { this.dragging = false; }.bind(this));\n corner_drag.on('drag', function() {\n this.setDimensions(this.layout.width + d3.event.dx, this.layout.height + d3.event.dy);\n }.bind(this.parent));\n corner_selector.call(corner_drag);\n this.parent.panel_boundaries.corner_selector = corner_selector;\n }\n return this.position();\n },\n position: function() {\n if (!this.showing) { return this; }\n // Position panel boundaries\n var plot_page_origin = this.parent.getPageOrigin();\n this.selectors.forEach(function(selector, panel_idx) {\n var panel_page_origin = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].getPageOrigin();\n var left = plot_page_origin.x;\n var top = panel_page_origin.y + this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].layout.height - 12;\n var width = this.parent.layout.width - 1;\n selector.style({\n top: top + 'px',\n left: left + 'px',\n width: width + 'px'\n });\n selector.select('span').style({\n width: width + 'px'\n });\n }.bind(this));\n // Position corner selector\n var corner_padding = 10;\n var corner_size = 16;\n this.corner_selector.style({\n top: (plot_page_origin.y + this.parent.layout.height - corner_padding - corner_size) + 'px',\n left: (plot_page_origin.x + this.parent.layout.width - corner_padding - corner_size) + 'px'\n });\n return this;\n },\n hide: function() {\n if (!this.showing) { return this; }\n this.showing = false;\n // Remove panel boundaries\n this.selectors.forEach(function(selector) { selector.remove(); });\n this.selectors = [];\n // Remove corner boundary\n this.corner_selector.remove();\n this.corner_selector = null;\n return this;\n }\n };\n\n // Show panel boundaries stipulated by the layout (basic toggle, only show on mouse over plot)\n if (this.layout.panel_boundaries) {\n d3.select(this.svg.node().parentNode).on('mouseover.' + this.id + '.panel_boundaries', function() {\n clearTimeout(this.panel_boundaries.hide_timeout);\n this.panel_boundaries.show();\n }.bind(this));\n d3.select(this.svg.node().parentNode).on('mouseout.' + this.id + '.panel_boundaries', function() {\n this.panel_boundaries.hide_timeout = setTimeout(function() {\n this.panel_boundaries.hide();\n }.bind(this), 300);\n }.bind(this));\n }\n\n // Create the dashboard object and immediately show it\n this.dashboard = new LocusZoom.Dashboard(this).show();\n\n // Initialize all panels\n for (var id in this.panels) {\n this.panels[id].initialize();\n }\n\n // Define plot-level mouse events\n var namespace = '.' + this.id;\n if (this.layout.mouse_guide) {\n var mouseout_mouse_guide = function() {\n this.mouse_guide.vertical.attr('x', -1);\n this.mouse_guide.horizontal.attr('y', -1);\n }.bind(this);\n var mousemove_mouse_guide = function() {\n var coords = d3.mouse(this.svg.node());\n this.mouse_guide.vertical.attr('x', coords[0]);\n this.mouse_guide.horizontal.attr('y', coords[1]);\n }.bind(this);\n this.svg\n .on('mouseout' + namespace + '-mouse_guide', mouseout_mouse_guide)\n .on('touchleave' + namespace + '-mouse_guide', mouseout_mouse_guide)\n .on('mousemove' + namespace + '-mouse_guide', mousemove_mouse_guide);\n }\n var mouseup = function() {\n this.stopDrag();\n }.bind(this);\n var mousemove = function() {\n if (this.interaction.dragging) {\n var coords = d3.mouse(this.svg.node());\n if (d3.event) { d3.event.preventDefault(); }\n this.interaction.dragging.dragged_x = coords[0] - this.interaction.dragging.start_x;\n this.interaction.dragging.dragged_y = coords[1] - this.interaction.dragging.start_y;\n this.panels[this.interaction.panel_id].render();\n this.interaction.linked_panel_ids.forEach(function(panel_id) {\n this.panels[panel_id].render();\n }.bind(this));\n }\n }.bind(this);\n this.svg\n .on('mouseup' + namespace, mouseup)\n .on('touchend' + namespace, mouseup)\n .on('mousemove' + namespace, mousemove)\n .on('touchmove' + namespace, mousemove);\n\n // Add an extra namespaced mouseup handler to the containing body, if there is one\n // This helps to stop interaction events gracefully when dragging outside of the plot element\n if (!d3.select('body').empty()) {\n d3.select('body')\n .on('mouseup' + namespace, mouseup)\n .on('touchend' + namespace, mouseup);\n }\n\n this.on('match_requested', function(eventData) {\n // Layers can broadcast that a specific point has been selected, and the plot will tell every other layer\n // to look for that value. Whenever a point is de-selected, it clears the match.\n var data = eventData.data;\n var to_send = (data.active ? data.value : null);\n this.applyState({ lz_match_value: to_send });\n }.bind(this));\n\n this.initialized = true;\n\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n var client_rect = this.svg.node().getBoundingClientRect();\n var width = client_rect.width ? client_rect.width : this.layout.width;\n var height = client_rect.height ? client_rect.height : this.layout.height;\n this.setDimensions(width, height);\n\n return this;\n\n};\n\n/**\n * Refresh (or fetch) a plot's data from sources, regardless of whether position or state has changed\n * @returns {Promise}\n */\nLocusZoom.Plot.prototype.refresh = function() {\n return this.applyState();\n};\n\n\n/**\n * A user-defined callback function that can receive (and potentially act on) new plot data.\n * @callback externalDataCallback\n * @param {Object} new_data The body resulting from a data request. This represents the same information that would be passed to\n * a data layer making an equivalent request.\n */\n\n/**\n * A user-defined callback function that can respond to errors received during a previous operation\n * @callback externalErrorCallback\n * @param err A representation of the error that occurred\n */\n\n/**\n * Allow newly fetched data to be made available outside the LocusZoom plot. For example, a callback could be\n * registered to draw an HTML table of top GWAS hits, and update that table whenever the plot region changes.\n *\n * This is a convenience method for external hooks. It registers an event listener and returns parsed data,\n * using the same fields syntax and underlying methods as data layers.\n *\n * @param {String[]} fields An array of field names and transforms, in the same syntax used by a data layer.\n * Different data sources should be prefixed by the source name.\n * @param {externalDataCallback} success_callback Used defined function that is automatically called any time that\n * new data is received by the plot.\n * @param {Object} [opts] Options\n * @param {externalErrorCallback} [opts.onerror] User defined function that is automatically called if a problem\n * occurs during the data request or subsequent callback operations\n * @param {boolean} [opts.discrete=false] Normally the callback will subscribe to the combined body from the chain,\n * which may not be in a format that matches what the external callback wants to do. If discrete=true, returns the\n * uncombined record info\n * @return {function} The newly created event listener, to allow for later cleanup/removal\n */\nLocusZoom.Plot.prototype.subscribeToData = function(fields, success_callback, opts) {\n opts = opts || {};\n\n // Register an event listener that is notified whenever new data has been rendered\n var error_callback = opts.onerror || function(err) {\n console.log('An error occurred while acting on an external callback', err);\n };\n var self = this;\n\n var listener = function() {\n try {\n self.lzd.getData(self.state, fields)\n .then(function (new_data) {\n success_callback(opts.discrete ? new_data.discrete : new_data.body);\n }).catch(error_callback);\n } catch (error) {\n // In certain cases, errors are thrown before a promise can be generated, and LZ error display seems to rely on these errors bubbling up\n error_callback(error);\n }\n };\n this.on('data_rendered', listener);\n return listener;\n};\n\n/**\n * Update state values and trigger a pull for fresh data on all data sources for all data layers\n * @param state_changes\n * @returns {Promise} A promise that resolves when all data fetch and update operations are complete\n */\nLocusZoom.Plot.prototype.applyState = function(state_changes) {\n state_changes = state_changes || {};\n if (typeof state_changes != 'object') {\n throw new Error('LocusZoom.applyState only accepts an object; ' + (typeof state_changes) + ' given');\n }\n\n // First make a copy of the current (old) state to work with\n var new_state = JSON.parse(JSON.stringify(this.state));\n\n // Apply changes by top-level property to the new state\n for (var property in state_changes) {\n new_state[property] = state_changes[property];\n }\n\n // Validate the new state (may do nothing, may do a lot, depends on how the user has things set up)\n new_state = LocusZoom.validateState(new_state, this.layout);\n\n // Apply new state to the actual state\n for (property in new_state) {\n this.state[property] = new_state[property];\n }\n\n // Generate requests for all panels given new state\n this.emit('data_requested');\n this.remap_promises = [];\n this.loading_data = true;\n for (var id in this.panels) {\n this.remap_promises.push(this.panels[id].reMap());\n }\n\n return Promise.all(this.remap_promises)\n .catch(function(error) {\n console.error(error);\n this.curtain.show(error.message || error);\n this.loading_data = false;\n }.bind(this))\n .then(function() {\n // Update dashboard / components\n this.dashboard.update();\n\n // Apply panel-level state values\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n var panel = this.panels[panel_id];\n panel.dashboard.update();\n // Apply data-layer-level state values\n panel.data_layer_ids_by_z_index.forEach(function(data_layer_id) {\n var data_layer = this.data_layers[data_layer_id];\n var state_id = panel_id + '.' + data_layer_id;\n for (var property in this.state[state_id]) {\n if (!this.state[state_id].hasOwnProperty(property)) { continue; }\n if (Array.isArray(this.state[state_id][property])) {\n this.state[state_id][property].forEach(function(element_id) {\n try {\n this.setElementStatus(property, this.getElementById(element_id), true);\n } catch (e) {\n console.warn('Unable to apply state: ' + state_id + ', ' + property);\n console.error(e);\n }\n }.bind(data_layer));\n }\n }\n }.bind(panel));\n }.bind(this));\n\n // Emit events\n this.emit('layout_changed');\n this.emit('data_rendered');\n this.emit('state_changed', state_changes);\n\n this.loading_data = false;\n\n }.bind(this));\n};\n\n/**\n * Register interactions along the specified axis, provided that the target panel allows interaction.\n *\n * @param {LocusZoom.Panel} panel\n * @param {('x_tick'|'y1_tick'|'y2_tick')} method The direction (axis) along which dragging is being performed.\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.startDrag = function(panel, method) {\n\n panel = panel || null;\n method = method || null;\n\n var axis = null;\n switch (method) {\n case 'background':\n case 'x_tick':\n axis = 'x';\n break;\n case 'y1_tick':\n axis = 'y1';\n break;\n case 'y2_tick':\n axis = 'y2';\n break;\n }\n\n if (!(panel instanceof LocusZoom.Panel) || !axis || !this.canInteract()) { return this.stopDrag(); }\n\n var coords = d3.mouse(this.svg.node());\n this.interaction = {\n panel_id: panel.id,\n linked_panel_ids: panel.getLinkedPanelIds(axis),\n dragging: {\n method: method,\n start_x: coords[0],\n start_y: coords[1],\n dragged_x: 0,\n dragged_y: 0,\n axis: axis\n }\n };\n\n this.svg.style('cursor', 'all-scroll');\n\n return this;\n\n};\n\n/**\n * Process drag interactions across the target panel and synchronize plot state across other panels in sync;\n * clear the event when complete\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.stopDrag = function() {\n\n if (!this.interaction.dragging) { return this; }\n\n if (typeof this.panels[this.interaction.panel_id] != 'object') {\n this.interaction = {};\n return this;\n }\n var panel = this.panels[this.interaction.panel_id];\n\n // Helper function to find the appropriate axis layouts on child data layers\n // Once found, apply the extent as floor/ceiling and remove all other directives\n // This forces all associated axes to conform to the extent generated by a drag action\n var overrideAxisLayout = function(axis, axis_number, extent) {\n panel.data_layer_ids_by_z_index.forEach(function(id) {\n if (panel.data_layers[id].layout[axis + '_axis'].axis === axis_number) {\n panel.data_layers[id].layout[axis + '_axis'].floor = extent[0];\n panel.data_layers[id].layout[axis + '_axis'].ceiling = extent[1];\n delete panel.data_layers[id].layout[axis + '_axis'].lower_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].upper_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].min_extent;\n delete panel.data_layers[id].layout[axis + '_axis'].ticks;\n }\n });\n };\n\n switch(this.interaction.dragging.method) {\n case 'background':\n case 'x_tick':\n if (this.interaction.dragging.dragged_x !== 0) {\n overrideAxisLayout('x', 1, panel.x_extent);\n this.applyState({ start: panel.x_extent[0], end: panel.x_extent[1] });\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n if (this.interaction.dragging.dragged_y !== 0) {\n // TODO: Hardcoded assumption of only two possible axes with single-digit #s (switch/case)\n var y_axis_number = parseInt(this.interaction.dragging.method[1]);\n overrideAxisLayout('y', y_axis_number, panel['y' + y_axis_number + '_extent']);\n }\n break;\n }\n\n this.interaction = {};\n this.svg.style('cursor', null);\n\n return this;\n\n};\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A panel is an abstract class representing a subdivision of the LocusZoom stage\n * to display a distinct data representation as a collection of data layers.\n * @class\n * @param {Object} layout\n * @param {LocusZoom.Plot|null} parent\n*/\nLocusZoom.Panel = function(layout, parent) {\n\n if (typeof layout !== 'object') {\n throw new Error('Unable to create panel, invalid layout');\n }\n\n /** @member {LocusZoom.Plot|null} */\n this.parent = parent || null;\n /** @member {LocusZoom.Plot|null} */\n this.parent_plot = parent;\n\n // Ensure a valid ID is present. If there is no valid ID then generate one\n if (typeof layout.id !== 'string' || !layout.id.length) {\n if (!this.parent) {\n layout.id = 'p' + Math.floor(Math.random() * Math.pow(10,8));\n } else {\n var id = null;\n var generateID = function() {\n id = 'p' + Math.floor(Math.random() * Math.pow(10,8));\n if (id == null || typeof this.parent.panels[id] != 'undefined') {\n id = generateID();\n }\n }.bind(this);\n layout.id = id;\n }\n } else if (this.parent) {\n if (typeof this.parent.panels[layout.id] !== 'undefined') {\n throw new Error('Cannot create panel with id [' + layout.id + ']; panel with that id already exists');\n }\n }\n /** @member {String} */\n this.id = layout.id;\n\n /** @member {Boolean} */\n this.initialized = false;\n /**\n * The index of this panel in the parent plot's `layout.panels`\n * @member {number}\n * */\n this.layout_idx = null;\n /** @member {Object} */\n this.svg = {};\n\n /**\n * A JSON-serializable object used to describe the composition of the Panel\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.Panel.DefaultLayout);\n\n // Define state parameters specific to this panel\n if (this.parent) {\n /** @member {Object} */\n this.state = this.parent.state;\n\n /** @member {String} */\n this.state_id = this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n } else {\n this.state = null;\n this.state_id = null;\n }\n\n /** @member {Object} */\n this.data_layers = {};\n /** @member {String[]} */\n this.data_layer_ids_by_z_index = [];\n\n /** @protected */\n this.applyDataLayerZIndexesToDataLayerLayouts = function() {\n this.data_layer_ids_by_z_index.forEach(function(dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n }.bind(this);\n\n /**\n * Track data requests in progress\n * @member {Promise[]}\n * @protected\n */\n this.data_promises = [];\n\n /** @member {d3.scale} */\n this.x_scale = null;\n /** @member {d3.scale} */\n this.y1_scale = null;\n /** @member {d3.scale} */\n this.y2_scale = null;\n\n /** @member {d3.extent} */\n this.x_extent = null;\n /** @member {d3.extent} */\n this.y1_extent = null;\n /** @member {d3.extent} */\n this.y2_extent = null;\n\n /** @member {Number[]} */\n this.x_ticks = [];\n /** @member {Number[]} */\n this.y1_ticks = [];\n /** @member {Number[]} */\n this.y2_ticks = [];\n\n /**\n * A timeout ID as returned by setTimeout\n * @protected\n * @member {number}\n */\n this.zoom_timeout = null;\n\n /** @returns {string} */\n this.getBaseId = function() {\n return this.parent.id + '.' + this.id;\n };\n\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [],\n 'element_selection': [],\n 'match_requested': [] // A data layer is attempting to highlight matching points (internal use only)\n };\n\n /**\n * There are several events that a LocusZoom panel can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following panel-level events are currently supported:\n * - `layout_changed` - context: panel - Any aspect of the panel's layout (including dimensions or state) has changed.\n * - `data_requested` - context: panel - A request for new data from any data source used in the panel has been made.\n * - `data_rendered` - context: panel - Data from a request has been received and rendered in the panel.\n * - `element_clicked` - context: panel - A data element in any of the panel's data layers has been clicked.\n * - `element_selection` - context: panel - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `panel.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * panel itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of the event (as defined in `event_hooks`)\n * @param {function} hook\n * @returns {function} The registered event listener\n */\n this.on = function(event, hook) {\n // TODO: Dry plot and panel event code into a shared mixin\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Panel}\n */\n this.off = function(event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n *\n * There is a shorter overloaded form of this method: if the event does not have any data, the second\n * argument can be a boolean to control bubbling\n *\n * @param {string} event A known event name\n * @param {*} [eventData] Data or event description that will be passed to the event listener\n * @param {boolean} [bubble=false] Whether to bubble the event to the parent\n * @returns {LocusZoom.Panel}\n */\n this.emit = function(event, eventData, bubble) {\n bubble = bubble || false;\n\n // TODO: DRY this with the parent plot implementation. Ensure interfaces remain compatible.\n // TODO: Improve documentation for overloaded method signature (JSDoc may have trouble here)\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n if (typeof eventData === 'boolean' && arguments.length === 2) {\n // Overloaded method signature: emit(event, bubble)\n bubble = eventData;\n eventData = null;\n }\n var sourceID = this.getBaseId();\n var self = this;\n var eventContext = {sourceID: sourceID, data: eventData || null};\n this.event_hooks[event].forEach(function(hookToRun) {\n // By default, any handlers fired here will see the panel as the value of `this`. If a bound function is\n // registered as a handler, the previously bound `this` will override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n if (bubble && this.parent) {\n this.parent.emit(event, eventContext);\n }\n return this;\n };\n\n /**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\n this.getPageOrigin = function() {\n var plot_origin = this.parent.getPageOrigin();\n return {\n x: plot_origin.x + this.layout.origin.x,\n y: plot_origin.y + this.layout.origin.y\n };\n };\n\n // Initialize the layout\n this.initializeLayout();\n\n return this;\n\n};\n\n/**\n * Default panel layout\n * @static\n * @type {Object}\n */\nLocusZoom.Panel.DefaultLayout = {\n title: { text: '', style: {}, x: 10, y: 22 },\n y_index: null,\n width: 0,\n height: 0,\n origin: { x: 0, y: null },\n min_width: 1,\n min_height: 1,\n proportional_width: null,\n proportional_height: null,\n proportional_origin: { x: 0, y: null },\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n background_click: 'clear_selections',\n dashboard: {\n components: []\n },\n cliparea: {\n height: 0,\n width: 0,\n origin: { x: 0, y: 0 }\n },\n axes: { // These are the only axes supported!!\n x: {},\n y1: {},\n y2: {}\n },\n legend: null,\n interaction: {\n drag_background_to_pan: false,\n drag_x_ticks_to_scale: false,\n drag_y1_ticks_to_scale: false,\n drag_y2_ticks_to_scale: false,\n scroll_to_zoom: false,\n x_linked: false,\n y1_linked: false,\n y2_linked: false\n },\n data_layers: []\n};\n\n/**\n * Prepare the panel for first use by performing parameter validation, creating axes, setting default dimensions,\n * and preparing / positioning data layers as appropriate.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.initializeLayout = function() {\n\n // If the layout is missing BOTH width and proportional width then set the proportional width to 1.\n // This will default the panel to taking up the full width of the plot.\n if (this.layout.width === 0 && this.layout.proportional_width === null) {\n this.layout.proportional_width = 1;\n }\n\n // If the layout is missing BOTH height and proportional height then set the proportional height to\n // an equal share of the plot's current height.\n if (this.layout.height === 0 && this.layout.proportional_height === null) {\n var panel_count = Object.keys(this.parent.panels).length;\n if (panel_count > 0) {\n this.layout.proportional_height = (1 / panel_count);\n } else {\n this.layout.proportional_height = 1;\n }\n }\n\n // Set panel dimensions, origin, and margin\n this.setDimensions();\n this.setOrigin();\n this.setMargin();\n\n // Set ranges\n // TODO: Define stub values in constructor\n this.x_range = [0, this.layout.cliparea.width];\n this.y1_range = [this.layout.cliparea.height, 0];\n this.y2_range = [this.layout.cliparea.height, 0];\n\n // Initialize panel axes\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (!Object.keys(this.layout.axes[axis]).length || this.layout.axes[axis].render === false) {\n // The default layout sets the axis to an empty object, so set its render boolean here\n this.layout.axes[axis].render = false;\n } else {\n this.layout.axes[axis].render = true;\n this.layout.axes[axis].label = this.layout.axes[axis].label || null;\n this.layout.axes[axis].label_function = this.layout.axes[axis].label_function || null;\n }\n }.bind(this));\n\n // Add data layers (which define x and y extents)\n this.layout.data_layers.forEach(function(data_layer_layout) {\n this.addDataLayer(data_layer_layout);\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Set the dimensions for the panel. If passed with no arguments will calculate optimal size based on layout\n * directives and the available area within the plot. If passed discrete width (number) and height (number) will\n * attempt to resize the panel to them, but may be limited by minimum dimensions defined on the plot or panel.\n *\n * @public\n * @param {number} [width]\n * @param {number} [height]\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setDimensions = function(width, height) {\n if (typeof width != 'undefined' && typeof height != 'undefined') {\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n }\n } else {\n if (this.layout.proportional_width !== null) {\n this.layout.width = Math.max(this.layout.proportional_width * this.parent.layout.width, this.layout.min_width);\n }\n if (this.layout.proportional_height !== null) {\n this.layout.height = Math.max(this.layout.proportional_height * this.parent.layout.height, this.layout.min_height);\n }\n }\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n if (this.svg.clipRect) {\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n if (this.initialized) {\n this.render();\n this.curtain.update();\n this.loader.update();\n this.dashboard.update();\n if (this.legend) { this.legend.position(); }\n }\n return this;\n};\n\n/**\n * Set panel origin on the plot, and re-render as appropriate\n *\n * @public\n * @param {number} x\n * @param {number} y\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setOrigin = function(x, y) {\n if (!isNaN(x) && x >= 0) { this.layout.origin.x = Math.max(Math.round(+x), 0); }\n if (!isNaN(y) && y >= 0) { this.layout.origin.y = Math.max(Math.round(+y), 0); }\n if (this.initialized) { this.render(); }\n return this;\n};\n\n/**\n * Set margins around this panel\n * @public\n * @param {number} top\n * @param {number} right\n * @param {number} bottom\n * @param {number} left\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setMargin = function(top, right, bottom, left) {\n var extra;\n if (!isNaN(top) && top >= 0) { this.layout.margin.top = Math.max(Math.round(+top), 0); }\n if (!isNaN(right) && right >= 0) { this.layout.margin.right = Math.max(Math.round(+right), 0); }\n if (!isNaN(bottom) && bottom >= 0) { this.layout.margin.bottom = Math.max(Math.round(+bottom), 0); }\n if (!isNaN(left) && left >= 0) { this.layout.margin.left = Math.max(Math.round(+left), 0); }\n if (this.layout.margin.top + this.layout.margin.bottom > this.layout.height) {\n extra = Math.floor(((this.layout.margin.top + this.layout.margin.bottom) - this.layout.height) / 2);\n this.layout.margin.top -= extra;\n this.layout.margin.bottom -= extra;\n }\n if (this.layout.margin.left + this.layout.margin.right > this.layout.width) {\n extra = Math.floor(((this.layout.margin.left + this.layout.margin.right) - this.layout.width) / 2);\n this.layout.margin.left -= extra;\n this.layout.margin.right -= extra;\n }\n ['top', 'right', 'bottom', 'left'].forEach(function(m) {\n this.layout.margin[m] = Math.max(this.layout.margin[m], 0);\n }.bind(this));\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n this.layout.cliparea.origin.x = this.layout.margin.left;\n this.layout.cliparea.origin.y = this.layout.margin.top;\n\n if (this.initialized) { this.render(); }\n return this;\n};\n\n/**\n * Set the title for the panel. If passed an object, will merge the object with the existing layout configuration, so\n * that all or only some of the title layout object's parameters can be customized. If passed null, false, or an empty\n * string, the title DOM element will be set to display: none.\n *\n * @param {string|object|null} title The title text, or an object with additional configuration\n * @param {string} title.text Text to display. Since titles are rendered as SVG text, HTML and newlines will not be rendered.\n * @param {number} title.x X-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n * @param {number} title.y Y-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n NOTE: SVG y values go from the top down, so the SVG origin of (0,0) is in the top left corner.\n * @param {object} title.style CSS styles object to be applied to the title's DOM element.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setTitle = function(title) {\n if (typeof this.layout.title == 'string') {\n var text = this.layout.title;\n this.layout.title = { text: text, x: 0, y: 0, style: {} };\n }\n if (typeof title == 'string') {\n this.layout.title.text = title;\n } else if (typeof title == 'object' && title !== null) {\n this.layout.title = LocusZoom.Layouts.merge(title, this.layout.title);\n }\n if (this.layout.title.text.length) {\n this.title.attr('display', null)\n .attr('x', parseFloat(this.layout.title.x))\n .attr('y', parseFloat(this.layout.title.y))\n .style(this.layout.title.style)\n .text(this.layout.title.text);\n } else {\n this.title.attr('display', 'none');\n }\n return this;\n};\n\n\n/**\n * Prepare the first rendering of the panel. This includes drawing the individual data layers, but also creates shared\n * elements such as axes, title, and loader/curtain.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.initialize = function() {\n\n // Append a container group element to house the main panel group element and the clip path\n // Position with initial layout parameters\n this.svg.container = this.parent.svg.append('g')\n .attr('id', this.getBaseId() + '.panel_container')\n .attr('transform', 'translate(' + (this.layout.origin.x || 0) + ',' + (this.layout.origin.y || 0) + ')');\n\n // Append clip path to the parent svg element, size with initial layout parameters\n var clipPath = this.svg.container.append('clipPath')\n .attr('id', this.getBaseId() + '.clip');\n this.svg.clipRect = clipPath.append('rect')\n .attr('width', this.layout.width).attr('height', this.layout.height);\n\n // Append svg group for rendering all panel child elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g')\n .attr('id', this.getBaseId() + '.panel')\n .attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n\n // Add curtain and loader prototypes to the panel\n /** @member {Object} */\n this.curtain = LocusZoom.generateCurtain.call(this);\n /** @member {Object} */\n this.loader = LocusZoom.generateLoader.call(this);\n\n /**\n * Create the dashboard object and hang components on it as defined by panel layout\n * @member {LocusZoom.Dashboard}\n */\n this.dashboard = new LocusZoom.Dashboard(this);\n\n // Inner border\n this.inner_border = this.svg.group.append('rect')\n .attr('class', 'lz-panel-background')\n .on('click', function() {\n if (this.layout.background_click === 'clear_selections') { this.clearSelections(); }\n }.bind(this));\n\n // Add the title\n /** @member {Element} */\n this.title = this.svg.group.append('text').attr('class', 'lz-panel-title');\n if (typeof this.layout.title != 'undefined') { this.setTitle(); }\n\n // Initialize Axes\n this.svg.x_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.x_axis').attr('class', 'lz-x lz-axis');\n if (this.layout.axes.x.render) {\n this.svg.x_axis_label = this.svg.x_axis.append('text')\n .attr('class', 'lz-x lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n this.svg.y1_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.y1_axis').attr('class', 'lz-y lz-y1 lz-axis');\n if (this.layout.axes.y1.render) {\n this.svg.y1_axis_label = this.svg.y1_axis.append('text')\n .attr('class', 'lz-y1 lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n this.svg.y2_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.y2_axis').attr('class', 'lz-y lz-y2 lz-axis');\n if (this.layout.axes.y2.render) {\n this.svg.y2_axis_label = this.svg.y2_axis.append('text')\n .attr('class', 'lz-y2 lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n\n // Initialize child Data Layers\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].initialize();\n }.bind(this));\n\n /**\n * Legend object, as defined by panel layout and child data layer layouts\n * @member {LocusZoom.Legend}\n * */\n this.legend = null;\n if (this.layout.legend) {\n this.legend = new LocusZoom.Legend(this);\n }\n\n // Establish panel background drag interaction mousedown event handler (on the panel background)\n if (this.layout.interaction.drag_background_to_pan) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var mousedown = function() {\n this.parent.startDrag(this, 'background');\n }.bind(this);\n this.svg.container.select('.lz-panel-background')\n .on('mousedown' + namespace + '.background', mousedown)\n .on('touchstart' + namespace + '.background', mousedown);\n }\n\n return this;\n\n};\n\n/**\n * Refresh the sort order of all data layers (called by data layer moveUp and moveDown methods)\n */\nLocusZoom.Panel.prototype.resortDataLayers = function() {\n var sort = [];\n this.data_layer_ids_by_z_index.forEach(function(id) {\n sort.push(this.data_layers[id].layout.z_index);\n }.bind(this));\n this.svg.group.selectAll('g.lz-data_layer-container').data(sort).sort(d3.ascending);\n this.applyDataLayerZIndexesToDataLayerLayouts();\n};\n\n/**\n * Get an array of panel IDs that are axis-linked to this panel\n * @param {('x'|'y1'|'y2')} axis\n * @returns {Array}\n */\nLocusZoom.Panel.prototype.getLinkedPanelIds = function(axis) {\n axis = axis || null;\n var linked_panel_ids = [];\n if (['x','y1','y2'].indexOf(axis) === -1) { return linked_panel_ids; }\n if (!this.layout.interaction[axis + '_linked']) { return linked_panel_ids; }\n this.parent.panel_ids_by_y_index.forEach(function(panel_id) {\n if (panel_id !== this.id && this.parent.panels[panel_id].layout.interaction[axis + '_linked']) {\n linked_panel_ids.push(panel_id);\n }\n }.bind(this));\n return linked_panel_ids;\n};\n\n/**\n * Move a panel up relative to others by y-index\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.moveUp = function() {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index - 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index - 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index - 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n};\n\n/**\n * Move a panel down (y-axis) relative to others in the plot\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.moveDown = function() {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index + 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index + 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index + 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n};\n\n/**\n * Create a new data layer from a provided layout object. Should have the keys specified in `DefaultLayout`\n * Will automatically add at the top (depth/z-index) of the panel unless explicitly directed differently\n * in the layout provided.\n * @param {object} layout\n * @returns {*}\n */\nLocusZoom.Panel.prototype.addDataLayer = function(layout) {\n\n // Sanity checks\n if (typeof layout !== 'object' || typeof layout.id !== 'string' || !layout.id.length) {\n throw new Error('Invalid data layer layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n if (typeof this.data_layers[layout.id] !== 'undefined') {\n throw new Error('Cannot create data_layer with id [' + layout.id + ']; data layer with that id already exists in the panel');\n }\n if (typeof layout.type !== 'string') {\n throw new Error('Invalid data layer type in layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n\n // If the layout defines a y axis make sure the axis number is set and is 1 or 2 (default to 1)\n if (typeof layout.y_axis == 'object' && (typeof layout.y_axis.axis == 'undefined' || [1,2].indexOf(layout.y_axis.axis) === -1)) {\n layout.y_axis.axis = 1;\n }\n\n // Create the Data Layer\n var data_layer = LocusZoom.DataLayers.get(layout.type, layout, this);\n\n // Store the Data Layer on the Panel\n this.data_layers[data_layer.id] = data_layer;\n\n // If a discrete z_index was set in the layout then adjust other data layer z_index values to accommodate this one\n if (data_layer.layout.z_index !== null && !isNaN(data_layer.layout.z_index)\n && this.data_layer_ids_by_z_index.length > 0) {\n // Negative z_index values should count backwards from the end, so convert negatives to appropriate values here\n if (data_layer.layout.z_index < 0) {\n data_layer.layout.z_index = Math.max(this.data_layer_ids_by_z_index.length + data_layer.layout.z_index, 0);\n }\n this.data_layer_ids_by_z_index.splice(data_layer.layout.z_index, 0, data_layer.id);\n this.data_layer_ids_by_z_index.forEach(function(dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n } else {\n var length = this.data_layer_ids_by_z_index.push(data_layer.id);\n this.data_layers[data_layer.id].layout.z_index = length - 1;\n }\n\n // Determine if this data layer was already in the layout.data_layers array.\n // If it wasn't, add it. Either way store the layout.data_layers array index on the data_layer.\n var layout_idx = null;\n this.layout.data_layers.forEach(function(data_layer_layout, idx) {\n if (data_layer_layout.id === data_layer.id) { layout_idx = idx; }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.data_layers.push(this.data_layers[data_layer.id].layout) - 1;\n }\n this.data_layers[data_layer.id].layout_idx = layout_idx;\n\n return this.data_layers[data_layer.id];\n};\n\n/**\n * Remove a data layer by id\n * @param {string} id\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.removeDataLayer = function(id) {\n if (!this.data_layers[id]) {\n throw new Error('Unable to remove data layer, ID not found: ' + id);\n }\n\n // Destroy all tooltips for the data layer\n this.data_layers[id].destroyAllTooltips();\n\n // Remove the svg container for the data layer if it exists\n if (this.data_layers[id].svg.container) {\n this.data_layers[id].svg.container.remove();\n }\n\n // Delete the data layer and its presence in the panel layout and state\n this.layout.data_layers.splice(this.data_layers[id].layout_idx, 1);\n delete this.state[this.data_layers[id].state_id];\n delete this.data_layers[id];\n\n // Remove the data_layer id from the z_index array\n this.data_layer_ids_by_z_index.splice(this.data_layer_ids_by_z_index.indexOf(id), 1);\n\n // Update layout_idx and layout.z_index values for all remaining data_layers\n this.applyDataLayerZIndexesToDataLayerLayouts();\n this.layout.data_layers.forEach(function(data_layer_layout, idx) {\n this.data_layers[data_layer_layout.id].layout_idx = idx;\n }.bind(this));\n\n return this;\n};\n\n/**\n * Clear all selections on all data layers\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.clearSelections = function() {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setAllElementStatus('selected', false);\n }.bind(this));\n return this;\n};\n\n/**\n * When the parent plot changes state, adjust the panel accordingly. For example, this may include fetching new data\n * from the API as the viewing region changes\n * @returns {Promise}\n */\nLocusZoom.Panel.prototype.reMap = function() {\n this.emit('data_requested');\n this.data_promises = [];\n\n // Remove any previous error messages before attempting to load new data\n this.curtain.hide();\n // Trigger reMap on each Data Layer\n for (var id in this.data_layers) {\n try {\n this.data_promises.push(this.data_layers[id].reMap());\n } catch (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }\n }\n // When all finished trigger a render\n return Promise.all(this.data_promises)\n .then(function() {\n this.initialized = true;\n this.render();\n this.emit('layout_changed', true);\n this.emit('data_rendered');\n }.bind(this))\n .catch(function(error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }.bind(this));\n};\n\n/**\n * Iterate over data layers to generate panel axis extents\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.generateExtents = function() {\n\n // Reset extents\n ['x', 'y1', 'y2'].forEach(function(axis) {\n this[axis + '_extent'] = null;\n }.bind(this));\n\n // Loop through the data layers\n for (var id in this.data_layers) {\n\n var data_layer = this.data_layers[id];\n\n // If defined and not decoupled, merge the x extent of the data layer with the panel's x extent\n if (data_layer.layout.x_axis && !data_layer.layout.x_axis.decoupled) {\n this.x_extent = d3.extent((this.x_extent || []).concat(data_layer.getAxisExtent('x')));\n }\n\n // If defined and not decoupled, merge the y extent of the data layer with the panel's appropriate y extent\n if (data_layer.layout.y_axis && !data_layer.layout.y_axis.decoupled) {\n var y_axis = 'y' + data_layer.layout.y_axis.axis;\n this[y_axis + '_extent'] = d3.extent((this[y_axis + '_extent'] || []).concat(data_layer.getAxisExtent('y')));\n }\n\n }\n\n // Override x_extent from state if explicitly defined to do so\n if (this.layout.axes.x && this.layout.axes.x.extent === 'state') {\n this.x_extent = [ this.state.start, this.state.end ];\n }\n\n return this;\n\n};\n\n/**\n * Generate an array of ticks for an axis. These ticks are generated in one of three ways (highest wins):\n * 1. An array of specific tick marks\n * 2. Query each data layer for what ticks are appropriate, and allow a panel-level tick configuration parameter\n * object to override the layer's default presentation settings\n * 3. Generate generic tick marks based on the extent of the data\n * @param {('x'|'y1'|'y2')} axis The string identifier of the axis\n * @returns {Number[]|Object[]} TODO: number format?\n * An array of numbers: interpreted as an array of axis value offsets for positioning.\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\nLocusZoom.Panel.prototype.generateTicks = function(axis) {\n\n // Parse an explicit 'ticks' attribute in the axis layout\n if (this.layout.axes[axis].ticks) {\n var layout = this.layout.axes[axis];\n\n var baseTickConfig = layout.ticks;\n if (Array.isArray(baseTickConfig)) {\n // Array of specific ticks hard-coded into a panel will override any ticks that an individual layer might specify\n return baseTickConfig;\n }\n\n if (typeof baseTickConfig === 'object') {\n // If the layout specifies base configuration for ticks- but without specific positions- then ask each\n // data layer to report the tick marks that it thinks it needs\n // TODO: Few layers currently need to specify custom ticks (which is ok!). But if it becomes common, consider adding mechanisms to deduplicate ticks across layers\n var self = this;\n\n // Pass any layer-specific customizations for how ticks are calculated. (styles are overridden separately)\n var config = { position: baseTickConfig.position };\n\n var combinedTicks = this.data_layer_ids_by_z_index.reduce(function(acc, data_layer_id) {\n var nextLayer = self.data_layers[data_layer_id];\n return acc.concat(nextLayer.getTicks(axis, config));\n }, []);\n\n return combinedTicks.map(function(item) {\n // The layer makes suggestions, but tick configuration params specified on the panel take precedence\n var itemConfig = {};\n itemConfig = LocusZoom.Layouts.merge(itemConfig, baseTickConfig);\n return LocusZoom.Layouts.merge(itemConfig, item);\n });\n }\n }\n\n // If no other configuration is provided, attempt to generate ticks from the extent\n if (this[axis + '_extent']) {\n return LocusZoom.prettyTicks(this[axis + '_extent'], 'both');\n }\n return [];\n};\n\n/**\n * Update rendering of this panel whenever an event triggers a redraw. Assumes that the panel has already been\n * prepared the first time via `initialize`\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.render = function() {\n\n // Position the panel container\n this.svg.container.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n\n // Set size on the clip rect\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n\n // Set and position the inner border, style if necessary\n this.inner_border\n .attr('x', this.layout.margin.left).attr('y', this.layout.margin.top)\n .attr('width', this.layout.width - (this.layout.margin.left + this.layout.margin.right))\n .attr('height', this.layout.height - (this.layout.margin.top + this.layout.margin.bottom));\n if (this.layout.inner_border) {\n this.inner_border.style({ 'stroke-width': 1, 'stroke': this.layout.inner_border });\n }\n\n // Set/update panel title if necessary\n this.setTitle();\n\n // Regenerate all extents\n this.generateExtents();\n\n // Helper function to constrain any procedurally generated vectors (e.g. ranges, extents)\n // Constraints applied here keep vectors from going to infinity or beyond a definable power of ten\n var constrain = function(value, limit_exponent) {\n var neg_min = Math.pow(-10, limit_exponent);\n var neg_max = Math.pow(-10, -limit_exponent);\n var pos_min = Math.pow(10, -limit_exponent);\n var pos_max = Math.pow(10, limit_exponent);\n if (value === Infinity) { value = pos_max; }\n if (value === -Infinity) { value = neg_min; }\n if (value === 0) { value = pos_min; }\n if (value > 0) { value = Math.max(Math.min(value, pos_max), pos_min); }\n if (value < 0) { value = Math.max(Math.min(value, neg_max), neg_min); }\n return value;\n };\n\n // Define default and shifted ranges for all axes\n var ranges = {};\n if (this.x_extent) {\n var base_x_range = { start: 0, end: this.layout.cliparea.width };\n if (this.layout.axes.x.range) {\n base_x_range.start = this.layout.axes.x.range.start || base_x_range.start;\n base_x_range.end = this.layout.axes.x.range.end || base_x_range.end;\n }\n ranges.x = [base_x_range.start, base_x_range.end];\n ranges.x_shifted = [base_x_range.start, base_x_range.end];\n }\n if (this.y1_extent) {\n var base_y1_range = { start: this.layout.cliparea.height, end: 0 };\n if (this.layout.axes.y1.range) {\n base_y1_range.start = this.layout.axes.y1.range.start || base_y1_range.start;\n base_y1_range.end = this.layout.axes.y1.range.end || base_y1_range.end;\n }\n ranges.y1 = [base_y1_range.start, base_y1_range.end];\n ranges.y1_shifted = [base_y1_range.start, base_y1_range.end];\n }\n if (this.y2_extent) {\n var base_y2_range = { start: this.layout.cliparea.height, end: 0 };\n if (this.layout.axes.y2.range) {\n base_y2_range.start = this.layout.axes.y2.range.start || base_y2_range.start;\n base_y2_range.end = this.layout.axes.y2.range.end || base_y2_range.end;\n }\n ranges.y2 = [base_y2_range.start, base_y2_range.end];\n ranges.y2_shifted = [base_y2_range.start, base_y2_range.end];\n }\n\n // Shift ranges based on any drag or zoom interactions currently underway\n if (this.parent.interaction.panel_id && (this.parent.interaction.panel_id === this.id || this.parent.interaction.linked_panel_ids.indexOf(this.id) !== -1)) {\n var anchor, scalar = null;\n if (this.parent.interaction.zooming && typeof this.x_scale == 'function') {\n var current_extent_size = Math.abs(this.x_extent[1] - this.x_extent[0]);\n var current_scaled_extent_size = Math.round(this.x_scale.invert(ranges.x_shifted[1])) - Math.round(this.x_scale.invert(ranges.x_shifted[0]));\n var zoom_factor = this.parent.interaction.zooming.scale;\n var potential_extent_size = Math.floor(current_scaled_extent_size * (1 / zoom_factor));\n if (zoom_factor < 1 && !isNaN(this.parent.layout.max_region_scale)) {\n zoom_factor = 1 / (Math.min(potential_extent_size, this.parent.layout.max_region_scale) / current_scaled_extent_size);\n } else if (zoom_factor > 1 && !isNaN(this.parent.layout.min_region_scale)) {\n zoom_factor = 1 / (Math.max(potential_extent_size, this.parent.layout.min_region_scale) / current_scaled_extent_size);\n }\n var new_extent_size = Math.floor(current_extent_size * zoom_factor);\n anchor = this.parent.interaction.zooming.center - this.layout.margin.left - this.layout.origin.x;\n var offset_ratio = anchor / this.layout.cliparea.width;\n var new_x_extent_start = Math.max(Math.floor(this.x_scale.invert(ranges.x_shifted[0]) - ((new_extent_size - current_scaled_extent_size) * offset_ratio)), 1);\n ranges.x_shifted = [ this.x_scale(new_x_extent_start), this.x_scale(new_x_extent_start + new_extent_size) ];\n } else if (this.parent.interaction.dragging) {\n switch (this.parent.interaction.dragging.method) {\n case 'background':\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n break;\n case 'x_tick':\n if (d3.event && d3.event.shiftKey) {\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n } else {\n anchor = this.parent.interaction.dragging.start_x - this.layout.margin.left - this.layout.origin.x;\n scalar = constrain(anchor / (anchor + this.parent.interaction.dragging.dragged_x), 3);\n ranges.x_shifted[0] = 0;\n ranges.x_shifted[1] = Math.max(this.layout.cliparea.width * (1 / scalar), 1);\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n var y_shifted = 'y' + this.parent.interaction.dragging.method[1] + '_shifted';\n if (d3.event && d3.event.shiftKey) {\n ranges[y_shifted][0] = this.layout.cliparea.height + this.parent.interaction.dragging.dragged_y;\n ranges[y_shifted][1] = +this.parent.interaction.dragging.dragged_y;\n } else {\n anchor = this.layout.cliparea.height - (this.parent.interaction.dragging.start_y - this.layout.margin.top - this.layout.origin.y);\n scalar = constrain(anchor / (anchor - this.parent.interaction.dragging.dragged_y), 3);\n ranges[y_shifted][0] = this.layout.cliparea.height;\n ranges[y_shifted][1] = this.layout.cliparea.height - (this.layout.cliparea.height * (1 / scalar));\n }\n }\n }\n }\n\n // Generate scales and ticks for all axes, then render them\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (!this[axis + '_extent']) { return; }\n\n // Base Scale\n this[axis + '_scale'] = d3.scale.linear()\n .domain(this[axis + '_extent'])\n .range(ranges[axis + '_shifted']);\n\n // Shift the extent\n this[axis + '_extent'] = [\n this[axis + '_scale'].invert(ranges[axis][0]),\n this[axis + '_scale'].invert(ranges[axis][1])\n ];\n\n // Finalize Scale\n this[axis + '_scale'] = d3.scale.linear()\n .domain(this[axis + '_extent']).range(ranges[axis]);\n\n // Render axis (and generate ticks as needed)\n this.renderAxis(axis);\n }.bind(this));\n\n // Establish mousewheel zoom event handers on the panel (namespacing not passed through by d3, so not used here)\n if (this.layout.interaction.scroll_to_zoom) {\n var zoom_handler = function() {\n // Look for a shift key press while scrolling to execute.\n // If not present, gracefully raise a notification and allow conventional scrolling\n if (!d3.event.shiftKey) {\n if (this.parent.canInteract(this.id)) {\n this.loader.show('Press [SHIFT] while scrolling to zoom').hide(1000);\n }\n return;\n }\n d3.event.preventDefault();\n if (!this.parent.canInteract(this.id)) { return; }\n var coords = d3.mouse(this.svg.container.node());\n var delta = Math.max(-1, Math.min(1, (d3.event.wheelDelta || -d3.event.detail || -d3.event.deltaY)));\n if (delta === 0) { return; }\n this.parent.interaction = {\n panel_id: this.id,\n linked_panel_ids: this.getLinkedPanelIds('x'),\n zooming: {\n scale: (delta < 1) ? 0.9 : 1.1,\n center: coords[0]\n }\n };\n this.render();\n this.parent.interaction.linked_panel_ids.forEach(function(panel_id) {\n this.parent.panels[panel_id].render();\n }.bind(this));\n if (this.zoom_timeout !== null) { clearTimeout(this.zoom_timeout); }\n this.zoom_timeout = setTimeout(function() {\n this.parent.interaction = {};\n this.parent.applyState({ start: this.x_extent[0], end: this.x_extent[1] });\n }.bind(this), 500);\n }.bind(this);\n this.zoom_listener = d3.behavior.zoom();\n this.svg.container.call(this.zoom_listener)\n .on('wheel.zoom', zoom_handler)\n .on('mousewheel.zoom', zoom_handler)\n .on('DOMMouseScroll.zoom', zoom_handler);\n }\n\n // Render data layers in order by z-index\n this.data_layer_ids_by_z_index.forEach(function(data_layer_id) {\n this.data_layers[data_layer_id].draw().render();\n }.bind(this));\n\n return this;\n};\n\n\n/**\n * Render ticks for a particular axis\n * @param {('x'|'y1'|'y2')} axis The identifier of the axes\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.renderAxis = function(axis) {\n\n if (['x', 'y1', 'y2'].indexOf(axis) === -1) {\n throw new Error('Unable to render axis; invalid axis identifier: ' + axis);\n }\n\n var canRender = this.layout.axes[axis].render\n && typeof this[axis + '_scale'] == 'function'\n && !isNaN(this[axis + '_scale'](0));\n\n // If the axis has already been rendered then check if we can/can't render it\n // Make sure the axis element is shown/hidden to suit\n if (this[axis + '_axis']) {\n this.svg.container.select('g.lz-axis.lz-' + axis).style('display', canRender ? null : 'none');\n }\n\n if (!canRender) { return this; }\n\n // Axis-specific values to plug in where needed\n var axis_params = {\n x: {\n position: 'translate(' + this.layout.margin.left + ',' + (this.layout.height - this.layout.margin.bottom) + ')',\n orientation: 'bottom',\n label_x: this.layout.cliparea.width / 2,\n label_y: (this.layout.axes[axis].label_offset || 0),\n label_rotate: null\n },\n y1: {\n position: 'translate(' + this.layout.margin.left + ',' + this.layout.margin.top + ')',\n orientation: 'left',\n label_x: -1 * (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n },\n y2: {\n position: 'translate(' + (this.layout.width - this.layout.margin.right) + ',' + this.layout.margin.top + ')',\n orientation: 'right',\n label_x: (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n }\n };\n\n // Generate Ticks\n this[axis + '_ticks'] = this.generateTicks(axis);\n\n // Determine if the ticks are all numbers (d3-automated tick rendering) or not (manual tick rendering)\n var ticksAreAllNumbers = (function(ticks) {\n for (var i = 0; i < ticks.length; i++) {\n if (isNaN(ticks[i])) {\n return false;\n }\n }\n return true;\n })(this[axis + '_ticks']);\n\n // Initialize the axis; set scale and orientation\n this[axis + '_axis'] = d3.svg.axis().scale(this[axis + '_scale']).orient(axis_params[axis].orientation).tickPadding(3);\n\n // Set tick values and format\n if (ticksAreAllNumbers) {\n this[axis + '_axis'].tickValues(this[axis + '_ticks']);\n if (this.layout.axes[axis].tick_format === 'region') {\n this[axis + '_axis'].tickFormat(function(d) { return LocusZoom.positionIntToString(d, 6); });\n }\n } else {\n var ticks = this[axis + '_ticks'].map(function(t) {\n return(t[axis.substr(0,1)]);\n });\n this[axis + '_axis'].tickValues(ticks)\n .tickFormat(function(t, i) { return this[axis + '_ticks'][i].text; }.bind(this));\n }\n\n // Position the axis in the SVG and apply the axis construct\n this.svg[axis + '_axis']\n .attr('transform', axis_params[axis].position)\n .call(this[axis + '_axis']);\n\n // If necessary manually apply styles and transforms to ticks as specified by the layout\n if (!ticksAreAllNumbers) {\n var tick_selector = d3.selectAll('g#' + this.getBaseId().replace('.','\\\\.') + '\\\\.' + axis + '_axis g.tick');\n var panel = this;\n tick_selector.each(function(d, i) {\n var selector = d3.select(this).select('text');\n if (panel[axis + '_ticks'][i].style) {\n selector.style(panel[axis + '_ticks'][i].style);\n }\n if (panel[axis + '_ticks'][i].transform) {\n selector.attr('transform', panel[axis + '_ticks'][i].transform);\n }\n });\n }\n\n // Render the axis label if necessary\n var label = this.layout.axes[axis].label || null;\n if (label !== null) {\n this.svg[axis + '_axis_label']\n .attr('x', axis_params[axis].label_x).attr('y', axis_params[axis].label_y)\n .text(LocusZoom.parseFields(this.state, label));\n if (axis_params[axis].label_rotate !== null) {\n this.svg[axis + '_axis_label']\n .attr('transform', 'rotate(' + axis_params[axis].label_rotate + ' ' + axis_params[axis].label_x + ',' + axis_params[axis].label_y + ')');\n }\n }\n\n // Attach interactive handlers to ticks as needed\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (this.layout.interaction['drag_' + axis + '_ticks_to_scale']) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var tick_mouseover = function() {\n if (typeof d3.select(this).node().focus == 'function') { d3.select(this).node().focus(); }\n var cursor = (axis === 'x') ? 'ew-resize' : 'ns-resize';\n if (d3.event && d3.event.shiftKey) { cursor = 'move'; }\n d3.select(this)\n .style({'font-weight': 'bold', 'cursor': cursor})\n .on('keydown' + namespace, tick_mouseover)\n .on('keyup' + namespace, tick_mouseover);\n };\n this.svg.container.selectAll('.lz-axis.lz-' + axis + ' .tick text')\n .attr('tabindex', 0) // necessary to make the tick focusable so keypress events can be captured\n .on('mouseover' + namespace, tick_mouseover)\n .on('mouseout' + namespace, function() {\n d3.select(this).style({'font-weight': 'normal'});\n d3.select(this).on('keydown' + namespace, null).on('keyup' + namespace, null);\n })\n .on('mousedown' + namespace, function() {\n this.parent.startDrag(this, axis + '_tick');\n }.bind(this));\n }\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Force the height of this panel to the largest absolute height of the data in\n * all child data layers (if not null for any child data layers)\n * @param {number|null} [target_height] A target height, which will be used in situations when the expected height can be\n * pre-calculated (eg when the layers are transitioning)\n */\nLocusZoom.Panel.prototype.scaleHeightToData = function(target_height) {\n target_height = +target_height || null;\n if (target_height === null) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n var dh = this.data_layers[id].getAbsoluteDataHeight();\n if (+dh) {\n if (target_height === null) {\n target_height = +dh;\n }\n else {\n target_height = Math.max(target_height, +dh);\n }\n }\n }.bind(this));\n }\n if (+target_height) {\n target_height += +this.layout.margin.top + +this.layout.margin.bottom;\n this.setDimensions(this.layout.width, target_height);\n this.parent.setDimensions();\n this.parent.panel_ids_by_y_index.forEach(function(id) {\n this.parent.panels[id].layout.proportional_height = null;\n }.bind(this));\n this.parent.positionPanels();\n }\n};\n\n/**\n * Methods to set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n */\nLocusZoom.Panel.prototype.setElementStatusByFilters = function(status, toggle, filters, exclusive) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setElementStatusByFilters(status, toggle, filters, exclusive);\n }.bind(this));\n};\n/**\n * Set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n */\nLocusZoom.Panel.prototype.setAllElementStatus = function(status, toggle) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setAllElementStatus(status, toggle);\n }.bind(this));\n};\n// TODO: Capture documentation for dynamically generated methods\nLocusZoom.DataLayer.Statuses.verbs.forEach(function(verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.Panel.prototype[verb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.Panel.prototype[antiverb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.Panel.prototype[verb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.Panel.prototype[antiverb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n});\n\n\n/**\n * Add a \"basic\" loader to a panel\n * This method is just a shortcut for adding the most commonly used type of loading indicator, which appears when\n * data is requested, animates (e.g. shows an infinitely cycling progress bar as opposed to one that loads from\n * 0-100% based on actual load progress), and disappears when new data is loaded and rendered.\n *\n *\n * @param {Boolean} show_immediately\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.addBasicLoader = function(show_immediately) {\n if (typeof show_immediately != 'undefined') { show_immediately = true; }\n if (show_immediately) {\n this.loader.show('Loading...').animate();\n }\n this.on('data_requested', function() {\n this.loader.show('Loading...').animate();\n }.bind(this));\n this.on('data_rendered', function() {\n this.loader.hide();\n }.bind(this));\n return this;\n};\n"]} \ No newline at end of file +{"version":3,"sources":["LocusZoom.js","Layouts.js","DataLayer.js","annotation_track.js","forest.js","genes.js","genome_legend.js","intervals.js","line.js","scatter.js","Singletons.js","Dashboard.js","Legend.js","Data.js","Plot.js","Panel.js"],"names":["LocusZoom","version","populate","selector","datasource","layout","Error","d3","select","html","plot","call","node","id","iterator","empty","attr","Plot","container","dataset","region","parsed_state","parsePositionQuery","Object","keys","forEach","key","state","svg","append","style","setDimensions","positionPanels","initialize","length","refresh","populateAll","plots","selectAll","each","d","i","positionIntToString","pos","exp","suffix","exp_symbols","isNaN","log","Math","LN10","min","max","places_exp","floor","toFixed","min_exp","places","ret","pow","positionStringToInt","p","val","toUpperCase","replace","suffixre","exec","mult","Number","x","chrposoff","chrpos","match","center","offset","chr","start","end","position","prettyTicks","range","clip_range","target_tick_count","parseInt","min_n","shrink_sml","high_u_bias","u5_bias","abs","c","base","base_toFixed","round","unit","ticks","parseFloat","push","indexOf","slice","pop","createCORSPromise","method","url","body","headers","timeout","Promise","resolve","reject","xhr","XMLHttpRequest","open","XDomainRequest","onreadystatechange","readyState","status","response","setTimeout","header","setRequestHeader","send","validateState","new_state","validated_region","attempted_midpoint","attempted_scale","temp","min_region_scale","max_region_scale","parseFields","data","tokens","regex","m","text","index","condition","variable","close","console","error","JSON","stringify","astify","token","shift","then","ast","cache","hasOwnProperty","Data","Field","render_node","value","map","join","getToolTipData","parentNode","classed","getToolTipDataLayer","getDataLayer","getToolTipPanel","data_layer","parent","getToolTipPlot","panel","generateCurtain","curtain","showing","content_selector","hide_delay","show","content","css","parent_plot","insert","on","hide","bind","update","clearTimeout","page_origin","getPageOrigin","top","y","left","width","height","delay","remove","generateLoader","loader","progress_selector","cancel_selector","percent","padding","loader_boundrect","getBoundingClientRect","animate","setPercentCompleted","subclass","extra","Sub","constructor","apply","arguments","prototype","create","k","ext","LZ_SIG_THRESHOLD_LOGP","Layouts","obj","layouts","get","type","name","modifications","merge","unnamespaced","parse","default_namespace","namespace","default","toString","applyNamespaces","element","re","resolved_namespace","r","merge_namespace","namespaced_element","namespaced_property","property","set","add","list","custom_layout","default_layout","custom_type","default_type","Array","isArray","closable","or","and","covariates_model_association","orientation","fields","z_index","x_axis","field","y_axis","axis","ceiling","point_shape","scale_function","parameters","field_value","else","point_size","color","breaks","values","legend","shape","size","label","class","id_field","upper_buffer","min_extent","behaviors","onmouseover","action","onmouseout","onclick","exclusive","onshiftclick","tooltip","l","fill_opacity","catalog","tooltip_positioning","category_field","lower_buffer","categories","null_value","spacing","lines","filters","operator","start_field","end_field","track_split_field","split_tracks","always_hide_legend","button_html","show_selected","button_title","state_field","options","display_name","components","group_position","title","subtitle","covariates_model_plot_dashboard","region_nav_plot_dashboard","step","min_width","min_height","proportional_width","margin","right","bottom","inner_border","dashboard","axes","label_offset","tick_format","extent","y1","y2","origin","hidden","interaction","drag_background_to_pan","drag_x_ticks_to_scale","drag_y1_ticks_to_scale","drag_y2_ticks_to_scale","scroll_to_zoom","x_linked","data_layers","layer_name","default_config_display_name","display","transform","data_layer_id","pad_from_bottom","responsive_resize","panels","proportional_height","StandardLayout","mouse_guide","DataLayer","initialized","layout_idx","Panel","DefaultLayout","_base_layout","state_id","setDefaultState","tooltips","global_statuses","addField","fieldName","transformations","fieldString","layer_state","Statuses","adjectives","verbs","menu_antiverbs","getBaseId","getAbsoluteDataHeight","dataBCR","group","canTransition","transition","panel_boundaries","dragging","panel_id","getElementId","element_id","getElementStatusNodeId","getElementById","applyDataMethods","field_to_match","receive","broadcast_value","lz_match_value","undefined","lz_highlight_match","toHTML","deselect","unselectElement","applyCustomDataMethods","clipRect","moveUp","data_layer_ids_by_z_index","resortDataLayers","moveDown","resolveScalableParameter","idx","f","ScaleFunctions","_getDataExtent","axis_config","getAxisExtent","dimension","axis_name","axis_layout","data_extent","original_extent_span","range_min","range_max","getTicks","config","createTooltip","positionTooltip","arrow","updateTooltip","destroyTooltip","element_or_id","temporary","label_mark_position","splice","destroyAllTooltips","event","pageX","pageY","positionAllTooltips","showOrHideTooltip","first_time","resolveStatus","statuses","directive","reduce","previousValue","currentValue","sub_status","sub_operator","show_directive","hide_directive","antistatus","show_resolved","hide_resolved","has_tooltip","tooltip_was_closed","filter","return_type","test","operators","a","b","matches","filterIndexes","filterElements","verb","adjective","antiverb","setElementStatus","setElementStatusByFilters","setAllElementStatus","active","get_element_id_error","element_status_node_id","element_status_idx","added_status","emit","is_selected","value_to_broadcast","toggle","status_ids","applyBehaviors","selection","event_match","executeBehaviors","requiredKeyStates","ctrl","ctrlKey","shiftKey","behavior","current_status_boolean","href","target","window","location","panel_origin","exportData","format","default_format","toLowerCase","e","warn","jsonified","delimiter","record","draw","cliparea","reMap","promise","lzd","getData","new_data","DataLayers","datalayers","datalayer","extend","parent_name","overrides","child","hit_area_width","render","self","trackData","visible_lines_group","enter","exit","hit_areas_group","hit_areas_selection","_getX","x_center","x_left","left_node","left_node_x_center","crds","arrow_type","arrow_top","arrow_left","arrow_width","stroke_width","tooltip_box","data_layer_height","data_layer_width","x_scale","y_center","offset_right","offset_left","top_offset","mouse","confidence_intervals","show_no_significance_line","border_radius","y_scale","sqrt","PI","ci_selection","ci_transform","ci_width","ci_height","duration","ease","points_selection","initial_y","fill","symbol","element_data","ci_config","axis_num","item","field_to_add","stroke","label_font_size","label_exon_spacing","exon_height","bounding_box_padding","track_vertical_spacing","getTrackHeight","transcript_idx","tracks","gene_track_index","assignTracks","getLabelWidth","gene_name","font_size","temp_text","label_width","getBBox","g","gene_id","split","gene_version","transcript_id","transcripts","display_range","text_anchor","centered_margin","display_domain","invert","track","potential_track","collision_on_potential_track","placed_gene","min_start","max_end","t","exons","gene","bboxes","boundary_fill","boundary_stroke","boundaries","labels","strand","exon_fill","exon_stroke","exon_id","clickareas","gene_bbox_id","gene_bbox","gene_center_x","chromosome_fill_colors","light","dark","chromosome_label_colors","genome_start","genome_end","chromosomes","variant_parts","variant","track_split_order","track_split_legend_to_y_axis","track_height","previous_tracks","interval_track_index","track_split_field_index","reverse","placed_interval","psuedoElement","sharedstatusnode_style","interval","statusnode_style","statusnodes","rects","interval_name","updateSplitTrackAxis","interval_bbox","interval_center_x","legend_axis","track_spacing","target_height","scaleHeightToData","toggleSplitTracks","interpolate","hitarea_width","mouse_event","line","tooltip_timeout","getMouseDisplayAndData","slope","x_field","y_field","bisect","bisector","datum","startDatum","endDatum","interpolateNumber","x_precision","toPrecision","y_precision","dd","min_arrow_left","max_arrow_left","path","area","y0","hitarea","hitarea_line","path_class","global_status","decoupled","x_extent","y_extent","x_range","default_y","flip_labels","handle_lines","Boolean","min_x","max_x","flip","dn","dnl","dnx","text_swing","dnlx2","line_swing","label_texts","da","dax","abound","dal","label_lines","db","bbound","collision","separate_labels","seperate_iterations","alpha","again","sign","adjust","new_a_y","new_b_y","min_y","max_y","delta","label_elements","label_line","filtered_data","label_groups","makeLDReference","ref","applyState","ldrefvar","_prepareData","xField","sourceData","sort","ak","bk","av","bv","_generateCategoryBounds","uniqueCategories","category","bounds","categoryNames","_setDynamicColorScheme","_getColorScale","from_source","color_params","find","colorParams","baseParams","parameters_categories_hash","every","colors","color_scale","scale","category10","category20","concat","categoryBounds","_categories","knownCategories","knownColors","xPos","diff","KnownDataSources","sources","findSourceByName","SOURCE_NAME","source","source_name","newObj","params","Function","getAll","setAll","clear","TransformationFunctions","getTrans","fun","parseTrans","parseTransString","funs","result","substring","fn","ceil","toExponential","str","encodeURIComponent","s","functions","input","threshold","prev","curr","nullval","upper_idx","brk","normalized_input","isFinite","Dashboard","hide_timeout","persist","component","Components","shouldPersist","visibility","destroy","force","Component","parent_panel","parent_svg","button","menu","Button","parent_dashboard","tag","setTag","setHtml","setText","setTitle","setColor","setStyle","getClass","permanent","setPermanent","bool","setStatus","highlight","disable","setOnMouseover","setOnMouseout","setOnclick","preUpdate","postUpdate","outer_selector","inner_selector","scroll_position","scrollTop","scrollbar_padding","menu_height_padding","page_scroll_top","document","documentElement","container_offset","getContainerOffset","dashboard_client_rect","button_client_rect","menu_client_rect","total_content_height","scrollHeight","base_max_width","container_max_width","content_max_width","base_max_height","max_height","setPopulate","menu_populate_function","div_selector","title_selector","display_width","display_height","generateBase64SVG","old","URL","revokeObjectURL","filename","css_string","stylesheet","styleSheets","outerHTML","dy","initial_html","style_def","insert_at","Blob","createObjectURL","suppress_confirm","confirm","removePanel","is_at_top","y_index","is_at_bottom","panel_ids_by_y_index","can_zoom","current_region_scale","zoom_factor","new_region_scale","menu_html","model","covariates","CovariatesModel","element_reference","updateComponent","removeByIdx","removeAll","table","covariate","row","cov","scale_timeout","status_adj","status_idx","status_verb","at_top","at_bottom","td","removeDataLayer","allowed_fields","fields_whitelist","dataLayer","dataLayerLayout","defaultConfig","configSlot","_selected_item","uniqueID","random","menuLayout","renderRow","display_options","row_id","radioId","field_name","defaultName","Legend","background_rect","elements","elements_group","label_size","line_height","label_x","label_y","path_y","symbolTypes","radius","bcr","right_x","pad_from_right","validateBuildSource","class_name","build","DataSources","addSource","ns","dsobj","source_id","getSource","removeSource","fromJSON","ds","toJSON","parts","full_name","applyTransformations","Requester","split_requests","requests","raw","trans","outnames","request_handles","discrete","Source","enableCache","dependentSource","parseInit","init","getCacheKey","chain","getURL","fetchRequest","getRequest","req","cacheKey","_cachedKey","_cachedResponse","preGetData","pre","resp","parseResponse","normalizeResponse","N","sameLength","records","j","prepareData","annotateData","extractFields","fieldFound","output_record","v","combineChainBody","json","standardized","one_source_body","new_body","parseArraysToObjects","standard","parseObjectsToObjects","parseData","constructorFun","uniqueName","getPrototypeOf","AssociationSource","unshift","analysis","LDSource","findMergeFields","exactMatch","arr","regexes","dataFields","position_field","pvalue","pvalue_field","_names_","names","nameMatch","id_match","RegExp","findRequestedFields","isrefvarin","isrefvarout","ldin","ldout","getRefvar","findExtremeValue","pval_field","is_log","cmp","extremeVal","extremeIdx","reqFields","refVar","columns","refSource","ldrefsource","leftJoin","lfield","rfield","position2","tagRefVariant","refvar","idfield","outrefname","outldname","corrField","rsquare","LDSource2","genome_build","ld_source","population","ld_pop","combined","chainRequests","payload","next","GwasCatalog","build_option","default_source","knownFields","posMatch","decider","decider_out","n_matches","outn","chainNames","catNames","GeneSource","GeneConstraintSource","query","alias","constraint","RecombinationRateSource","IntervalSource","bedtracksource","StaticSource","_data","PheWASSource","ConnectorSource","_source_name_mapping","specified_ids","REQUIRED_SOURCES","chain_source_id","applyPanelYIndexesToPanelLayouts","pid","remap_promises","window_onresize","event_hooks","hook","off","theseHooks","hookMatch","eventData","sourceID","hookToRun","eventContext","bounding_client_rect","x_offset","scrollLeft","y_offset","offsetParent","offsetTop","offsetLeft","canInteract","loading_data","zooming","initializeLayout","aspect_ratio","sumProportional","total","rescaleSVG","clientRect","RESIZE_MODES","panel_layout","addPanel","panel_width","panel_height","setOrigin","proportional_origin","clearPanelData","panelId","mode","panelsList","dlid","layer","x_linked_margins","total_proportional_height","proportional_adjustment","calculated_plot_height","mouse_guide_svg","mouse_guide_vertical_svg","mouse_guide_horizontal_svg","vertical","horizontal","selectors","corner_selector","panel_idx","panel_resize_drag","drag","this_panel","original_panel_height","panel_height_change","new_calculated_plot_height","loop_panel_id","loop_panel_idx","loop_panel","corner_drag","dx","plot_page_origin","panel_page_origin","corner_padding","corner_size","mouseout_mouse_guide","mousemove_mouse_guide","coords","mouseup","stopDrag","mousemove","preventDefault","dragged_x","start_x","dragged_y","start_y","linked_panel_ids","to_send","client_rect","subscribeToData","success_callback","opts","error_callback","onerror","err","listener","catch","state_changes","all","message","startDrag","getLinkedPanelIds","overrideAxisLayout","axis_number","y_axis_number","generateID","applyDataLayerZIndexesToDataLayerLayouts","data_promises","y1_scale","y2_scale","y1_extent","y2_extent","x_ticks","y1_ticks","y2_ticks","zoom_timeout","bubble","plot_origin","background_click","y1_linked","y2_linked","panel_count","setMargin","y1_range","y2_range","label_function","data_layer_layout","addDataLayer","clipPath","clearSelections","x_axis_label","y1_axis","y1_axis_label","y2_axis","y2_axis_label","mousedown","ascending","generateExtents","generateTicks","baseTickConfig","combinedTicks","acc","nextLayer","itemConfig","constrain","limit_exponent","neg_min","neg_max","pos_min","pos_max","Infinity","ranges","base_x_range","x_shifted","base_y1_range","y1_shifted","base_y2_range","y2_shifted","anchor","scalar","current_extent_size","current_scaled_extent_size","potential_extent_size","new_extent_size","offset_ratio","new_x_extent_start","y_shifted","linear","domain","renderAxis","zoom_handler","wheelDelta","detail","deltaY","zoom_listener","zoom","canRender","axis_params","label_rotate","ticksAreAllNumbers","orient","tickPadding","tickValues","tickFormat","substr","tick_selector","tick_mouseover","focus","cursor","dh","addBasicLoader","show_immediately"],"mappings":"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","file":"locuszoom.app.js","sourcesContent":["/**\n * @namespace\n */\nvar LocusZoom = {\n version: '0.10.1'\n};\n\n/**\n * Populate a single element with a LocusZoom plot.\n * selector can be a string for a DOM Query or a d3 selector.\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot} The newly created plot instance\n */\nLocusZoom.populate = function(selector, datasource, layout) {\n if (typeof selector == 'undefined') {\n throw new Error('LocusZoom.populate selector not defined');\n }\n // Empty the selector of any existing content\n d3.select(selector).html('');\n var plot;\n d3.select(selector).call(function() {\n // Require each containing element have an ID. If one isn't present, create one.\n if (typeof this.node().id == 'undefined') {\n var iterator = 0;\n while (!d3.select('#lz-' + iterator).empty()) { iterator++; }\n this.attr('id', '#lz-' + iterator);\n }\n // Create the plot\n plot = new LocusZoom.Plot(this.node().id, datasource, layout);\n plot.container = this.node();\n // Detect data-region and fill in state values if present\n if (typeof this.node().dataset !== 'undefined' && typeof this.node().dataset.region !== 'undefined') {\n var parsed_state = LocusZoom.parsePositionQuery(this.node().dataset.region);\n Object.keys(parsed_state).forEach(function(key) {\n plot.state[key] = parsed_state[key];\n });\n }\n // Add an SVG to the div and set its dimensions\n plot.svg = d3.select('div#' + plot.id)\n .append('svg')\n .attr('version', '1.1')\n .attr('xmlns', 'http://www.w3.org/2000/svg')\n .attr('id', plot.id + '_svg').attr('class', 'lz-locuszoom')\n .style(plot.layout.style);\n plot.setDimensions();\n plot.positionPanels();\n // Initialize the plot\n plot.initialize();\n // If the plot has defined data sources then trigger its first mapping based on state values\n if (typeof datasource == 'object' && Object.keys(datasource).length) {\n plot.refresh();\n }\n });\n return plot;\n};\n\n/**\n * Populate arbitrarily many elements each with a LocusZoom plot\n * using a common datasource and layout\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot[]}\n */\nLocusZoom.populateAll = function(selector, datasource, layout) {\n var plots = [];\n d3.selectAll(selector).each(function(d,i) {\n plots[i] = LocusZoom.populate(this, datasource, layout);\n });\n return plots;\n};\n\n/**\n * Convert an integer chromosome position to an SI string representation (e.g. 23423456 => \"23.42\" (Mb))\n * @param {Number} pos Position\n * @param {Number} [exp] Exponent to use for the returned string, eg 6=> MB. If not specified, will attempt to guess\n * the most appropriate SI prefix based on the number provided.\n * @param {Boolean} [suffix=false] Whether or not to append a suffix (e.g. \"Mb\") to the end of the returned string\n * @returns {string}\n */\nLocusZoom.positionIntToString = function(pos, exp, suffix) {\n var exp_symbols = { 0: '', 3: 'K', 6: 'M', 9: 'G' };\n suffix = suffix || false;\n if (isNaN(exp) || exp === null) {\n var log = Math.log(pos) / Math.LN10;\n exp = Math.min(Math.max(log - (log % 3), 0), 9);\n }\n var places_exp = exp - Math.floor((Math.log(pos) / Math.LN10).toFixed(exp + 3));\n var min_exp = Math.min(Math.max(exp, 0), 2);\n var places = Math.min(Math.max(places_exp, min_exp), 12);\n var ret = '' + (pos / Math.pow(10, exp)).toFixed(places);\n if (suffix && typeof exp_symbols[exp] !== 'undefined') {\n ret += ' ' + exp_symbols[exp] + 'b';\n }\n return ret;\n};\n\n/**\n * Convert an SI string chromosome position to an integer representation (e.g. \"5.8 Mb\" => 58000000)\n * @param {String} p The chromosome position\n * @returns {Number}\n */\nLocusZoom.positionStringToInt = function(p) {\n var val = p.toUpperCase();\n val = val.replace(/,/g, '');\n var suffixre = /([KMG])[B]*$/;\n var suffix = suffixre.exec(val);\n var mult = 1;\n if (suffix) {\n if (suffix[1] === 'M') {\n mult = 1e6;\n } else if (suffix[1] === 'G') {\n mult = 1e9;\n } else {\n mult = 1e3; //K\n }\n val = val.replace(suffixre,'');\n }\n val = Number(val) * mult;\n return val;\n};\n\n/**\n * Parse region queries into their constituent parts\n * TODO: handle genes (or send off to API)\n * @param {String} x A chromosome position query. May be any of the forms `chr:start-end`, `chr:center+offset`,\n * or `chr:pos`\n * @returns {{chr:*, start: *, end:*} | {chr:*, position:*}}\n */\nLocusZoom.parsePositionQuery = function(x) {\n var chrposoff = /^(\\w+):([\\d,.]+[kmgbKMGB]*)([-+])([\\d,.]+[kmgbKMGB]*)$/;\n var chrpos = /^(\\w+):([\\d,.]+[kmgbKMGB]*)$/;\n var match = chrposoff.exec(x);\n if (match) {\n if (match[3] === '+') {\n var center = LocusZoom.positionStringToInt(match[2]);\n var offset = LocusZoom.positionStringToInt(match[4]);\n return {\n chr:match[1],\n start: center - offset,\n end: center + offset\n };\n } else {\n return {\n chr: match[1],\n start: LocusZoom.positionStringToInt(match[2]),\n end: LocusZoom.positionStringToInt(match[4])\n };\n }\n }\n match = chrpos.exec(x);\n if (match) {\n return {\n chr:match[1],\n position: LocusZoom.positionStringToInt(match[2])\n };\n }\n return null;\n};\n\n/**\n * Generate a \"pretty\" set of ticks (multiples of 1, 2, or 5 on the same order of magnitude for the range)\n * Based on R's \"pretty\" function: https://github.com/wch/r-source/blob/b156e3a711967f58131e23c1b1dc1ea90e2f0c43/src/appl/pretty.c\n * @param {Number[]} range A two-item array specifying [low, high] values for the axis range\n * @param {('low'|'high'|'both'|'neither')} [clip_range='neither'] What to do if first and last generated ticks extend\n * beyond the range. Set this to \"low\", \"high\", \"both\", or \"neither\" to clip the first (low) or last (high) tick to\n * be inside the range or allow them to extend beyond.\n * e.g. \"low\" will clip the first (low) tick if it extends beyond the low end of the range but allow the\n * last (high) tick to extend beyond the range. \"both\" clips both ends, \"neither\" allows both to extend beyond.\n * @param {Number} [target_tick_count=5] The approximate number of ticks you would like to be returned; may not be exact\n * @returns {Number[]}\n */\nLocusZoom.prettyTicks = function(range, clip_range, target_tick_count) {\n if (typeof target_tick_count == 'undefined' || isNaN(parseInt(target_tick_count))) {\n target_tick_count = 5;\n }\n target_tick_count = parseInt(target_tick_count);\n\n var min_n = target_tick_count / 3;\n var shrink_sml = 0.75;\n var high_u_bias = 1.5;\n var u5_bias = 0.5 + 1.5 * high_u_bias;\n\n var d = Math.abs(range[0] - range[1]);\n var c = d / target_tick_count;\n if ((Math.log(d) / Math.LN10) < -2) {\n c = (Math.max(Math.abs(d)) * shrink_sml) / min_n;\n }\n\n var base = Math.pow(10, Math.floor(Math.log(c) / Math.LN10));\n var base_toFixed = 0;\n if (base < 1 && base !== 0) {\n base_toFixed = Math.abs(Math.round(Math.log(base) / Math.LN10));\n }\n\n var unit = base;\n if ( ((2 * base) - c) < (high_u_bias * (c - unit)) ) {\n unit = 2 * base;\n if ( ((5 * base) - c) < (u5_bias * (c - unit)) ) {\n unit = 5 * base;\n if ( ((10 * base) - c) < (high_u_bias * (c - unit)) ) {\n unit = 10 * base;\n }\n }\n }\n\n var ticks = [];\n var i = parseFloat( (Math.floor(range[0] / unit) * unit).toFixed(base_toFixed) );\n while (i < range[1]) {\n ticks.push(i);\n i += unit;\n if (base_toFixed > 0) {\n i = parseFloat(i.toFixed(base_toFixed));\n }\n }\n ticks.push(i);\n\n if (typeof clip_range == 'undefined' || ['low', 'high', 'both', 'neither'].indexOf(clip_range) === -1) {\n clip_range = 'neither';\n }\n if (clip_range === 'low' || clip_range === 'both') {\n if (ticks[0] < range[0]) { ticks = ticks.slice(1); }\n }\n if (clip_range === 'high' || clip_range === 'both') {\n if (ticks[ticks.length - 1] > range[1]) { ticks.pop(); }\n }\n\n return ticks;\n};\n\n/**\n * Make an AJAX request and return a promise.\n * From http://www.html5rocks.com/en/tutorials/cors/\n * and with promises from https://gist.github.com/kriskowal/593076\n *\n * @param {String} method The HTTP verb\n * @param {String} url\n * @param {String} [body] The request body to send to the server\n * @param {Object} [headers] Object of custom request headers\n * @param {Number} [timeout] If provided, wait this long (in ms) before timing out\n * @returns {Promise}\n */\nLocusZoom.createCORSPromise = function (method, url, body, headers, timeout) {\n return new Promise(function (resolve, reject) {\n var xhr = new XMLHttpRequest();\n if ('withCredentials' in xhr) {\n // Check if the XMLHttpRequest object has a \"withCredentials\" property.\n // \"withCredentials\" only exists on XMLHTTPRequest2 objects.\n xhr.open(method, url, true);\n } else if (typeof XDomainRequest != 'undefined') {\n // Otherwise, check if XDomainRequest.\n // XDomainRequest only exists in IE, and is IE's way of making CORS requests.\n xhr = new XDomainRequest();\n xhr.open(method, url);\n } else {\n // Otherwise, CORS is not supported by the browser.\n xhr = null;\n }\n if (xhr) {\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4) {\n if (xhr.status === 200 || xhr.status === 0 ) {\n resolve(xhr.response);\n } else {\n reject('HTTP ' + xhr.status + ' for ' + url);\n }\n }\n };\n timeout && setTimeout(reject, timeout);\n body = typeof body !== 'undefined' ? body : '';\n if (typeof headers !== 'undefined') {\n for (var header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n }\n // Send the request\n xhr.send(body);\n }\n });\n};\n\n/**\n * Validate a (presumed complete) plot state object against internal rules for consistency, and ensure the plot fits\n * within any constraints imposed by the layout.\n * @param {Object} new_state\n * @param {Number} new_state.start\n * @param {Number} new_state.end\n * @param {Object} layout\n * @returns {*|{}}\n */\nLocusZoom.validateState = function(new_state, layout) {\n\n new_state = new_state || {};\n layout = layout || {};\n\n // If a \"chr\", \"start\", and \"end\" are present then resolve start and end\n // to numeric values that are not decimal, negative, or flipped\n var validated_region = false;\n if (typeof new_state.chr != 'undefined' && typeof new_state.start != 'undefined' && typeof new_state.end != 'undefined') {\n // Determine a numeric scale and midpoint for the attempted region,\n var attempted_midpoint = null; var attempted_scale;\n new_state.start = Math.max(parseInt(new_state.start), 1);\n new_state.end = Math.max(parseInt(new_state.end), 1);\n if (isNaN(new_state.start) && isNaN(new_state.end)) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_midpoint = 0.5;\n attempted_scale = 0;\n } else if (isNaN(new_state.start) || isNaN(new_state.end)) {\n attempted_midpoint = new_state.start || new_state.end;\n attempted_scale = 0;\n new_state.start = (isNaN(new_state.start) ? new_state.end : new_state.start);\n new_state.end = (isNaN(new_state.end) ? new_state.start : new_state.end);\n } else {\n attempted_midpoint = Math.round((new_state.start + new_state.end) / 2);\n attempted_scale = new_state.end - new_state.start;\n if (attempted_scale < 0) {\n var temp = new_state.start;\n new_state.end = new_state.start;\n new_state.start = temp;\n attempted_scale = new_state.end - new_state.start;\n }\n if (attempted_midpoint < 0) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_scale = 0;\n }\n }\n validated_region = true;\n }\n\n // Constrain w/r/t layout-defined minimum region scale\n if (!isNaN(layout.min_region_scale) && validated_region && attempted_scale < layout.min_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.min_region_scale / 2), 1);\n new_state.end = new_state.start + layout.min_region_scale;\n }\n\n // Constrain w/r/t layout-defined maximum region scale\n if (!isNaN(layout.max_region_scale) && validated_region && attempted_scale > layout.max_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.max_region_scale / 2), 1);\n new_state.end = new_state.start + layout.max_region_scale;\n }\n\n return new_state;\n};\n\n//\n/**\n * Replace placeholders in an html string with field values defined in a data object\n * Only works on scalar values! Will ignore non-scalars.\n *\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @param {Object} data\n * @param {String} html A placeholder string in which to substitute fields. Supports several template options:\n * `{{field_name}}` is a variable placeholder for the value of `field_name` from the provided data\n * `{{#if field_name}} Conditional text {{/if}}` will insert the contents of the tag only if the value exists.\n * Since this is only an existence check, **variables with a value of 0 will be evaluated as true**.\n * This can be used with namespaced values, `{{#if assoc:field}}`; any dynamic namespacing will be applied when the\n * layout is first retrieved.\n * @returns {string}\n */\nLocusZoom.parseFields = function (data, html) {\n if (typeof data != 'object') {\n throw new Error('LocusZoom.parseFields invalid arguments: data is not an object');\n }\n if (typeof html != 'string') {\n throw new Error('LocusZoom.parseFields invalid arguments: html is not a string');\n }\n // `tokens` is like [token,...]\n // `token` is like {text: '...'} or {variable: 'foo|bar'} or {condition: 'foo|bar'} or {close: 'if'}\n var tokens = [];\n var regex = /\\{\\{(?:(#if )?([A-Za-z0-9_:|]+)|(\\/if))\\}\\}/;\n while (html.length > 0) {\n var m = regex.exec(html);\n if (!m) { tokens.push({text: html}); html = ''; }\n else if (m.index !== 0) { tokens.push({text: html.slice(0, m.index)}); html = html.slice(m.index); }\n else if (m[1] === '#if ') { tokens.push({condition: m[2]}); html = html.slice(m[0].length); }\n else if (m[2]) { tokens.push({variable: m[2]}); html = html.slice(m[0].length); }\n else if (m[3] === '/if') { tokens.push({close: 'if'}); html = html.slice(m[0].length); }\n else {\n console.error('Error tokenizing tooltip when remaining template is ' + JSON.stringify(html) +\n ' and previous tokens are ' + JSON.stringify(tokens) +\n ' and current regex match is ' + JSON.stringify([m[1], m[2], m[3]]));\n html = html.slice(m[0].length);\n }\n }\n var astify = function() {\n var token = tokens.shift();\n if (typeof token.text !== 'undefined' || token.variable) {\n return token;\n } else if (token.condition) {\n token.then = [];\n while(tokens.length > 0) {\n if (tokens[0].close === 'if') { tokens.shift(); break; }\n token.then.push(astify());\n }\n return token;\n } else {\n console.error('Error making tooltip AST due to unknown token ' + JSON.stringify(token));\n return { text: '' };\n }\n };\n // `ast` is like [thing,...]\n // `thing` is like {text: \"...\"} or {variable:\"foo|bar\"} or {condition: \"foo|bar\", then:[thing,...]}\n var ast = [];\n while (tokens.length > 0) {\n ast.push(astify());\n }\n\n var resolve = function(variable) {\n if (!resolve.cache.hasOwnProperty(variable)) {\n resolve.cache[variable] = (new LocusZoom.Data.Field(variable)).resolve(data);\n }\n return resolve.cache[variable];\n };\n resolve.cache = {};\n var render_node = function(node) {\n if (typeof node.text !== 'undefined') {\n return node.text;\n } else if (node.variable) {\n try {\n var value = resolve(node.variable);\n if (['string','number','boolean'].indexOf(typeof value) !== -1) { return value; }\n if (value === null) { return ''; }\n } catch (error) { console.error('Error while processing variable ' + JSON.stringify(node.variable)); }\n return '{{' + node.variable + '}}';\n } else if (node.condition) {\n try {\n var condition = resolve(node.condition);\n if (condition || condition === 0) {\n return node.then.map(render_node).join('');\n }\n } catch (error) { console.error('Error while processing condition ' + JSON.stringify(node.variable)); }\n return '';\n } else { console.error('Error rendering tooltip due to unknown AST node ' + JSON.stringify(node)); }\n };\n return ast.map(render_node).join('');\n};\n\n/**\n * Shortcut method for getting the data bound to a tool tip.\n * @param {Element} node\n * @returns {*} The first element of data bound to the tooltip\n */\nLocusZoom.getToolTipData = function(node) {\n if (typeof node != 'object' || typeof node.parentNode == 'undefined') {\n throw new Error('Invalid node object');\n }\n // If this node is a locuszoom tool tip then return its data\n var selector = d3.select(node);\n if (selector.classed('lz-data_layer-tooltip') && typeof selector.data()[0] != 'undefined') {\n return selector.data()[0];\n } else {\n return LocusZoom.getToolTipData(node.parentNode);\n }\n};\n\n/**\n * Shortcut method for getting a reference to the data layer that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.getToolTipDataLayer = function(node) {\n var data = LocusZoom.getToolTipData(node);\n if (data.getDataLayer) { return data.getDataLayer(); }\n return null;\n};\n\n/**\n * Shortcut method for getting a reference to the panel that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.getToolTipPanel = function(node) {\n var data_layer = LocusZoom.getToolTipDataLayer(node);\n if (data_layer) { return data_layer.parent; }\n return null;\n};\n\n/**\n * Shortcut method for getting a reference to the plot that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.getToolTipPlot = function(node) {\n var panel = LocusZoom.getToolTipPanel(node);\n if (panel) { return panel.parent; }\n return null;\n};\n\n/**\n * Generate a curtain object for a plot, panel, or any other subdivision of a layout\n * The panel curtain, like the plot curtain is an HTML overlay that obscures the entire panel. It can be styled\n * arbitrarily and display arbitrary messages. It is useful for reporting error messages visually to an end user\n * when the error renders the panel unusable.\n * TODO: Improve type doc here\n * @returns {object}\n */\nLocusZoom.generateCurtain = function() {\n var curtain = {\n showing: false,\n selector: null,\n content_selector: null,\n hide_delay: null,\n\n /**\n * Generate the curtain. Any content (string) argument passed will be displayed in the curtain as raw HTML.\n * CSS (object) can be passed which will apply styles to the curtain and its content.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n show: function(content, css) {\n if (!this.curtain.showing) {\n this.curtain.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div')\n .attr('class', 'lz-curtain').attr('id', this.id + '.curtain');\n this.curtain.content_selector = this.curtain.selector.append('div').attr('class', 'lz-curtain-content');\n this.curtain.selector.append('div').attr('class', 'lz-curtain-dismiss').html('Dismiss')\n .on('click', function() {\n this.curtain.hide();\n }.bind(this));\n this.curtain.showing = true;\n }\n return this.curtain.update(content, css);\n }.bind(this),\n\n /**\n * Update the content and css of the curtain that's currently being shown. This method also adjusts the size\n * and positioning of the curtain to ensure it still covers the entire panel with no overlap.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n update: function(content, css) {\n if (!this.curtain.showing) { return this.curtain; }\n clearTimeout(this.curtain.hide_delay);\n // Apply CSS if provided\n if (typeof css == 'object') {\n this.curtain.selector.style(css);\n }\n // Update size and position\n var page_origin = this.getPageOrigin();\n this.curtain.selector.style({\n top: page_origin.y + 'px',\n left: page_origin.x + 'px',\n width: this.layout.width + 'px',\n height: this.layout.height + 'px'\n });\n this.curtain.content_selector.style({\n 'max-width': (this.layout.width - 40) + 'px',\n 'max-height': (this.layout.height - 40) + 'px'\n });\n // Apply content if provided\n if (typeof content == 'string') {\n this.curtain.content_selector.html(content);\n }\n return this.curtain;\n }.bind(this),\n\n /**\n * Remove the curtain\n * @param {number} delay Time to wait (in ms)\n */\n hide: function(delay) {\n if (!this.curtain.showing) { return this.curtain; }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.curtain.hide_delay);\n this.curtain.hide_delay = setTimeout(this.curtain.hide, delay);\n return this.curtain;\n }\n // Remove curtain\n this.curtain.selector.remove();\n this.curtain.selector = null;\n this.curtain.content_selector = null;\n this.curtain.showing = false;\n return this.curtain;\n }.bind(this)\n };\n return curtain;\n};\n\n/**\n * Generate a loader object for a plot, panel, or any other subdivision of a layout\n *\n * The panel loader is a small HTML overlay that appears in the lower left corner of the panel. It cannot be styled\n * arbitrarily, but can show a custom message and show a minimalist loading bar that can be updated to specific\n * completion percentages or be animated.\n * TODO Improve type documentation\n * @returns {object}\n */\nLocusZoom.generateLoader = function() {\n var loader = {\n showing: false,\n selector: null,\n content_selector: null,\n progress_selector: null,\n cancel_selector: null,\n\n /**\n * Show a loading indicator\n * @param {string} [content='Loading...'] Loading message (displayed as raw HTML)\n */\n show: function(content) {\n // Generate loader\n if (!this.loader.showing) {\n this.loader.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div')\n .attr('class', 'lz-loader').attr('id', this.id + '.loader');\n this.loader.content_selector = this.loader.selector.append('div')\n .attr('class', 'lz-loader-content');\n this.loader.progress_selector = this.loader.selector\n .append('div').attr('class', 'lz-loader-progress-container')\n .append('div').attr('class', 'lz-loader-progress');\n /* TODO: figure out how to make this cancel button work\n this.loader.cancel_selector = this.loader.selector.append(\"div\")\n .attr(\"class\", \"lz-loader-cancel\").html(\"Cancel\")\n .on(\"click\", function(){\n this.loader.hide();\n }.bind(this));\n */\n this.loader.showing = true;\n if (typeof content == 'undefined') { content = 'Loading...'; }\n }\n return this.loader.update(content);\n }.bind(this),\n\n /**\n * Update the currently displayed loader and ensure the new content is positioned correctly.\n * @param {string} content The text to display (as raw HTML). If not a string, will be ignored.\n * @param {number} [percent] A number from 1-100. If a value is specified, it will stop all animations\n * in progress.\n */\n update: function(content, percent) {\n if (!this.loader.showing) { return this.loader; }\n clearTimeout(this.loader.hide_delay);\n // Apply content if provided\n if (typeof content == 'string') {\n this.loader.content_selector.html(content);\n }\n // Update size and position\n var padding = 6; // is there a better place to store/define this?\n var page_origin = this.getPageOrigin();\n var loader_boundrect = this.loader.selector.node().getBoundingClientRect();\n this.loader.selector.style({\n top: (page_origin.y + this.layout.height - loader_boundrect.height - padding) + 'px',\n left: (page_origin.x + padding) + 'px'\n });\n /* Uncomment this code when a functional cancel button can be shown\n var cancel_boundrect = this.loader.cancel_selector.node().getBoundingClientRect();\n this.loader.content_selector.style({\n \"padding-right\": (cancel_boundrect.width + padding) + \"px\"\n });\n */\n // Apply percent if provided\n if (typeof percent == 'number') {\n this.loader.progress_selector.style({\n width: (Math.min(Math.max(percent, 1), 100)) + '%'\n });\n }\n return this.loader;\n }.bind(this),\n\n /**\n * Adds a class to the loading bar that makes it loop infinitely in a loading animation. Useful when exact\n * percent progress is not available.\n */\n animate: function() {\n this.loader.progress_selector.classed('lz-loader-progress-animated', true);\n return this.loader;\n }.bind(this),\n\n /**\n * Sets the loading bar in the loader to percentage width equal to the percent (number) value passed. Percents\n * will automatically be limited to a range of 1 to 100. Will stop all animations in progress.\n */\n setPercentCompleted: function(percent) {\n this.loader.progress_selector.classed('lz-loader-progress-animated', false);\n return this.loader.update(null, percent);\n }.bind(this),\n\n /**\n * Remove the loader\n * @param {number} delay Time to wait (in ms)\n */\n hide: function(delay) {\n if (!this.loader.showing) { return this.loader; }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.loader.hide_delay);\n this.loader.hide_delay = setTimeout(this.loader.hide, delay);\n return this.loader;\n }\n // Remove loader\n this.loader.selector.remove();\n this.loader.selector = null;\n this.loader.content_selector = null;\n this.loader.progress_selector = null;\n this.loader.cancel_selector = null;\n this.loader.showing = false;\n return this.loader;\n }.bind(this)\n };\n return loader;\n};\n\n/**\n * Create a new subclass following classical inheritance patterns. Some registry singletons use this internally to\n * enable code reuse and customization of known LZ core functionality.\n *\n * @param {Function} parent A parent class constructor that will be extended by the child class\n * @param {Object} extra An object of additional properties and methods to add/override behavior for the child class.\n * The special \"constructor\" property can be used to specify a custom constructor, or it will call parent by default.\n * Implementer must manage super calls when overriding the constructor.\n * @returns {Function} The constructor for the new child class\n */\nLocusZoom.subclass = function(parent, extra) {\n if (typeof parent !== 'function' ) {\n throw new Error('Parent must be a callable constructor');\n }\n\n extra = extra || {};\n var Sub = extra.hasOwnProperty('constructor') ? extra.constructor : function() {\n parent.apply(this, arguments);\n };\n\n Sub.prototype = Object.create(parent.prototype);\n Object.keys(extra).forEach(function(k) {\n Sub.prototype[k] = extra[k];\n });\n return Sub;\n};\n\n\n/**\n * LocusZoom optional extensions will live under this namespace.\n *\n * Extension code is not part of the core LocusZoom app.js bundle.\n * @namespace\n * @public\n */\nLocusZoom.ext = {};\n","/* global LocusZoom */\n'use strict';\n\nvar LZ_SIG_THRESHOLD_LOGP = 7.301; // -log10(.05/1e6)\n\n/**\n * Manage known layouts for all parts of the LocusZoom plot\n *\n * This registry allows for layouts to be reused and customized many times on a page, using a common base pattern.\n * It handles the work of ensuring that each new instance of the layout has no shared state with other copies.\n *\n * @class\n */\nLocusZoom.Layouts = (function () {\n var obj = {};\n var layouts = {\n 'plot': {},\n 'panel': {},\n 'data_layer': {},\n 'dashboard': {},\n 'dashboard_components': {},\n 'tooltip': {}\n };\n\n /**\n * Generate a layout configuration object\n * @param {('plot'|'panel'|'data_layer'|'dashboard'|'tooltip')} type The type of layout to retrieve\n * @param {string} name Identifier of the predefined layout within the specified type\n * @param {object} [modifications] Custom properties that override default settings for this layout\n * @returns {object} A JSON-serializable object representation\n */\n obj.get = function (type, name, modifications) {\n if (typeof type != 'string' || typeof name != 'string') {\n throw new Error('invalid arguments passed to LocusZoom.Layouts.get, requires string (layout type) and string (layout name)');\n } else if (layouts[type][name]) {\n // Get the base layout\n var layout = LocusZoom.Layouts.merge(modifications || {}, layouts[type][name]);\n // If \"unnamespaced\" is true then strike that from the layout and return the layout without namespacing\n if (layout.unnamespaced) {\n delete layout.unnamespaced;\n return JSON.parse(JSON.stringify(layout));\n }\n // Determine the default namespace for namespaced values\n var default_namespace = '';\n if (typeof layout.namespace == 'string') {\n default_namespace = layout.namespace;\n } else if (typeof layout.namespace == 'object' && Object.keys(layout.namespace).length) {\n if (typeof layout.namespace.default != 'undefined') {\n default_namespace = layout.namespace.default;\n } else {\n default_namespace = layout.namespace[Object.keys(layout.namespace)[0]].toString();\n }\n }\n default_namespace += default_namespace.length ? ':' : '';\n // Apply namespaces to layout, recursively\n var applyNamespaces = function (element, namespace) {\n if (namespace) {\n if (typeof namespace == 'string') {\n namespace = { default: namespace };\n }\n } else {\n namespace = { default: '' };\n }\n if (typeof element == 'string') {\n var re = /\\{\\{namespace(\\[[A-Za-z_0-9]+\\]|)\\}\\}/g;\n var match, base, key, resolved_namespace;\n var replace = [];\n while ((match = re.exec(element)) !== null) {\n base = match[0];\n key = match[1].length ? match[1].replace(/(\\[|\\])/g, '') : null;\n resolved_namespace = default_namespace;\n if (namespace != null && typeof namespace == 'object' && typeof namespace[key] != 'undefined') {\n resolved_namespace = namespace[key] + (namespace[key].length ? ':' : '');\n }\n replace.push({ base: base, namespace: resolved_namespace });\n }\n for (var r in replace) {\n element = element.replace(replace[r].base, replace[r].namespace);\n }\n } else if (typeof element == 'object' && element != null) {\n if (typeof element.namespace != 'undefined') {\n var merge_namespace = (typeof element.namespace == 'string') ? { default: element.namespace } : element.namespace;\n namespace = LocusZoom.Layouts.merge(namespace, merge_namespace);\n }\n var namespaced_element, namespaced_property;\n for (var property in element) {\n if (property === 'namespace') {\n continue;\n }\n namespaced_element = applyNamespaces(element[property], namespace);\n namespaced_property = applyNamespaces(property, namespace);\n if (property !== namespaced_property) {\n delete element[property];\n }\n element[namespaced_property] = namespaced_element;\n }\n }\n return element;\n };\n layout = applyNamespaces(layout, layout.namespace);\n // Return the layout as valid JSON only\n return JSON.parse(JSON.stringify(layout));\n } else {\n throw new Error('layout type [' + type + '] name [' + name + '] not found');\n }\n };\n\n /** @private */\n obj.set = function (type, name, layout) {\n if (typeof type != 'string' || typeof name != 'string' || typeof layout != 'object') {\n throw new Error('unable to set new layout; bad arguments passed to set()');\n }\n if (!layouts[type]) {\n layouts[type] = {};\n }\n if (layout) {\n return (layouts[type][name] = JSON.parse(JSON.stringify(layout)));\n } else {\n delete layouts[type][name];\n return null;\n }\n };\n\n /**\n * Register a new layout definition by name.\n *\n * @param {string} type The type of layout to add. Usually, this will be one of the predefined LocusZoom types,\n * but if you pass a different name, this method will automatically create the new `type` bucket\n * @param {string} name The identifier of the newly added layout\n * @param {object} [layout] A JSON-serializable object containing configuration properties for this layout\n * @returns The JSON representation of the newly created layout\n */\n obj.add = function (type, name, layout) {\n return obj.set(type, name, layout);\n };\n\n /**\n * List all registered layouts\n * @param [type] Optionally narrow the list to only layouts of a specific type; else return all known layouts\n * @returns {*}\n */\n obj.list = function (type) {\n if (!layouts[type]) {\n var list = {};\n Object.keys(layouts).forEach(function (type) {\n list[type] = Object.keys(layouts[type]);\n });\n return list;\n } else {\n return Object.keys(layouts[type]);\n }\n };\n\n /**\n * A helper method used for merging two objects. If a key is present in both, takes the value from the first object\n * Values from `default_layout` will be cleanly copied over, ensuring no references or shared state.\n *\n * Frequently used for preparing custom layouts. Both objects should be JSON-serializable.\n *\n * @param {object} custom_layout An object containing configuration parameters that override or add to defaults\n * @param {object} default_layout An object containing default settings.\n * @returns {object} The custom layout is modified in place and also returned from this method.\n */\n obj.merge = function (custom_layout, default_layout) {\n if (typeof custom_layout !== 'object' || typeof default_layout !== 'object') {\n throw new Error('LocusZoom.Layouts.merge only accepts two layout objects; ' + (typeof custom_layout) + ', ' + (typeof default_layout) + ' given');\n }\n for (var property in default_layout) {\n if (!default_layout.hasOwnProperty(property)) {\n continue;\n }\n // Get types for comparison. Treat nulls in the custom layout as undefined for simplicity.\n // (javascript treats nulls as \"object\" when we just want to overwrite them as if they're undefined)\n // Also separate arrays from objects as a discrete type.\n var custom_type = custom_layout[property] === null ? 'undefined' : typeof custom_layout[property];\n var default_type = typeof default_layout[property];\n if (custom_type === 'object' && Array.isArray(custom_layout[property])) {\n custom_type = 'array';\n }\n if (default_type === 'object' && Array.isArray(default_layout[property])) {\n default_type = 'array';\n }\n // Unsupported property types: throw an exception\n if (custom_type === 'function' || default_type === 'function') {\n throw new Error('LocusZoom.Layouts.merge encountered an unsupported property type');\n }\n // Undefined custom value: pull the default value\n if (custom_type === 'undefined') {\n custom_layout[property] = JSON.parse(JSON.stringify(default_layout[property]));\n continue;\n }\n // Both values are objects: merge recursively\n if (custom_type === 'object' && default_type === 'object') {\n custom_layout[property] = LocusZoom.Layouts.merge(custom_layout[property], default_layout[property]);\n continue;\n }\n }\n return custom_layout;\n };\n\n return obj;\n})();\n\n\n/**\n * Tooltip Layouts\n * @namespace LocusZoom.Layouts.tooltips\n */\n\nLocusZoom.Layouts.add('tooltip', 'standard_association', {\n namespace: { 'assoc': 'assoc' },\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[assoc]}}variant|htmlescape}}
'\n + 'P Value: {{{{namespace[assoc]}}log_pvalue|logtoscinotation|htmlescape}}
'\n + 'Ref. Allele: {{{{namespace[assoc]}}ref_allele|htmlescape}}
'\n + 'Make LD Reference
'\n});\n\nLocusZoom.Layouts.add('tooltip', 'covariates_model_association', function () {\n var covariates_model_association = LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true });\n covariates_model_association.html += 'Condition on Variant
';\n return covariates_model_association;\n}());\n\nLocusZoom.Layouts.add('tooltip', 'standard_genes', {\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '

{{gene_name|htmlescape}}

'\n + 'Gene ID: {{gene_id|htmlescape}}
'\n + 'Transcript ID: {{transcript_id|htmlescape}}
'\n + '{{#if pLI}}'\n + ''\n + ''\n + ''\n + ''\n + '
ConstraintExpected variantsObserved variantsConst. Metric
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
o/e = {{oe_syn}} ({{oe_syn_lower}} - {{oe_syn_upper}})
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
o/e = {{oe_mis}} ({{oe_mis_lower}} - {{oe_mis_upper}})
pLoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
o/e = {{oe_lof}} ({{oe_lof_lower}} - {{oe_lof_upper}})

{{/if}}'\n + 'More data on gnomAD'\n});\n\nLocusZoom.Layouts.add('tooltip', 'standard_intervals', {\n namespace: { 'intervals': 'intervals' },\n closable: false,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[intervals]}}state_name|htmlescape}}
{{{{namespace[intervals]}}start|htmlescape}}-{{{{namespace[intervals]}}end|htmlescape}}'\n});\n\nLocusZoom.Layouts.add('tooltip', 'catalog_variant', {\n namespace: { 'assoc': 'assoc', 'catalog': 'catalog' },\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[catalog]}}variant|htmlescape}}
'\n + 'Catalog entries: {{n_catalog_matches|htmlescape}}
'\n + 'Top Trait: {{{{namespace[catalog]}}trait|htmlescape}}
'\n + 'Top P Value: {{{{namespace[catalog]}}log_pvalue|logtoscinotation}}
'\n // User note: if a different catalog is used, the tooltip will need to be replaced with a different link URL\n + 'More: GWAS catalog / dbSNP'\n});\n\n/**\n * Data Layer Layouts: represent specific information from a data source\n * @namespace Layouts.data_layer\n */\n\nLocusZoom.Layouts.add('data_layer', 'significance', {\n id: 'significance',\n type: 'orthogonal_line',\n orientation: 'horizontal',\n offset: LZ_SIG_THRESHOLD_LOGP\n});\n\nLocusZoom.Layouts.add('data_layer', 'recomb_rate', {\n namespace: { 'recomb': 'recomb' },\n id: 'recombrate',\n type: 'line',\n fields: ['{{namespace[recomb]}}position', '{{namespace[recomb]}}recomb_rate'],\n z_index: 1,\n style: {\n 'stroke': '#0000FF',\n 'stroke-width': '1.5px'\n },\n x_axis: {\n field: '{{namespace[recomb]}}position'\n },\n y_axis: {\n axis: 2,\n field: '{{namespace[recomb]}}recomb_rate',\n floor: 0,\n ceiling: 100\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'association_pvalues', {\n namespace: { 'assoc': 'assoc', 'ld': 'ld' },\n id: 'associationpvalues',\n type: 'scatter',\n point_shape: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 'diamond',\n else: 'circle'\n }\n },\n point_size: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 80,\n else: 40\n }\n },\n color: [\n {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: '#9632b8'\n }\n },\n {\n scale_function: 'numerical_bin',\n field: '{{namespace[ld]}}state',\n parameters: {\n breaks: [0, 0.2, 0.4, 0.6, 0.8],\n values: ['#357ebd', '#46b8da', '#5cb85c', '#eea236', '#d43f3a']\n }\n },\n '#B8B8B8'\n ],\n legend: [\n { shape: 'diamond', color: '#9632b8', size: 40, label: 'LD Ref Var', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#d43f3a', size: 40, label: '1.0 > r² ≥ 0.8', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#eea236', size: 40, label: '0.8 > r² ≥ 0.6', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#5cb85c', size: 40, label: '0.6 > r² ≥ 0.4', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#46b8da', size: 40, label: '0.4 > r² ≥ 0.2', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#357ebd', size: 40, label: '0.2 > r² ≥ 0.0', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#B8B8B8', size: 40, label: 'no r² data', class: 'lz-data_layer-scatter' }\n ],\n label: null,\n fields: ['{{namespace[assoc]}}variant', '{{namespace[assoc]}}position', '{{namespace[assoc]}}log_pvalue', '{{namespace[assoc]}}log_pvalue|logtoscinotation', '{{namespace[assoc]}}ref_allele', '{{namespace[ld]}}state', '{{namespace[ld]}}isrefvar'],\n id_field: '{{namespace[assoc]}}variant',\n z_index: 2,\n x_axis: {\n field: '{{namespace[assoc]}}position'\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[assoc]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.10,\n min_extent: [0, 10]\n },\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'association_pvalues_catalog', function () {\n // Slightly modify an existing layout\n var l = LocusZoom.Layouts.get('data_layer', 'association_pvalues', {\n unnamespaced: true,\n id: 'associationpvaluescatalog',\n fill_opacity: 0.7\n });\n l.tooltip.html += '{{#if {{namespace[catalog]}}rsid}}
See hits in GWAS catalog{{/if}}';\n l.namespace.catalog = 'catalog';\n l.fields.push('{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait', '{{namespace[catalog]}}log_pvalue');\n return l;\n}());\n\nLocusZoom.Layouts.add('data_layer', 'phewas_pvalues', {\n namespace: { 'phewas': 'phewas' },\n id: 'phewaspvalues',\n type: 'category_scatter',\n point_shape: 'circle',\n point_size: 70,\n tooltip_positioning: 'vertical',\n id_field: '{{namespace[phewas]}}id',\n fields: ['{{namespace[phewas]}}id', '{{namespace[phewas]}}log_pvalue', '{{namespace[phewas]}}trait_group', '{{namespace[phewas]}}trait_label'],\n x_axis: {\n field: '{{namespace[phewas]}}x', // Synthetic/derived field added by `category_scatter` layer\n category_field: '{{namespace[phewas]}}trait_group',\n lower_buffer: 0.025,\n upper_buffer: 0.025\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[phewas]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.15\n },\n color: [{\n field: '{{namespace[phewas]}}trait_group',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [],\n values: [],\n null_value: '#B8B8B8'\n }\n }],\n fill_opacity: 0.7,\n tooltip: {\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: [\n 'Trait: {{{{namespace[phewas]}}trait_label|htmlescape}}
',\n 'Trait Category: {{{{namespace[phewas]}}trait_group|htmlescape}}
',\n 'P-value: {{{{namespace[phewas]}}log_pvalue|logtoscinotation|htmlescape}}
'\n ].join('')\n },\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n label: {\n text: '{{{{namespace[phewas]}}trait_label|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n {\n field: '{{namespace[phewas]}}log_pvalue',\n operator: '>=',\n value: 20\n }\n ],\n style: {\n 'font-size': '14px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'genes', {\n namespace: { 'gene': 'gene', 'constraint': 'constraint' },\n id: 'genes',\n type: 'genes',\n fields: ['{{namespace[gene]}}all', '{{namespace[constraint]}}all'],\n id_field: 'gene_id',\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_genes', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'genome_legend', {\n namespace: { 'genome': 'genome' },\n id: 'genome_legend',\n type: 'genome_legend',\n fields: ['{{namespace[genome]}}chr', '{{namespace[genome]}}base_pairs'],\n x_axis: {\n floor: 0,\n ceiling: 2881033286\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'intervals', {\n namespace: { 'intervals': 'intervals' },\n id: 'intervals',\n type: 'intervals',\n fields: ['{{namespace[intervals]}}start', '{{namespace[intervals]}}end', '{{namespace[intervals]}}state_id', '{{namespace[intervals]}}state_name'],\n id_field: '{{namespace[intervals]}}start',\n start_field: '{{namespace[intervals]}}start',\n end_field: '{{namespace[intervals]}}end',\n track_split_field: '{{namespace[intervals]}}state_id',\n split_tracks: true,\n always_hide_legend: false,\n color: {\n field: '{{namespace[intervals]}}state_id',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],\n values: ['rgb(212,63,58)', 'rgb(250,120,105)', 'rgb(252,168,139)', 'rgb(240,189,66)', 'rgb(250,224,105)', 'rgb(240,238,84)', 'rgb(244,252,23)', 'rgb(23,232,252)', 'rgb(32,191,17)', 'rgb(23,166,77)', 'rgb(32,191,17)', 'rgb(162,133,166)', 'rgb(212,212,212)'],\n null_value: '#B8B8B8'\n }\n },\n legend: [\n { shape: 'rect', color: 'rgb(212,63,58)', width: 9, label: 'Active Promoter', '{{namespace[intervals]}}state_id': 1 },\n { shape: 'rect', color: 'rgb(250,120,105)', width: 9, label: 'Weak Promoter', '{{namespace[intervals]}}state_id': 2 },\n { shape: 'rect', color: 'rgb(252,168,139)', width: 9, label: 'Poised Promoter', '{{namespace[intervals]}}state_id': 3 },\n { shape: 'rect', color: 'rgb(240,189,66)', width: 9, label: 'Strong enhancer', '{{namespace[intervals]}}state_id': 4 },\n { shape: 'rect', color: 'rgb(250,224,105)', width: 9, label: 'Strong enhancer', '{{namespace[intervals]}}state_id': 5 },\n { shape: 'rect', color: 'rgb(240,238,84)', width: 9, label: 'Weak enhancer', '{{namespace[intervals]}}state_id': 6 },\n { shape: 'rect', color: 'rgb(244,252,23)', width: 9, label: 'Weak enhancer', '{{namespace[intervals]}}state_id': 7 },\n { shape: 'rect', color: 'rgb(23,232,252)', width: 9, label: 'Insulator', '{{namespace[intervals]}}state_id': 8 },\n { shape: 'rect', color: 'rgb(32,191,17)', width: 9, label: 'Transcriptional transition', '{{namespace[intervals]}}state_id': 9 },\n { shape: 'rect', color: 'rgb(23,166,77)', width: 9, label: 'Transcriptional elongation', '{{namespace[intervals]}}state_id': 10 },\n { shape: 'rect', color: 'rgb(136,240,129)', width: 9, label: 'Weak transcribed', '{{namespace[intervals]}}state_id': 11 },\n { shape: 'rect', color: 'rgb(162,133,166)', width: 9, label: 'Polycomb-repressed', '{{namespace[intervals]}}state_id': 12 },\n { shape: 'rect', color: 'rgb(212,212,212)', width: 9, label: 'Heterochromatin / low signal', '{{namespace[intervals]}}state_id': 13 }\n ],\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_intervals', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'annotation_catalog', {\n // Identify GWAS hits that are present in the GWAS catalog\n namespace: { 'assoc': 'assoc', 'catalog': 'catalog' },\n id: 'annotation_catalog',\n type: 'annotation_track',\n id_field: '{{namespace[catalog]}}variant',\n x_axis: {\n field: '{{namespace[assoc]}}position'\n },\n color: '#0000CC',\n fields: [\n '{{namespace[assoc]}}variant', '{{namespace[assoc]}}chromosome', '{{namespace[assoc]}}position',\n '{{namespace[catalog]}}variant', '{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait',\n '{{namespace[catalog]}}log_pvalue', '{{namespace[catalog]}}pos'\n ],\n filters: [\n // Specify which points to show on the track. Any selection must satisfy ALL filters\n ['{{namespace[catalog]}}rsid', '!=', null],\n ['{{namespace[catalog]}}log_pvalue', '>', LZ_SIG_THRESHOLD_LOGP]\n ],\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'catalog_variant', { unnamespaced: true }),\n tooltip_positioning: 'top'\n});\n\n/**\n * Individual dashboard buttons\n * @namespace Layouts.dashboard_components\n */\nLocusZoom.Layouts.add('dashboard_components', 'ldlz2_pop_selector', {\n // **Note**: this widget is aimed at the LDLZ2 datasource, and the UM 1000G LDServer. Older LZ usages\n // (on the original LD data source) will not work with these population names.\n type: 'set_state',\n position: 'right',\n color: 'blue',\n button_html: 'LD Population: ',\n show_selected: true,\n button_title: 'Select LD Population: ',\n state_field: 'ld_pop',\n // This list below is hardcoded to work with the UMich LDServer, default 1000G populations\n // It can be customized to work with other LD servers that specify population differently\n // https://portaldev.sph.umich.edu/ld/genome_builds/GRCh37/references/1000G/populations\n options: [\n { display_name: 'ALL (default)', value: 'ALL' },\n { display_name: 'AFR', value: 'AFR' },\n { display_name: 'AMR', value: 'AMR' },\n { display_name: 'EAS', value: 'EAS' },\n { display_name: 'EUR', value: 'EUR' },\n { display_name: 'SAS', value: 'SAS' }\n ]\n});\n\n/**\n * Dashboard Layouts: Collections of toolbar buttons etc\n * @namespace Layouts.dashboard\n */\nLocusZoom.Layouts.add('dashboard', 'standard_panel', {\n components: [\n {\n type: 'remove_panel',\n position: 'right',\n color: 'red',\n group_position: 'end'\n },\n {\n type: 'move_panel_up',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'move_panel_down',\n position: 'right',\n group_position: 'start',\n style: { 'margin-left': '0.75em' }\n }\n ]\n});\n\nLocusZoom.Layouts.add('dashboard', 'standard_plot', {\n components: [\n {\n type: 'title',\n title: 'LocusZoom',\n subtitle: 'v' + LocusZoom.version + '',\n position: 'left'\n },\n {\n type: 'download',\n position: 'right'\n }\n ]\n});\n\nLocusZoom.Layouts.add('dashboard', 'covariates_model_plot', function () {\n var covariates_model_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n covariates_model_plot_dashboard.components.push({\n type: 'covariates_model',\n button_html: 'Model',\n button_title: 'Show and edit covariates currently in model',\n position: 'left'\n });\n return covariates_model_plot_dashboard;\n}());\n\nLocusZoom.Layouts.add('dashboard', 'region_nav_plot', function () {\n var region_nav_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n region_nav_plot_dashboard.components.push(\n {\n type: 'shift_region',\n step: 500000,\n button_html: '>>',\n position: 'right',\n group_position: 'end'\n }, {\n type: 'shift_region',\n step: 50000,\n button_html: '>',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'zoom_region',\n step: 0.2,\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'zoom_region',\n step: -0.2,\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'shift_region',\n step: -50000,\n button_html: '<',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'shift_region',\n step: -500000,\n button_html: '<<',\n position: 'right',\n group_position: 'start'\n }\n );\n return region_nav_plot_dashboard;\n}());\n\n/**\n * Panel Layouts\n * @namespace Layouts.panel\n */\n\nLocusZoom.Layouts.add('panel', 'association', {\n id: 'association',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 200,\n proportional_width: 1,\n margin: { top: 35, right: 50, bottom: 40, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_legend',\n position: 'right'\n });\n return l;\n })(),\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n },\n y2: {\n label: 'Recombination Rate (cM/Mb)',\n label_offset: 40\n }\n },\n legend: {\n orientation: 'vertical',\n origin: { x: 55, y: 40 },\n hidden: true\n },\n interaction: {\n drag_background_to_pan: true,\n drag_x_ticks_to_scale: true,\n drag_y1_ticks_to_scale: true,\n drag_y2_ticks_to_scale: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'association_catalog', function () {\n var l = LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n id: 'associationcatalog',\n namespace: { 'assoc': 'assoc', 'ld': 'ld', 'catalog': 'catalog' } // Required to resolve display options\n });\n l.dashboard.components.push({\n type: 'display_options',\n position: 'right',\n color: 'blue',\n // Below: special config specific to this widget\n button_html: 'Display options...',\n button_title: 'Control how plot items are displayed',\n\n layer_name: 'associationpvaluescatalog',\n default_config_display_name: 'No catalog labels (default)', // display name for the default plot color option (allow user to revert to plot defaults)\n\n options: [\n {\n // First dropdown menu item\n display_name: 'Label catalog traits', // Human readable representation of field name\n display: { // Specify layout directives that control display of the plot for this option\n label: {\n text: '{{{{namespace[catalog]}}trait|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n // Only label points if they are significant for some trait in the catalog, AND in high LD\n // with the top hit of interest\n {\n field: '{{namespace[catalog]}}trait',\n operator: '!=',\n value: null\n },\n {\n field: '{{namespace[catalog]}}log_pvalue',\n operator: '>',\n value: LZ_SIG_THRESHOLD_LOGP\n },\n {\n field: '{{namespace[ld]}}state',\n operator: '>',\n value: 0.4\n },\n ],\n style: {\n 'font-size': '10px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n }\n }\n ]\n });\n l.data_layers = [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues_catalog', { unnamespaced: true })\n ];\n return l;\n}());\n\nLocusZoom.Layouts.add('panel', 'genes', {\n id: 'genes',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 112.5,\n proportional_width: 1,\n margin: { top: 20, right: 50, bottom: 20, left: 50 },\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'resize_to_data',\n position: 'right',\n button_html: 'Show all genes',\n });\n return l;\n })(),\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'genes', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'phewas', {\n id: 'phewas',\n width: 800,\n height: 300,\n min_width: 800,\n min_height: 300,\n proportional_width: 1,\n margin: { top: 20, right: 50, bottom: 120, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n axes: {\n x: {\n ticks: { // Object based config (shared defaults; allow layers to specify ticks)\n style: {\n 'font-weight': 'bold',\n 'font-size': '11px',\n 'text-anchor': 'start'\n },\n transform: 'rotate(50)',\n position: 'left' // Special param recognized by `category_scatter` layers\n }\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'phewas_pvalues', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'genome_legend', {\n id: 'genome_legend',\n width: 800,\n height: 50,\n origin: { x: 0, y: 300 },\n min_width: 800,\n min_height: 50,\n proportional_width: 1,\n margin: { top: 0, right: 50, bottom: 35, left: 50 },\n axes: {\n x: {\n label: 'Genomic Position (number denotes chromosome)',\n label_offset: 35,\n ticks: [\n {\n x: 124625310,\n text: '1',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 370850307,\n text: '2',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 591461209,\n text: '3',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 786049562,\n text: '4',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 972084330,\n text: '5',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1148099493,\n text: '6',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1313226358,\n text: '7',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1465977701,\n text: '8',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1609766427,\n text: '9',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1748140516,\n text: '10',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1883411148,\n text: '11',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2017840353,\n text: '12',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2142351240,\n text: '13',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2253610949,\n text: '14',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2358551415,\n text: '15',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2454994487,\n text: '16',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2540769469,\n text: '17',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2620405698,\n text: '18',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2689008813,\n text: '19',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2750086065,\n text: '20',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2805663772,\n text: '21',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2855381003,\n text: '22',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n }\n ]\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'genome_legend', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'intervals', {\n id: 'intervals',\n width: 1000,\n height: 50,\n min_width: 500,\n min_height: 50,\n margin: { top: 25, right: 150, bottom: 5, left: 50 },\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_split_tracks',\n data_layer_id: 'intervals',\n position: 'right'\n });\n return l;\n })(),\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n legend: {\n hidden: true,\n orientation: 'horizontal',\n origin: { x: 50, y: 0 },\n pad_from_bottom: 5\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'intervals', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'annotation_catalog', {\n id: 'annotationcatalog',\n width: 800,\n height: 50,\n min_height: 50,\n proportional_width: 1,\n margin: { top: 25, right: 50, bottom: 0, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true }),\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'annotation_catalog', { unnamespaced: true })\n ]\n});\n\n/**\n * Plot Layouts\n * @namespace Layouts.plot\n */\n\nLocusZoom.Layouts.add('plot', 'standard_association', {\n state: {},\n width: 800,\n height: 450,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', { unnamespaced: true, proportional_height: 0.5 }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true, proportional_height: 0.5 })\n ]\n});\n\nLocusZoom.Layouts.add('plot', 'association_catalog', {\n state: {},\n width: 800,\n height: 500,\n responsive_resize: 'width_only',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'annotation_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'association_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true })\n ]\n});\n\n// Shortcut to \"StandardLayout\" for backward compatibility\nLocusZoom.StandardLayout = LocusZoom.Layouts.get('plot', 'standard_association');\n\nLocusZoom.Layouts.add('plot', 'standard_phewas', {\n width: 800,\n height: 600,\n min_width: 800,\n min_height: 600,\n responsive_resize: 'both',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'phewas', { unnamespaced: true, proportional_height: 0.45 }),\n LocusZoom.Layouts.get('panel', 'genome_legend', { unnamespaced: true, proportional_height: 0.1 }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true, proportional_height: 0.45,\n margin: { bottom: 40 },\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n }\n }\n })\n ],\n mouse_guide: false\n});\n\nLocusZoom.Layouts.add('plot', 'interval_association', {\n state: {},\n width: 800,\n height: 550,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n width: 800,\n proportional_height: (225 / 570)\n }),\n LocusZoom.Layouts.get('panel', 'intervals', { unnamespaced: true, proportional_height: (120 / 570) }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true, width: 800, proportional_height: (225 / 570) })\n ]\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A data layer is an abstract class representing a data set and its graphical representation within a panel\n * @public\n * @class\n * @param {Object} layout A JSON-serializable object describing the layout for this layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n*/\nLocusZoom.DataLayer = function(layout, parent) {\n /** @member {Boolean} */\n this.initialized = false;\n /** @member {Number} */\n this.layout_idx = null;\n\n /** @member {String} */\n this.id = null;\n /** @member {LocusZoom.Panel} */\n this.parent = parent || null;\n /**\n * @member {{group: d3.selection, container: d3.selection, clipRect: d3.selection}}\n */\n this.svg = {};\n\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n if (typeof parent != 'undefined' && parent instanceof LocusZoom.Panel) { this.parent_plot = parent.parent; }\n\n /** @member {Object} */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.DataLayer.DefaultLayout);\n if (this.layout.id) { this.id = this.layout.id; }\n\n // Ensure any axes defined in the layout have an explicit axis number (default: 1)\n if (this.layout.x_axis !== {} && typeof this.layout.x_axis.axis !== 'number') { this.layout.x_axis.axis = 1; }\n if (this.layout.y_axis !== {} && typeof this.layout.y_axis.axis !== 'number') { this.layout.y_axis.axis = 1; }\n\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original data layer state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n\n /** @member {Object} */\n this.state = {};\n /** @member {String} */\n this.state_id = null;\n\n this.setDefaultState();\n\n // Initialize parameters for storing data and tool tips\n /** @member {Array} */\n this.data = [];\n if (this.layout.tooltip) {\n /** @member {Object} */\n this.tooltips = {};\n }\n\n // Initialize flags for tracking global statuses\n this.global_statuses = {\n 'highlighted': false,\n 'selected': false,\n 'faded': false,\n 'hidden': false\n };\n\n return this;\n\n};\n\n/**\n * Instruct this datalayer to begin tracking additional fields from data sources (does not guarantee that such a field actually exists)\n *\n * Custom plots can use this to dynamically extend datalayer functionality after the plot is drawn\n *\n * (since removing core fields may break layer functionality, there is presently no hook for the inverse behavior)\n * @param fieldName\n * @param namespace\n * @param {String|String[]} transformations The name (or array of names) of transformations to apply to this field\n * @returns {String} The raw string added to the fields array\n */\nLocusZoom.DataLayer.prototype.addField = function(fieldName, namespace, transformations) {\n if (!fieldName || !namespace) {\n throw new Error('Must specify field name and namespace to use when adding field');\n }\n var fieldString = namespace + ':' + fieldName;\n if (transformations) {\n fieldString += '|';\n if (typeof transformations === 'string') {\n fieldString += transformations;\n } else if (Array.isArray(transformations)) {\n fieldString += transformations.join('|');\n } else {\n throw new Error('Must provide transformations as either a string or array of strings');\n }\n }\n var fields = this.layout.fields;\n if (fields.indexOf(fieldString) === -1) {\n fields.push(fieldString);\n }\n return fieldString;\n};\n\n/**\n * Define default state that should get tracked during the lifetime of this layer.\n *\n * In some special custom usages, it may be useful to completely reset a panel (eg \"click for\n * genome region\" links), plotting new data that invalidates any previously tracked state. This hook makes it\n * possible to reset without destroying the panel entirely. It is used by `Plot.clearPanelData`.\n */\nLocusZoom.DataLayer.prototype.setDefaultState = function() {\n // Define state parameters specific to this data layer. Within plot state, this will live under a key\n // `panel_name.layer_name`.\n if (this.parent) {\n this.state = this.parent.state;\n this.state_id = this.parent.id + '.' + this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n var layer_state = this.state[this.state_id];\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function(status) {\n layer_state[status] = layer_state[status] || [];\n });\n // Also initialize \"internal-only\" state fields\n layer_state['has_tooltip'] = layer_state['has_tooltip'] || [];\n }\n};\n\n/**\n * A basic description of keys expected in a layout. Not intended to be directly used or modified by an end user.\n * @protected\n * @type {{type: string, fields: Array, x_axis: {}, y_axis: {}}}\n */\nLocusZoom.DataLayer.DefaultLayout = {\n type: '',\n fields: [],\n x_axis: {},\n y_axis: {}\n};\n\n/**\n * Available statuses that individual elements can have. Each status is described by\n * a verb/antiverb and an adjective. Verbs and antiverbs are used to generate data layer\n * methods for updating the status on one or more elements. Adjectives are used in class\n * names and applied or removed from elements to have a visual representation of the status,\n * as well as used as keys in the state for tracking which elements are in which status(es)\n * @static\n * @type {{verbs: String[], adjectives: String[], menu_antiverbs: String[]}}\n */\nLocusZoom.DataLayer.Statuses = {\n verbs: ['highlight', 'select', 'fade', 'hide'],\n adjectives: ['highlighted', 'selected', 'faded', 'hidden'],\n menu_antiverbs: ['unhighlight', 'deselect', 'unfade', 'show']\n};\n\n/**\n * Get the fully qualified identifier for the data layer, prefixed by any parent or container elements\n *\n * @returns {string} A dot-delimited string of the format ..\n */\nLocusZoom.DataLayer.prototype.getBaseId = function() {\n return this.parent_plot.id + '.' + this.parent.id + '.' + this.id;\n};\n\n/**\n * Determine the pixel height of data-bound objects represented inside this data layer. (excluding elements such as axes)\n *\n * May be used by operations that resize the data layer to fit available data\n *\n * @public\n * @returns {number}\n */\nLocusZoom.DataLayer.prototype.getAbsoluteDataHeight = function() {\n var dataBCR = this.svg.group.node().getBoundingClientRect();\n return dataBCR.height;\n};\n\n/**\n * Whether transitions can be applied to this data layer\n * @returns {boolean}\n */\nLocusZoom.DataLayer.prototype.canTransition = function() {\n if (!this.layout.transition) { return false; }\n return !(this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.panel_id);\n};\n\n/**\n * Fetch the fully qualified ID to be associated with a specific visual element, based on the data to which that\n * element is bound. In general this element ID will be unique, allowing it to be addressed directly via selectors.\n * @param {String|Object} element\n * @returns {String}\n */\nLocusZoom.DataLayer.prototype.getElementId = function(element) {\n var element_id = 'element';\n if (typeof element == 'string') {\n element_id = element;\n } else if (typeof element == 'object') {\n var id_field = this.layout.id_field || 'id';\n if (typeof element[id_field] == 'undefined') {\n throw new Error('Unable to generate element ID');\n }\n element_id = element[id_field].toString().replace(/\\W/g,'');\n }\n return (this.getBaseId() + '-' + element_id).replace(/([:.[\\],])/g, '_');\n};\n\n/**\n * Fetch an ID that may bind a data element to a separate visual node for displaying status\n * Examples of this might be seperate visual nodes to show select/highlight statuses, or\n * even a common/shared node to show status across many elements in a set.\n * Abstract method. It should be overridden by data layers that implement seperate status\n * nodes specifically to the use case of the data layer type.\n * @param {String|Object} element\n * @returns {String|null}\n */\nLocusZoom.DataLayer.prototype.getElementStatusNodeId = function(element) {\n return null;\n};\n\n/**\n * Returns a reference to the underlying data associated with a single visual element in the data layer, as\n * referenced by the unique identifier for the element\n\n * @param {String} id The unique identifier for the element, as defined by `getElementId`\n * @returns {Object|null} The data bound to that element\n */\nLocusZoom.DataLayer.prototype.getElementById = function(id) {\n var selector = d3.select('#' + id.replace(/([:.[\\],])/g, '\\\\$1')); // escape special characters\n if (!selector.empty() && selector.data() && selector.data().length) {\n return selector.data()[0];\n } else {\n return null;\n }\n};\n\n/**\n * Basic method to apply arbitrary methods and properties to data elements.\n * This is called on all data immediately after being fetched.\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.applyDataMethods = function() {\n var field_to_match = (this.layout.match && this.layout.match.receive);\n var broadcast_value = this.parent_plot.state.lz_match_value;\n\n this.data.forEach(function(d, i) {\n // Basic toHTML() method - return the stringified value in the id_field, if defined.\n\n // When this layer receives data, mark whether points match (via a synthetic boolean field)\n // Any field-based layout directives (color, size, shape) can then be used to control display\n if (field_to_match && broadcast_value !== null && broadcast_value !== undefined) {\n d.lz_highlight_match = (d[field_to_match] === broadcast_value);\n }\n\n this.data[i].toHTML = function() {\n var id_field = this.layout.id_field || 'id';\n var html = '';\n if (this.data[i][id_field]) { html = this.data[i][id_field].toString(); }\n return html;\n }.bind(this);\n // getDataLayer() method - return a reference to the data layer\n this.data[i].getDataLayer = function() {\n return this;\n }.bind(this);\n // deselect() method - shortcut method to deselect the element\n this.data[i].deselect = function() {\n var data_layer = this.getDataLayer();\n data_layer.unselectElement(this);\n };\n }.bind(this));\n this.applyCustomDataMethods();\n return this;\n};\n\n/**\n * Hook that allows custom datalayers to apply additional methods and properties to data elements as needed\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.applyCustomDataMethods = function() {\n return this;\n};\n\n/**\n * Initialize a data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.initialize = function() {\n\n // Append a container group element to house the main data layer group element and the clip path\n this.svg.container = this.parent.svg.group.append('g')\n .attr('class', 'lz-data_layer-container')\n .attr('id', this.getBaseId() + '.data_layer_container');\n\n // Append clip path to the container element\n this.svg.clipRect = this.svg.container.append('clipPath')\n .attr('id', this.getBaseId() + '.clip')\n .append('rect');\n\n // Append svg group for rendering all data layer elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g')\n .attr('id', this.getBaseId() + '.data_layer')\n .attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n\n return this;\n\n};\n\n/**\n * Move a data layer up relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.moveUp = function() {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n};\n\n/**\n * Move a data layer down relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.moveDown = function() {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n};\n\n/**\n * Apply scaling functions to an element or parameter as needed, based on its layout and the element's data\n * If the layout parameter is already a primitive type, simply return the value as given\n * @param {Array|Number|String|Object} layout\n * @param {*} data The value to be used with the filter\n * @returns {*} The transformed value\n */\nLocusZoom.DataLayer.prototype.resolveScalableParameter = function(layout, data) {\n var ret = null;\n if (Array.isArray(layout)) {\n var idx = 0;\n while (ret === null && idx < layout.length) {\n ret = this.resolveScalableParameter(layout[idx], data);\n idx++;\n }\n } else {\n switch (typeof layout) {\n case 'number':\n case 'string':\n ret = layout;\n break;\n case 'object':\n if (layout.scale_function) {\n if(layout.field) {\n var f = new LocusZoom.Data.Field(layout.field);\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, f.resolve(data));\n } else {\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, data);\n }\n }\n break;\n }\n }\n return ret;\n};\n\n\n/**\n * Implementation hook for fetching the min and max values of available data. Used to determine axis range, if no other\n * explicit axis settings override. Useful for data layers where the data extent depends on more than one field.\n * (eg confidence intervals in a forest plot)\n * @param data\n * @param axis_config The configuration object for the specified axis.\n * @returns {Array} [min, max] without any padding applied\n * @private\n */\nLocusZoom.DataLayer.prototype._getDataExtent = function(data, axis_config) {\n data = data || this.data;\n // By default this depends only on a single field.\n return d3.extent(data, function (d) {\n var f = new LocusZoom.Data.Field(axis_config.field);\n return +f.resolve(d);\n });\n};\n\n/**\n * Generate dimension extent function based on layout parameters\n * @param {('x'|'y')} dimension\n */\nLocusZoom.DataLayer.prototype.getAxisExtent = function(dimension) {\n\n if (['x', 'y'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier passed to LocusZoom.DataLayer.getAxisExtent()');\n }\n\n var axis_name = dimension + '_axis';\n var axis_layout = this.layout[axis_name];\n\n // If a floor AND a ceiling are explicitly defined then just return that extent and be done\n if (!isNaN(axis_layout.floor) && !isNaN(axis_layout.ceiling)) {\n return [+axis_layout.floor, +axis_layout.ceiling];\n }\n\n // If a field is defined for the axis and the data layer has data then generate the extent from the data set\n var data_extent = [];\n if (axis_layout.field && this.data) {\n if (!this.data.length) {\n // If data has been fetched (but no points in region), enforce the min_extent (with no buffers,\n // because we don't need padding around an empty screen)\n data_extent = axis_layout.min_extent || [];\n return data_extent;\n } else {\n data_extent = this._getDataExtent(this.data, axis_layout);\n\n // Apply upper/lower buffers, if applicable\n var original_extent_span = data_extent[1] - data_extent[0];\n if (!isNaN(axis_layout.lower_buffer)) {\n data_extent[0] -= original_extent_span * axis_layout.lower_buffer;\n }\n if (!isNaN(axis_layout.upper_buffer)) {\n data_extent[1] += original_extent_span * axis_layout.upper_buffer;\n }\n\n if (typeof axis_layout.min_extent == 'object') {\n // The data should span at least the range specified by min_extent, an array with [low, high]\n var range_min = axis_layout.min_extent[0];\n var range_max = axis_layout.min_extent[1];\n if (!isNaN(range_min) && !isNaN(range_max)) {\n data_extent[0] = Math.min(data_extent[0], range_min);\n }\n if (!isNaN(range_max)) {\n data_extent[1] = Math.max(data_extent[1], range_max);\n }\n }\n // If specified, floor and ceiling will override the actual data range\n return [\n isNaN(axis_layout.floor) ? data_extent[0] : axis_layout.floor,\n isNaN(axis_layout.ceiling) ? data_extent[1] : axis_layout.ceiling\n ];\n }\n }\n\n // If this is for the x axis and no extent could be generated yet but state has a defined start and end\n // then default to using the state-defined region as the extent\n if (dimension === 'x' && !isNaN(this.state.start) && !isNaN(this.state.end)) {\n return [this.state.start, this.state.end];\n }\n\n // No conditions met for generating a valid extent, return an empty array\n return [];\n\n};\n\n/**\n * Allow this data layer to tell the panel what axis ticks it thinks it will require. The panel may choose whether\n * to use some, all, or none of these when rendering, either alone or in conjunction with other data layers.\n *\n * This method is a stub and should be overridden in data layers that need to specify custom behavior.\n *\n * @param {('x'|'y1'|'y2')} dimension\n * @param {Object} [config] Additional parameters for the panel to specify how it wants ticks to be drawn. The names\n * and meanings of these parameters may vary between different data layers.\n * @returns {Object[]}\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\nLocusZoom.DataLayer.prototype.getTicks = function (dimension, config) {\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier at layer level' + dimension);\n }\n return [];\n};\n\n/**\n * Generate a tool tip for a given element\n * @param {String|Object} data Data for the element associated with the tooltip\n */\nLocusZoom.DataLayer.prototype.createTooltip = function(data) {\n if (typeof this.layout.tooltip != 'object') {\n throw new Error('DataLayer [' + this.id + '] layout does not define a tooltip');\n }\n var id = this.getElementId(data);\n if (this.tooltips[id]) {\n this.positionTooltip(id);\n return;\n }\n this.tooltips[id] = {\n data: data,\n arrow: null,\n selector: d3.select(this.parent_plot.svg.node().parentNode).append('div')\n .attr('class', 'lz-data_layer-tooltip')\n .attr('id', id + '-tooltip')\n };\n this.state[this.state_id]['has_tooltip'].push(id);\n this.updateTooltip(data);\n return this;\n};\n\n/**\n * Update a tool tip (generate its inner HTML)\n * @param {String|Object} d The element associated with the tooltip\n * @param {String} [id] An identifier to the tooltip\n */\nLocusZoom.DataLayer.prototype.updateTooltip = function(d, id) {\n if (typeof id == 'undefined') { id = this.getElementId(d); }\n // Empty the tooltip of all HTML (including its arrow!)\n this.tooltips[id].selector.html('');\n this.tooltips[id].arrow = null;\n // Set the new HTML\n if (this.layout.tooltip.html) {\n this.tooltips[id].selector.html(LocusZoom.parseFields(d, this.layout.tooltip.html));\n }\n // If the layout allows tool tips on this data layer to be closable then add the close button\n // and add padding to the tooltip to accommodate it\n if (this.layout.tooltip.closable) {\n this.tooltips[id].selector.insert('button', ':first-child')\n .attr('class', 'lz-tooltip-close-button')\n .attr('title', 'Close')\n .text('×')\n .on('click', function() {\n this.destroyTooltip(id);\n }.bind(this));\n }\n // Apply data directly to the tool tip for easier retrieval by custom UI elements inside the tool tip\n this.tooltips[id].selector.data([d]);\n // Reposition and draw a new arrow\n this.positionTooltip(id);\n return this;\n};\n\n/**\n * Destroy tool tip - remove the tool tip element from the DOM and delete the tool tip's record on the data layer\n * @param {String|Object} element_or_id The element (or id) associated with the tooltip\n * @param {boolean} [temporary=false] Whether this is temporary (not to be tracked in state). Differentiates\n * \"recreate tooltips on re-render\" (which is temporary) from \"user has closed this tooltip\" (permanent)\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.destroyTooltip = function(element_or_id, temporary) {\n var id;\n if (typeof element_or_id == 'string') {\n id = element_or_id;\n } else {\n id = this.getElementId(element_or_id);\n }\n if (this.tooltips[id]) {\n if (typeof this.tooltips[id].selector == 'object') {\n this.tooltips[id].selector.remove();\n }\n delete this.tooltips[id];\n }\n // When a tooltip is removed, also remove the reference from the state\n if (!temporary) {\n var state = this.state[this.state_id]['has_tooltip'];\n var label_mark_position = state.indexOf(id);\n state.splice(label_mark_position, 1);\n }\n return this;\n};\n\n/**\n * Loop through and destroy all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.destroyAllTooltips = function() {\n for (var id in this.tooltips) {\n this.destroyTooltip(id, true);\n }\n return this;\n};\n\n//\n/**\n * Position tool tip - naïve function to place a tool tip to the lower right of the current mouse element\n * Most data layers reimplement this method to position tool tips specifically for the data they display\n * @param {String} id The identifier of the tooltip to position\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n // Position the div itself\n this.tooltips[id].selector\n .style('left', (d3.event.pageX) + 'px')\n .style('top', (d3.event.pageY) + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!this.tooltips[id].arrow) {\n this.tooltips[id].arrow = this.tooltips[id].selector.append('div')\n .style('position', 'absolute')\n .attr('class', 'lz-data_layer-tooltip-arrow_top_left');\n }\n this.tooltips[id].arrow\n .style('left', '-1px')\n .style('top', '-1px');\n return this;\n};\n\n/**\n * Loop through and position all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.positionAllTooltips = function() {\n for (var id in this.tooltips) {\n this.positionTooltip(id);\n }\n return this;\n};\n\n/**\n * Show or hide a tool tip by ID depending on directives in the layout and state values relative to the ID\n * @param {String|Object} element The element associated with the tooltip\n * @param {boolean} first_time Because panels can re-render, the rules for showing a tooltip\n * depend on whether this is the first time a status change affecting display has been applied.\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.showOrHideTooltip = function(element, first_time) {\n if (typeof this.layout.tooltip != 'object') { return; }\n var id = this.getElementId(element);\n\n /**\n * Apply rules and decide whether to show or hide the tooltip\n * @param {Object} statuses All statuses that apply to an element\n * @param {String[]|object} directive A layout directive object\n * @param operator\n * @returns {null|bool}\n */\n var resolveStatus = function(statuses, directive, operator) {\n var status = null;\n if (typeof statuses != 'object' || statuses === null) { return null; }\n if (Array.isArray(directive)) {\n // This happens when the function is called on the inner part of the directive\n operator = operator || 'and';\n if (directive.length === 1) {\n status = statuses[directive[0]];\n } else {\n status = directive.reduce(function(previousValue, currentValue) {\n if (operator === 'and') {\n return statuses[previousValue] && statuses[currentValue];\n } else if (operator === 'or') {\n return statuses[previousValue] || statuses[currentValue];\n }\n return null;\n });\n }\n } else if (typeof directive == 'object') {\n var sub_status;\n for (var sub_operator in directive) {\n sub_status = resolveStatus(statuses, directive[sub_operator], sub_operator);\n if (status === null) {\n status = sub_status;\n } else if (operator === 'and') {\n status = status && sub_status;\n } else if (operator === 'or') {\n status = status || sub_status;\n }\n }\n } else {\n return false;\n }\n return status;\n };\n\n var show_directive = {};\n if (typeof this.layout.tooltip.show == 'string') {\n show_directive = { and: [ this.layout.tooltip.show ] };\n } else if (typeof this.layout.tooltip.show == 'object') {\n show_directive = this.layout.tooltip.show;\n }\n\n var hide_directive = {};\n if (typeof this.layout.tooltip.hide == 'string') {\n hide_directive = { and: [ this.layout.tooltip.hide ] };\n } else if (typeof this.layout.tooltip.hide == 'object') {\n hide_directive = this.layout.tooltip.hide;\n }\n\n // Find all the statuses that apply to just this single element\n var layer_state = this.state[this.state_id];\n var statuses = {}; // {status_name: bool}\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function(status) {\n var antistatus = 'un' + status;\n statuses[status] = (layer_state[status].indexOf(id) !== -1);\n statuses[antistatus] = !statuses[status];\n });\n\n // Decide whether to show/hide the tooltip based solely on the underlying element\n var show_resolved = resolveStatus(statuses, show_directive);\n var hide_resolved = resolveStatus(statuses, hide_directive);\n\n // Most of the tooltip display logic depends on behavior layouts: was point (un)selected, (un)highlighted, etc.\n // But sometimes, a point is selected, and the user then closes the tooltip. If the panel is re-rendered for\n // some outside reason (like state change), we must track this in the create/destroy events as tooltip state.\n var has_tooltip = (layer_state['has_tooltip'].indexOf(id) !== -1);\n var tooltip_was_closed = first_time ? false : !has_tooltip;\n if (show_resolved && !tooltip_was_closed && !hide_resolved) {\n this.createTooltip(element);\n } else {\n this.destroyTooltip(element);\n }\n\n return this;\n};\n\n/**\n * Find the elements (or indices) that match any of a set of provided filters\n * @protected\n * @param {Array[]} filters A list of filter entries: [field, value] (for equivalence testing) or\n * [field, operator, value] for other operators\n * @param {('indexes'|'elements')} [return_type='indexes'] Specify whether to return either the indices of the matching\n * elements, or references to the elements themselves\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filter = function(filters, return_type) {\n if (typeof return_type == 'undefined' || ['indexes','elements'].indexOf(return_type) === -1) {\n return_type = 'indexes';\n }\n if (!Array.isArray(filters)) { return []; }\n var test = function(element, filter) {\n var operators = {\n '=': function(a,b) { return a === b; },\n // eslint-disable-next-line eqeqeq\n '!=': function(a,b) { return a != b; }, // For absence of a value, deliberately allow weak comparisons (eg undefined/null)\n '<': function(a,b) { return a < b; },\n '<=': function(a,b) { return a <= b; },\n '>': function(a,b) { return a > b; },\n '>=': function(a,b) { return a >= b; },\n '%': function(a,b) { return a % b; }\n };\n if (!Array.isArray(filter)) { return false; }\n if (filter.length === 2) {\n return element[filter[0]] === filter[1];\n } else if (filter.length === 3 && operators[filter[1]]) {\n return operators[filter[1]](element[filter[0]], filter[2]);\n } else {\n return false;\n }\n };\n var matches = [];\n this.data.forEach(function(element, idx) {\n var match = true;\n filters.forEach(function(filter) {\n if (!test(element, filter)) { match = false; }\n });\n if (match) { matches.push(return_type === 'indexes' ? idx : element); }\n });\n return matches;\n};\n\n/**\n * @param filters\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filterIndexes = function(filters) { return this.filter(filters, 'indexes'); };\n/**\n * @param filters\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filterElements = function(filters) { return this.filter(filters, 'elements'); };\n\nLocusZoom.DataLayer.Statuses.verbs.forEach(function(verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset a single element's status\n // TODO: Improve documentation for dynamically generated methods/properties\n LocusZoom.DataLayer.prototype[verb + 'Element'] = function(element, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n this.setElementStatus(adjective, element, true, exclusive);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'Element'] = function(element, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n this.setElementStatus(adjective, element, false, exclusive);\n return this;\n };\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.DataLayer.prototype[verb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.DataLayer.prototype[antiverb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.DataLayer.prototype[verb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n});\n\n/**\n * Toggle a status (e.g. highlighted, selected, identified) on an element\n * @param {String} status The name of a recognized status to be added/removed on an appropriate element\n * @param {String|Object} element The data bound to the element of interest\n * @param {Boolean} active True to add the status (and associated CSS styles); false to remove it\n * @param {Boolean} exclusive Whether to only allow a state for a single element at a time\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setElementStatus = function(status, element, active, exclusive) {\n if (status === 'has_tooltip') {\n // This is a special adjective that exists solely to track tooltip state. It has no CSS and never gets set\n // directly. It is invisible to the official enums.\n return this;\n }\n\n // Sanity checks\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatus()');\n }\n if (typeof element == 'undefined') {\n throw new Error('Invalid element passed to DataLayer.setElementStatus()');\n }\n if (typeof active == 'undefined') {\n active = true;\n }\n\n // Get an ID for the element or return having changed nothing\n try {\n var element_id = this.getElementId(element);\n } catch (get_element_id_error) {\n return this;\n }\n\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !active);\n }\n\n // Set/unset the proper status class on the appropriate DOM element(s)\n d3.select('#' + element_id).classed('lz-data_layer-' + this.layout.type + '-' + status, active);\n var element_status_node_id = this.getElementStatusNodeId(element);\n if (element_status_node_id !== null) {\n d3.select('#' + element_status_node_id).classed('lz-data_layer-' + this.layout.type + '-statusnode-' + status, active);\n }\n\n // Track element ID in the proper status state array\n var element_status_idx = this.state[this.state_id][status].indexOf(element_id);\n var added_status = (element_status_idx === -1); // On a re-render, existing statuses will be reapplied.\n if (active && added_status) {\n this.state[this.state_id][status].push(element_id);\n }\n if (!active && !added_status) {\n this.state[this.state_id][status].splice(element_status_idx, 1);\n }\n\n // Trigger tool tip show/hide logic\n this.showOrHideTooltip(element, added_status);\n\n // Trigger layout changed event hook\n if (added_status) {\n this.parent.emit('layout_changed', true);\n }\n\n var is_selected = (status === 'selected');\n if (is_selected && (added_status || !active)) {\n // Notify parents that an element has changed selection status (either active, or inactive)\n this.parent.emit('element_selection', { element: element, active: active }, true);\n }\n\n var value_to_broadcast = (this.layout.match && this.layout.match.send);\n if (is_selected && value_to_broadcast && (added_status || !active)) {\n this.parent.emit(\n 'match_requested',\n { value: element[value_to_broadcast], active: active },\n true\n );\n }\n return this;\n};\n\n/**\n * Toggle a status on elements in the data layer based on a set of filters\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setElementStatusByFilters = function(status, toggle, filters, exclusive) {\n\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatusByFilters()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; } else { toggle = !!toggle; }\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n if (!Array.isArray(filters)) { filters = []; }\n\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !toggle);\n }\n\n // Apply statuses\n this.filterElements(filters).forEach(function(element) {\n this.setElementStatus(status, element, toggle);\n }.bind(this));\n\n return this;\n};\n\n/**\n * Toggle a status on all elements in the data layer\n * @param {String} status\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setAllElementStatus = function(status, toggle) {\n\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; }\n\n // Apply statuses\n if (toggle) {\n this.data.forEach(function(element) {\n this.setElementStatus(status, element, true);\n }.bind(this));\n } else {\n var status_ids = this.state[this.state_id][status].slice();\n status_ids.forEach(function(id) {\n var element = this.getElementById(id);\n if (typeof element == 'object' && element !== null) {\n this.setElementStatus(status, element, false);\n }\n }.bind(this));\n this.state[this.state_id][status] = [];\n }\n\n // Update global status flag\n this.global_statuses[status] = toggle;\n\n return this;\n};\n\n/**\n * Apply all layout-defined behaviors (DOM event handlers) to a selection of elements\n * @param {d3.selection} selection\n */\nLocusZoom.DataLayer.prototype.applyBehaviors = function(selection) {\n if (typeof this.layout.behaviors != 'object') { return; }\n Object.keys(this.layout.behaviors).forEach(function(directive) {\n var event_match = /(click|mouseover|mouseout)/.exec(directive);\n if (!event_match) { return; }\n selection.on(event_match[0] + '.' + directive, this.executeBehaviors(directive, this.layout.behaviors[directive]));\n }.bind(this));\n};\n\n/**\n * Generate a function that executes an arbitrary list of behaviors on an element during an event\n * @param {String} directive The name of the event, as described in layout.behaviors for this datalayer\n * @param {Object} behaviors An object describing the behavior to attach to this single element\n * @param {string} behaviors.action The name of the action that would trigger this behavior (eg click, mouseover, etc)\n * @param {string} behaviors.status What status to apply to the element when this behavior is triggered (highlighted,\n * selected, etc)\n * @param {string} [behaviors.exclusive] Whether triggering the event for this element should unset the relevant status\n * for all other elements. Useful for, eg, click events that exclusively highlight one thing.\n * @returns {function(this:LocusZoom.DataLayer)} Return a function that handles the event in context with the behavior\n * and the element- can be attached as an event listener\n */\nLocusZoom.DataLayer.prototype.executeBehaviors = function(directive, behaviors) {\n\n // Determine the required state of control and shift keys during the event\n var requiredKeyStates = {\n 'ctrl': (directive.indexOf('ctrl') !== -1),\n 'shift': (directive.indexOf('shift') !== -1)\n };\n\n return function(element) {\n\n // Do nothing if the required control and shift key presses (or lack thereof) doesn't match the event\n if (requiredKeyStates.ctrl !== !!d3.event.ctrlKey || requiredKeyStates.shift !== !!d3.event.shiftKey) { return; }\n\n // Loop through behaviors making each one go in succession\n behaviors.forEach(function(behavior) {\n\n // Route first by the action, if defined\n if (typeof behavior != 'object' || behavior === null) { return; }\n\n switch (behavior.action) {\n\n // Set a status (set to true regardless of current status, optionally with exclusivity)\n case 'set':\n this.setElementStatus(behavior.status, element, true, behavior.exclusive);\n break;\n\n // Unset a status (set to false regardless of current status, optionally with exclusivity)\n case 'unset':\n this.setElementStatus(behavior.status, element, false, behavior.exclusive);\n break;\n\n // Toggle a status\n case 'toggle':\n var current_status_boolean = (this.state[this.state_id][behavior.status].indexOf(this.getElementId(element)) !== -1);\n var exclusive = behavior.exclusive && !current_status_boolean;\n this.setElementStatus(behavior.status, element, !current_status_boolean, exclusive);\n break;\n\n // Link to a dynamic URL\n case 'link':\n if (typeof behavior.href == 'string') {\n var url = LocusZoom.parseFields(element, behavior.href);\n if (typeof behavior.target == 'string') {\n window.open(url, behavior.target);\n } else {\n window.location.href = url;\n }\n }\n break;\n\n // Action not defined, just return\n default:\n break;\n\n }\n\n return;\n\n }.bind(this));\n\n }.bind(this);\n\n};\n\n/**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\nLocusZoom.DataLayer.prototype.getPageOrigin = function() {\n var panel_origin = this.parent.getPageOrigin();\n return {\n x: panel_origin.x + this.parent.layout.margin.left,\n y: panel_origin.y + this.parent.layout.margin.top\n };\n};\n\n/**\n * Get a data layer's current underlying data in a standard format (e.g. JSON or CSV)\n * @param {('csv'|'tsv'|'json')} format How to export the data\n * @returns {*}\n */\nLocusZoom.DataLayer.prototype.exportData = function(format) {\n var default_format = 'json';\n format = format || default_format;\n format = (typeof format == 'string' ? format.toLowerCase() : default_format);\n if (['json','csv','tsv'].indexOf(format) === -1) { format = default_format; }\n var ret;\n switch (format) {\n case 'json':\n try {\n ret = JSON.stringify(this.data);\n } catch (e) {\n ret = null;\n console.warn('Unable to export JSON data from data layer: ' + this.getBaseId());\n console.error(e);\n }\n break;\n case 'tsv':\n case 'csv':\n try {\n var jsonified = JSON.parse(JSON.stringify(this.data));\n if (typeof jsonified != 'object') {\n ret = jsonified.toString();\n } else if (!Array.isArray(jsonified)) {\n ret = 'Object';\n } else {\n var delimiter = (format === 'tsv') ? '\\t' : ',';\n var header = this.layout.fields.map(function(header) {\n return JSON.stringify(header);\n }).join(delimiter) + '\\n';\n ret = header + jsonified.map(function(record) {\n return this.layout.fields.map(function(field) {\n if (typeof record[field] == 'undefined') {\n return JSON.stringify(null);\n } else if (typeof record[field] == 'object' && record[field] !== null) {\n return Array.isArray(record[field]) ? '\"[Array(' + record[field].length + ')]\"' : '\"[Object]\"';\n } else {\n return JSON.stringify(record[field]);\n }\n }).join(delimiter);\n }.bind(this)).join('\\n');\n }\n } catch (e) {\n ret = null;\n console.error('Unable to export CSV data from data layer: ' + this.getBaseId() + ';', e);\n }\n break;\n }\n return ret;\n};\n\n/**\n * Position the datalayer and all tooltips\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.draw = function() {\n this.svg.container.attr('transform', 'translate(' + this.parent.layout.cliparea.origin.x + ',' + this.parent.layout.cliparea.origin.y + ')');\n this.svg.clipRect\n .attr('width', this.parent.layout.cliparea.width)\n .attr('height', this.parent.layout.cliparea.height);\n this.positionAllTooltips();\n return this;\n};\n\n\n/**\n * Re-Map a data layer to reflect changes in the state of a plot (such as viewing region/ chromosome range)\n * @return {Promise}\n */\nLocusZoom.DataLayer.prototype.reMap = function() {\n this.destroyAllTooltips(); // hack - only non-visible tooltips should be destroyed\n // and then recreated if returning to visibility\n\n // Fetch new data. Datalayers are only given access to the final consolidated data from the chain (not headers or raw payloads)\n var promise = this.parent_plot.lzd.getData(this.state, this.layout.fields);\n promise.then(function(new_data) {\n this.data = new_data.body;\n this.applyDataMethods();\n this.initialized = true;\n }.bind(this));\n\n return promise;\n};\n\n\n/**\n * The central registry of known data layer definitions (which may be stored in separate files due to length)\n * @namespace\n */\nLocusZoom.DataLayers = (function() {\n var obj = {};\n var datalayers = {};\n /**\n * @name LocusZoom.DataLayers.get\n * @param {String} name The name of the datalayer\n * @param {Object} layout The configuration object for this data layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n * @returns {LocusZoom.DataLayer}\n */\n obj.get = function(name, layout, parent) {\n if (!name) {\n return null;\n } else if (datalayers[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for data layer [' + name + ']');\n } else {\n return new datalayers[name](layout, parent);\n }\n } else {\n throw new Error('data layer [' + name + '] not found');\n }\n };\n\n /**\n * @name LocusZoom.DataLayers.set\n * @protected\n * @param {String} name\n * @param {Function} datalayer Constructor for the datalayer\n */\n obj.set = function(name, datalayer) {\n if (datalayer) {\n if (typeof datalayer != 'function') {\n throw new Error('unable to set data layer [' + name + '], argument provided is not a function');\n } else {\n datalayers[name] = datalayer;\n datalayers[name].prototype = new LocusZoom.DataLayer();\n }\n } else {\n delete datalayers[name];\n }\n };\n\n /**\n * Add a new type of datalayer to the registry of known layer types\n * @name LocusZoom.DataLayers.add\n * @param {String} name The name of the data layer to register\n * @param {Function} datalayer\n */\n obj.add = function(name, datalayer) {\n if (datalayers[name]) {\n throw new Error('data layer already exists with name: ' + name);\n } else {\n obj.set(name, datalayer);\n }\n };\n\n /**\n * Register a new datalayer that inherits and extends basic behaviors from a known datalayer\n * @param {String} parent_name The name of the parent data layer whose behavior is to be extended\n * @param {String} name The name of the new datalayer to register\n * @param {Object} [overrides] Object of properties and methods to combine with the prototype of the parent datalayer\n * @returns {Function} The constructor for the new child class\n */\n obj.extend = function(parent_name, name, overrides) {\n // TODO: Consider exposing additional constructor argument, if there is a use case for very granular extension\n overrides = overrides || {};\n\n var parent = datalayers[parent_name];\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered datalayer type');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n // Bypass .set() because we want a layer of inheritance below `DataLayer`\n datalayers[name] = child;\n return child;\n };\n\n /**\n * List the names of all known datalayers\n * @name LocusZoom.DataLayers.list\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(datalayers);\n };\n\n return obj;\n})();\n","'use strict';\n\n/**\n * Create a single continuous 2D track that provides information about each datapoint\n *\n * For example, this can be used to color by membership in a group, alongside information in other panels\n *\n * @class LocusZoom.DataLayers.annotation_track\n * @augments LocusZoom.DataLayer\n * @param {Object} layout\n * @param {Object|String} [layout.color]\n * @param {Array[]} An array of filter entries specifying which points to draw annotations for.\n * See `LocusZoom.DataLayer.filter` for details\n */\nLocusZoom.DataLayers.add('annotation_track', function(layout) {\n // In the future we may add additional options for controlling marker size/ shape, based on user feedback\n this.DefaultLayout = {\n color: '#000000',\n filters: [],\n tooltip_positioning: 'middle', // Allowed values: top, middle, bottom\n hit_area_width: 8,\n };\n\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n if (!Array.isArray(layout.filters)) {\n throw new Error('Annotation track must specify array of filters for selecting points to annotate');\n }\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n this.render = function() {\n var self = this;\n // Only render points that currently satisfy all provided filter conditions.\n var trackData = this.filter(this.layout.filters, 'elements');\n\n // Put the containing visible lines before the one containing hit areas, so that the hit areas will be on top.\n var visible_lines_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-visible_lines');\n if (visible_lines_group.size() === 0) {\n visible_lines_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-visible_lines');\n }\n var selection = visible_lines_group.selectAll('rect.lz-data_layer-' + self.layout.type)\n .data(trackData, function (d) { return d[self.layout.id_field]; });\n\n // Draw rectangles (visual and tooltip positioning)\n selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function (d) { return self.getElementId(d); });\n\n var width = 1;\n selection\n .attr('x', function (d) {return self.parent['x_scale'](d[self.layout.x_axis.field]) - width / 2; })\n .attr('width', width)\n .attr('height', self.parent.layout.height)\n .attr('fill', function(d) { return self.resolveScalableParameter(self.layout.color, d); });\n\n // Remove unused elements\n selection.exit()\n .remove();\n\n var hit_areas_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-hit_areas');\n if (hit_areas_group.size() === 0) {\n hit_areas_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-hit_areas');\n }\n var hit_areas_selection = hit_areas_group.selectAll('rect.lz-data_layer-' + self.layout.type)\n .data(trackData, function (d) { return d[self.layout.id_field]; });\n\n // Add new elements as needed\n hit_areas_selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function (d) { return self.getElementId(d); });\n\n // Update the set of elements to reflect new data\n\n var _getX = function (d, i) { // Helper for position calcs below\n var x_center = self.parent['x_scale'](d[self.layout.x_axis.field]);\n var x_left = x_center - self.layout.hit_area_width / 2;\n if (i >= 1) {\n // This assumes that the data are in sorted order.\n var left_node = trackData[i - 1];\n var left_node_x_center = self.parent['x_scale'](left_node[self.layout.x_axis.field]);\n x_left = Math.max(x_left, (x_center + left_node_x_center) / 2);\n }\n return [x_left, x_center];\n };\n hit_areas_selection\n .attr('height', self.parent.layout.height)\n .attr('opacity', 0)\n .attr('x', function (d, i) {\n var crds = _getX(d,i);\n return crds[0];\n }).attr('width', function (d, i) {\n var crds = _getX(d,i);\n return (crds[1] - crds[0]) + self.layout.hit_area_width / 2;\n });\n\n // Remove unused elements\n hit_areas_selection.exit().remove();\n\n // Set up tooltips and mouse interaction\n this.applyBehaviors(hit_areas_selection);\n };\n\n // Reimplement the positionTooltip() method to be annotation-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var offset = stroke_width / 2;\n var page_origin = this.getPageOrigin();\n\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_center = data_layer_height / 2;\n\n // Tooltip should be horizontally centered above the point to be annotated. (or below if space is limited)\n var offset_right = Math.max((tooltip_box.width / 2) - x_center, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - (tooltip_box.width / 2) - offset_left + offset_right;\n arrow_left = (tooltip_box.width / 2) - (arrow_width) + offset_left - offset_right - offset;\n\n var top_offset = 0;\n switch(this.layout.tooltip_positioning) {\n case 'top':\n arrow_type = 'down';\n break;\n case 'bottom':\n top_offset = data_layer_height;\n arrow_type = 'up';\n break;\n case 'middle':\n default:\n var position = d3.mouse(this.svg.container.node());\n // Position the tooltip so that it does not overlap the mouse pointer\n top_offset = y_center;\n if (position[1] > (data_layer_height / 2)) {\n arrow_type = 'down';\n } else {\n arrow_type = 'up';\n }\n }\n\n if (arrow_type === 'up') {\n top = page_origin.y + top_offset + stroke_width + arrow_width;\n arrow_top = 0 - stroke_width - arrow_width;\n } else if (arrow_type === 'down') {\n top = page_origin.y + top_offset - (tooltip_box.height + stroke_width + arrow_width);\n arrow_top = tooltip_box.height - stroke_width;\n }\n\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n return this;\n});\n","'use strict';\n\n/**\n * Forest Data Layer\n * Implements a standard forest plot. In order to space out points, any layout using this must specify axis ticks\n * and extent in advance.\n *\n * If you are using dynamically fetched data, consider using `category_forest` instead.\n *\n * @class LocusZoom.DataLayers.forest\n */\nLocusZoom.DataLayers.add('forest', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'square',\n color: '#888888',\n fill_opacity: 1,\n y_axis: {\n axis: 2\n },\n id_field: 'id',\n confidence_intervals: {\n start_field: 'ci_start',\n end_field: 'ci_end'\n },\n show_no_significance_line: true\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Reimplement the positionTooltip() method to be forest-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n var offset = Math.sqrt(point_size / Math.PI);\n var left, arrow_type, arrow_left;\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var top, arrow_top;\n if (y_center - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + y_center - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (y_center + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + y_center - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Implement the main render function\n this.render = function() {\n\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n // Generate confidence interval paths if fields are defined\n if (this.layout.confidence_intervals\n && this.layout.fields.indexOf(this.layout.confidence_intervals.start_field) !== -1\n && this.layout.fields.indexOf(this.layout.confidence_intervals.end_field) !== -1) {\n // Generate a selection for all forest plot confidence intervals\n var ci_selection = this.svg.group\n .selectAll('rect.lz-data_layer-forest.lz-data_layer-forest-ci')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n // Create confidence interval rect elements\n ci_selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-forest lz-data_layer-forest-ci')\n .attr('id', function(d) { return this.getElementId(d) + '_ci'; }.bind(this))\n .attr('transform', 'translate(0,' + (isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height) + ')');\n // Apply position and size parameters using transition if necessary\n var ci_transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var ci_width = function(d) {\n return this.parent[x_scale](d[this.layout.confidence_intervals.end_field])\n - this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n }.bind(this);\n var ci_height = 1;\n if (this.canTransition()) {\n ci_selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', ci_transform)\n .attr('width', ci_width).attr('height', ci_height);\n } else {\n ci_selection\n .attr('transform', ci_transform)\n .attr('width', ci_width).attr('height', ci_height);\n }\n // Remove old elements as needed\n ci_selection.exit().remove();\n }\n\n // Generate a selection for all forest plot points\n var points_selection = this.svg.group\n .selectAll('path.lz-data_layer-forest.lz-data_layer-forest-point')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n points_selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-forest lz-data_layer-forest-point')\n .attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .attr('transform', 'translate(0,' + initial_y + ')');\n\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n\n var fill = function(d) { return this.resolveScalableParameter(this.layout.color, d); }.bind(this);\n var fill_opacity = function(d) { return this.resolveScalableParameter(this.layout.fill_opacity, d); }.bind(this);\n\n var shape = d3.svg.symbol()\n .size(function(d) { return this.resolveScalableParameter(this.layout.point_size, d); }.bind(this))\n .type(function(d) { return this.resolveScalableParameter(this.layout.point_shape, d); }.bind(this));\n\n // Apply position and color, using a transition if necessary\n if (this.canTransition()) {\n points_selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n } else {\n points_selection\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n }\n\n // Remove old elements as needed\n points_selection.exit().remove();\n\n // Apply default event emitters to selection\n points_selection.on('click.event_emitter', function(element_data) {\n this.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n\n // Apply behaviors to points\n this.applyBehaviors(points_selection);\n };\n return this;\n\n});\n\n/**\n * A y-aligned forest plot in which the y-axis represents item labels, which are dynamically chosen when data is loaded.\n * Each item is assumed to include both data and confidence intervals.\n * This allows generating forest plots without defining the layout in advance.\n *\n * @class LocusZoom.DataLayers.category_forest\n * @augments LocusZoom.DataLayers.forest\n */\nLocusZoom.DataLayers.extend('forest', 'category_forest', {\n _getDataExtent: function(data, axis_config) {\n // In a forest plot, the data range is determined by *three* fields (beta + CI start/end)\n var ci_config = this.layout.confidence_intervals;\n if (ci_config\n && this.layout.fields.indexOf(ci_config.start_field) !== -1\n && this.layout.fields.indexOf(ci_config.end_field) !== -1) {\n var min = function(d) {\n var f = new LocusZoom.Data.Field(ci_config.start_field);\n return +f.resolve(d);\n };\n\n var max = function(d) {\n var f = new LocusZoom.Data.Field(ci_config.end_field);\n return +f.resolve(d);\n };\n\n return [d3.min(data, min), d3.max(data, max)];\n }\n\n // If there are no confidence intervals set, then range must depend only on a single field\n return LocusZoom.DataLayer.prototype._getDataExtent.call(this, data, axis_config);\n },\n\n getTicks: function(dimension, config) { // Overrides parent method\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier' + dimension);\n }\n\n // Design assumption: one axis (y1 or y2) has the ticks, and the layout says which to use\n // Also assumes that every tick gets assigned a unique matching label\n var axis_num = this.layout.y_axis.axis;\n if (dimension === ('y' + axis_num)) {\n var category_field = this.layout.y_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n\n return this.data.map(function (item, index) {\n return {\n y: index + 1,\n text: item[category_field]\n };\n });\n } else {\n return [];\n }\n },\n\n applyCustomDataMethods: function () {\n // Add a synthetic yaxis field to ensure data is spread out on plot. Then, set axis floor and ceiling to\n // correct extents.\n var field_to_add = this.layout.y_axis.field;\n if (!field_to_add) {\n throw new Error('Layout for ' + this.layout.id + ' must specify yaxis.field');\n }\n\n this.data = this.data.map(function (item, index) {\n item[field_to_add] = index + 1;\n return item;\n });\n // Update axis extents based on one label for every point (with a bit of padding above and below)\n this.layout.y_axis.floor = 0;\n this.layout.y_axis.ceiling = this.data.length + 1;\n return this;\n }\n});\n","'use strict';\n\n/*********************\n * Genes Data Layer\n * Implements a data layer that will render gene tracks\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('genes', function(layout) {\n /**\n * Define a default layout for this DataLayer type and merge it with the passed argument\n * @protected\n * @member {Object}\n * */\n this.DefaultLayout = {\n // Optionally specify different fill and stroke properties\n stroke: 'rgb(54, 54, 150)',\n color: '#363696',\n label_font_size: 12,\n label_exon_spacing: 4,\n exon_height: 16,\n bounding_box_padding: 6,\n track_vertical_spacing: 10\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * Generate a statusnode ID for a given element\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function(element) {\n return this.getElementId(element) + '-statusnode';\n };\n\n /**\n * Helper function to sum layout values to derive total height for a single gene track\n * @returns {number}\n */\n this.getTrackHeight = function() {\n return 2 * this.layout.bounding_box_padding\n + this.layout.label_font_size\n + this.layout.label_exon_spacing\n + this.layout.exon_height\n + this.layout.track_vertical_spacing;\n };\n\n /**\n * A gene may have arbitrarily many transcripts, but this data layer isn't set up to render them yet.\n * Stash a transcript_idx to point to the first transcript and use that for all transcript refs.\n * @member {number}\n * @type {number}\n */\n this.transcript_idx = 0;\n\n /**\n * An internal counter for the number of tracks in the data layer. Used as an internal counter for looping\n * over positions / assignments\n * @protected\n * @member {number}\n */\n this.tracks = 1;\n\n /**\n * Store information about genes in dataset, in a hash indexed by track number: {track_number: [gene_indices]}\n * @member {Object.}\n */\n this.gene_track_index = { 1: [] };\n\n /**\n * Ensure that genes in overlapping chromosome regions are positioned so that parts of different genes do not\n * overlap in the view. A track is a row used to vertically separate overlapping genes.\n * @returns {LocusZoom.DataLayer}\n */\n this.assignTracks = function() {\n /**\n * Function to get the width in pixels of a label given the text and layout attributes\n * TODO: Move to outer scope?\n * @param {String} gene_name\n * @param {number|string} font_size\n * @returns {number}\n */\n this.getLabelWidth = function(gene_name, font_size) {\n try {\n var temp_text = this.svg.group.append('text')\n .attr('x', 0).attr('y', 0).attr('class', 'lz-data_layer-genes lz-label')\n .style('font-size', font_size)\n .text(gene_name + '→');\n var label_width = temp_text.node().getBBox().width;\n temp_text.remove();\n return label_width;\n } catch (e) {\n return 0;\n }\n };\n\n // Reinitialize some metadata\n this.tracks = 1;\n this.gene_track_index = { 1: [] };\n\n this.data.map(function(d, g) {\n\n // If necessary, split combined gene id / version fields into discrete fields.\n // NOTE: this may be an issue with CSG's genes data source that may eventually be solved upstream.\n if (this.data[g].gene_id && this.data[g].gene_id.indexOf('.')) {\n var split = this.data[g].gene_id.split('.');\n this.data[g].gene_id = split[0];\n this.data[g].gene_version = split[1];\n }\n\n // Stash the transcript ID on the parent gene\n this.data[g].transcript_id = this.data[g].transcripts[this.transcript_idx].transcript_id;\n\n // Determine display range start and end, based on minimum allowable gene display width, bounded by what we can see\n // (range: values in terms of pixels on the screen)\n this.data[g].display_range = {\n start: this.parent.x_scale(Math.max(d.start, this.state.start)),\n end: this.parent.x_scale(Math.min(d.end, this.state.end))\n };\n this.data[g].display_range.label_width = this.getLabelWidth(this.data[g].gene_name, this.layout.label_font_size);\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n // Determine label text anchor (default to middle)\n this.data[g].display_range.text_anchor = 'middle';\n if (this.data[g].display_range.width < this.data[g].display_range.label_width) {\n if (d.start < this.state.start) {\n this.data[g].display_range.end = this.data[g].display_range.start\n + this.data[g].display_range.label_width\n + this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'start';\n } else if (d.end > this.state.end) {\n this.data[g].display_range.start = this.data[g].display_range.end\n - this.data[g].display_range.label_width\n - this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n var centered_margin = ((this.data[g].display_range.label_width - this.data[g].display_range.width) / 2)\n + this.layout.label_font_size;\n if ((this.data[g].display_range.start - centered_margin) < this.parent.x_scale(this.state.start)) {\n this.data[g].display_range.start = this.parent.x_scale(this.state.start);\n this.data[g].display_range.end = this.data[g].display_range.start + this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'start';\n } else if ((this.data[g].display_range.end + centered_margin) > this.parent.x_scale(this.state.end)) {\n this.data[g].display_range.end = this.parent.x_scale(this.state.end);\n this.data[g].display_range.start = this.data[g].display_range.end - this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n this.data[g].display_range.start -= centered_margin;\n this.data[g].display_range.end += centered_margin;\n }\n }\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n }\n // Add bounding box padding to the calculated display range start, end, and width\n this.data[g].display_range.start -= this.layout.bounding_box_padding;\n this.data[g].display_range.end += this.layout.bounding_box_padding;\n this.data[g].display_range.width += 2 * this.layout.bounding_box_padding;\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[g].display_domain = {\n start: this.parent.x_scale.invert(this.data[g].display_range.start),\n end: this.parent.x_scale.invert(this.data[g].display_range.end)\n };\n this.data[g].display_domain.width = this.data[g].display_domain.end - this.data[g].display_domain.start;\n\n // Using display range/domain data generated above cast each gene to tracks such that none overlap\n this.data[g].track = null;\n var potential_track = 1;\n while (this.data[g].track === null) {\n var collision_on_potential_track = false;\n this.gene_track_index[potential_track].map(function(placed_gene) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_gene.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_gene.display_range.end, this.display_range.end);\n if ((max_end - min_start) < (placed_gene.display_range.width + this.display_range.width)) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[g]));\n if (!collision_on_potential_track) {\n this.data[g].track = potential_track;\n this.gene_track_index[potential_track].push(this.data[g]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.gene_track_index[potential_track] = [];\n }\n }\n }\n\n // Stash parent references on all genes, trascripts, and exons\n this.data[g].parent = this;\n this.data[g].transcripts.map(function(d, t) {\n this.data[g].transcripts[t].parent = this.data[g];\n this.data[g].transcripts[t].exons.map(function(d, e) {\n this.data[g].transcripts[t].exons[e].parent = this.data[g].transcripts[t];\n }.bind(this));\n }.bind(this));\n\n }.bind(this));\n return this;\n };\n\n /**\n * Main render function\n */\n this.render = function() {\n\n var self = this;\n this.assignTracks();\n\n var width, height, x, y;\n\n // Render gene groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-genes')\n .data(this.data, function(d) { return d.gene_name; });\n\n selection.enter().append('g')\n .attr('class', 'lz-data_layer-genes');\n\n selection.attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .each(function(gene) {\n\n var data_layer = gene.parent;\n\n // Render gene bounding boxes (status nodes to show selected/highlighted)\n var bboxes = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-data_layer-genes-statusnode')\n .data([gene], function(d) { return data_layer.getElementStatusNodeId(d); });\n\n bboxes.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-data_layer-genes-statusnode');\n\n bboxes\n .attr('id', function(d) {\n return data_layer.getElementStatusNodeId(d);\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n bboxes\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n bboxes\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n bboxes.exit().remove();\n\n // Render gene boundaries\n var boundary_fill = function(d) { return self.resolveScalableParameter(self.layout.color, d); };\n var boundary_stroke = function(d) { return self.resolveScalableParameter(self.layout.stroke, d); };\n var boundaries = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-boundary')\n .data([gene], function(d) { return d.gene_name + '_boundary'; })\n .style({ fill: boundary_fill, stroke: boundary_stroke });\n\n boundaries.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-boundary');\n\n width = function(d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function() {\n return 1; // TODO: scale dynamically?\n };\n x = function(d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size\n + data_layer.layout.label_exon_spacing\n + (Math.max(data_layer.layout.exon_height, 3) / 2);\n };\n if (data_layer.canTransition()) {\n boundaries\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n boundaries\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n boundaries.exit().remove();\n\n // Render gene labels\n var labels = d3.select(this).selectAll('text.lz-data_layer-genes.lz-label')\n .data([gene], function(d) { return d.gene_name + '_label'; });\n\n labels.enter().append('text')\n .attr('class', 'lz-data_layer-genes lz-label');\n\n labels\n .attr('text-anchor', function(d) {\n return d.display_range.text_anchor;\n })\n .text(function(d) {\n return (d.strand === '+') ? d.gene_name + '→' : '←' + d.gene_name;\n })\n .style('font-size', gene.parent.layout.label_font_size);\n\n x = function(d) {\n if (d.display_range.text_anchor === 'middle') {\n return d.display_range.start + (d.display_range.width / 2);\n } else if (d.display_range.text_anchor === 'start') {\n return d.display_range.start + data_layer.layout.bounding_box_padding;\n } else if (d.display_range.text_anchor === 'end') {\n return d.display_range.end - data_layer.layout.bounding_box_padding;\n }\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size;\n };\n if (data_layer.canTransition()) {\n labels\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('x', x).attr('y', y);\n } else {\n labels\n .attr('x', x).attr('y', y);\n }\n\n labels.exit().remove();\n\n // Render exon rects (first transcript only, for now)\n // Exons: by default color on gene properties for consistency with the gene boundary track- hence color uses d.parent.parent\n var exon_fill = function(d) { return self.resolveScalableParameter(self.layout.color, d.parent.parent); };\n var exon_stroke = function(d) { return self.resolveScalableParameter(self.layout.stroke, d.parent.parent); };\n\n var exons = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-exon')\n .data(gene.transcripts[gene.parent.transcript_idx].exons, function(d) { return d.exon_id; });\n\n exons.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-exon');\n\n exons\n .style({ fill: exon_fill, stroke: exon_stroke });\n\n width = function(d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function() {\n return data_layer.layout.exon_height;\n };\n x = function(d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function() {\n return ((gene.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size\n + data_layer.layout.label_exon_spacing;\n };\n if (data_layer.canTransition()) {\n exons\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n exons\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n exons.exit().remove();\n\n // Render gene click area\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-clickarea')\n .data([gene], function(d) { return d.gene_name + '_clickarea'; });\n\n clickareas.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-clickarea');\n\n clickareas\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '_clickarea';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n clickareas\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n // Remove old clickareas as needed\n clickareas.exit().remove();\n\n // Apply default event emitters to clickareas\n clickareas.on('click.event_emitter', function(element) {\n element.parent.parent.emit('element_clicked', element, true);\n });\n\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n\n });\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n /**\n * Reimplement the positionTooltip() method to be gene-specific\n * @param {String} id\n */\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var gene_bbox_id = this.getElementStatusNodeId(tooltip.data);\n var gene_bbox = d3.select('#' + gene_bbox_id).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the gene that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var gene_center_x = ((tooltip.data.display_range.start + tooltip.data.display_range.end) / 2) - (this.layout.bounding_box_padding / 2);\n var offset_right = Math.max((tooltip_box.width / 2) - gene_center_x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + gene_center_x - data_layer_width, 0);\n var left = page_origin.x + gene_center_x - (tooltip_box.width / 2) - offset_left + offset_right;\n var arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right;\n // Position vertically below the gene unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (gene_bbox.y + gene_bbox.height)) {\n top = page_origin.y + gene_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + gene_bbox.y + gene_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n return this;\n\n});\n","'use strict';\n\n/*********************\n Genome Legend Data Layer\n Implements a data layer that will render a genome legend\n*/\n\n// Build a custom data layer for a genome legend\nLocusZoom.DataLayers.add('genome_legend', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n chromosome_fill_colors: {\n light: 'rgb(155, 155, 188)',\n dark: 'rgb(95, 95, 128)'\n },\n chromosome_label_colors: {\n light: 'rgb(120, 120, 186)',\n dark: 'rgb(0, 0, 66)'\n }\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Implement the main render function\n this.render = function() {\n\n // Iterate over data to generate genome-wide start/end values for each chromosome\n var position = 0;\n this.data.forEach(function(d, i) {\n this.data[i].genome_start = position;\n this.data[i].genome_end = position + d['genome:base_pairs'];\n position += d['genome:base_pairs'];\n }.bind(this));\n\n var chromosomes = this.svg.group\n .selectAll('rect.lz-data_layer-genome_legend')\n .data(this.data, function(d) { return d['genome:chr']; });\n\n // Create chromosome elements, apply class\n chromosomes.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-genome_legend');\n\n // Position and fill chromosome rects\n var data_layer = this;\n var panel = this.parent;\n\n chromosomes\n .attr('fill', function(d) { return (d['genome:chr'] % 2 ? data_layer.layout.chromosome_fill_colors.light : data_layer.layout.chromosome_fill_colors.dark); })\n .attr('x', function(d) { return panel.x_scale(d.genome_start); })\n .attr('y', 0)\n .attr('width', function(d) { return panel.x_scale(d['genome:base_pairs']); })\n .attr('height', panel.layout.cliparea.height);\n\n // Remove old elements as needed\n chromosomes.exit().remove();\n\n // Parse current state variant into a position\n // Assumes that variant string is of the format 10:123352136_C/T or 10:123352136\n var variant_parts = /([^:]+):(\\d+)(?:_.*)?/.exec(this.state.variant);\n if (!variant_parts) {\n throw new Error('Genome legend cannot understand the specified variant position');\n }\n var chr = variant_parts[1];\n var offset = variant_parts[2];\n // TODO: How does this handle representation of X or Y chromosomes?\n position = +this.data[chr - 1].genome_start + +offset;\n\n // Render the position\n var region = this.svg.group\n .selectAll('rect.lz-data_layer-genome_legend-marker')\n .data([{ start: position, end: position + 1 }]);\n\n region.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-genome_legend-marker');\n\n region\n .transition()\n .duration(500)\n .style({\n 'fill': 'rgba(255, 250, 50, 0.8)',\n 'stroke': 'rgba(255, 250, 50, 0.8)',\n 'stroke-width': '3px'\n })\n .attr('x', function(d) { return panel.x_scale(d.start); })\n .attr('y', 0)\n .attr('width', function(d) { return panel.x_scale(d.end - d.start); })\n .attr('height', panel.layout.cliparea.height);\n\n region.exit().remove();\n\n };\n\n return this;\n\n});\n","'use strict';\n\n/**\n * Intervals Data Layer\n * Implements a data layer that will render interval annotation tracks (intervals must provide start and end values)\n * @class LocusZoom.DataLayers.intervals\n * @augments LocusZoom.DataLayer\n */\nLocusZoom.DataLayers.add('intervals', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n start_field: 'start',\n end_field: 'end',\n track_split_field: 'state_id',\n track_split_order: 'DESC',\n track_split_legend_to_y_axis: 2,\n split_tracks: true,\n track_height: 15,\n track_vertical_spacing: 3,\n bounding_box_padding: 2,\n always_hide_legend: false,\n color: '#B8B8B8',\n fill_opacity: 1\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * To define shared highlighting on the track split field define the status node id override\n * to generate an ID common to the track when we're actively splitting data out to separate tracks\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function(element) {\n if (this.layout.split_tracks) {\n return (this.getBaseId() + '-statusnode-' + element[this.layout.track_split_field]).replace(/[:.[\\],]/g, '_');\n }\n return this.getElementId(element) + '-statusnode';\n }.bind(this);\n\n // Helper function to sum layout values to derive total height for a single interval track\n this.getTrackHeight = function() {\n return this.layout.track_height\n + this.layout.track_vertical_spacing\n + (2 * this.layout.bounding_box_padding);\n };\n\n this.tracks = 1;\n this.previous_tracks = 1;\n\n // track-number-indexed object with arrays of interval indexes in the dataset\n this.interval_track_index = { 1: [] };\n\n // After we've loaded interval data interpret it to assign\n // each to a track so that they do not overlap in the view\n this.assignTracks = function() {\n\n // Reinitialize some metadata\n this.previous_tracks = this.tracks;\n this.tracks = 0;\n this.interval_track_index = { 1: [] };\n this.track_split_field_index = {};\n\n // If splitting tracks by a field's value then do a first pass determine\n // a value/track mapping that preserves the order of possible values\n if (this.layout.track_split_field && this.layout.split_tracks) {\n this.data.map(function(d) {\n this.track_split_field_index[d[this.layout.track_split_field]] = null;\n }.bind(this));\n var index = Object.keys(this.track_split_field_index);\n if (this.layout.track_split_order === 'DESC') { index.reverse(); }\n index.forEach(function(val) {\n this.track_split_field_index[val] = this.tracks + 1;\n this.interval_track_index[this.tracks + 1] = [];\n this.tracks++;\n }.bind(this));\n }\n\n this.data.map(function(d, i) {\n\n // Stash a parent reference on the interval\n this.data[i].parent = this;\n\n // Determine display range start and end, based on minimum allowable interval display width,\n // bounded by what we can see (range: values in terms of pixels on the screen)\n this.data[i].display_range = {\n start: this.parent.x_scale(Math.max(d[this.layout.start_field], this.state.start)),\n end: this.parent.x_scale(Math.min(d[this.layout.end_field], this.state.end))\n };\n this.data[i].display_range.width = this.data[i].display_range.end - this.data[i].display_range.start;\n\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[i].display_domain = {\n start: this.parent.x_scale.invert(this.data[i].display_range.start),\n end: this.parent.x_scale.invert(this.data[i].display_range.end)\n };\n this.data[i].display_domain.width = this.data[i].display_domain.end - this.data[i].display_domain.start;\n\n // If splitting to tracks based on the value of the designated track split field\n // then don't bother with collision detection (intervals will be grouped on tracks\n // solely by the value of track_split_field)\n if (this.layout.track_split_field && this.layout.split_tracks) {\n var val = this.data[i][this.layout.track_split_field];\n this.data[i].track = this.track_split_field_index[val];\n this.interval_track_index[this.data[i].track].push(i);\n } else {\n // If not splitting to tracks based on a field value then do so based on collision\n // detection (as how it's done for genes). Use display range/domain data generated\n // above and cast each interval to tracks such that none overlap\n this.tracks = 1;\n this.data[i].track = null;\n var potential_track = 1;\n while (this.data[i].track === null) {\n var collision_on_potential_track = false;\n this.interval_track_index[potential_track].map(function(placed_interval) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_interval.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_interval.display_range.end, this.display_range.end);\n if ((max_end - min_start) < (placed_interval.display_range.width + this.display_range.width)) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[i]));\n if (!collision_on_potential_track) {\n this.data[i].track = potential_track;\n this.interval_track_index[potential_track].push(this.data[i]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.interval_track_index[potential_track] = [];\n }\n }\n }\n\n }\n\n }.bind(this));\n\n return this;\n };\n\n // Implement the main render function\n this.render = function() {\n\n this.assignTracks();\n\n // Remove any shared highlight nodes and re-render them if we're splitting on tracks\n // At most there will only be dozen or so nodes here (one per track) and each time\n // we render data we may have new tracks, so wiping/redrawing all is reasonable.\n this.svg.group.selectAll('.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-shared').remove();\n Object.keys(this.track_split_field_index).forEach(function(key) {\n // Make a psuedo-element so that we can generate an id for the shared node\n var psuedoElement = {};\n psuedoElement[this.layout.track_split_field] = key;\n // Insert the shared node\n var sharedstatusnode_style = {display: (this.layout.split_tracks ? null : 'none')};\n this.svg.group.insert('rect', ':first-child')\n .attr('id', this.getElementStatusNodeId(psuedoElement))\n .attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-shared')\n .attr('rx', this.layout.bounding_box_padding).attr('ry', this.layout.bounding_box_padding)\n .attr('width', this.parent.layout.cliparea.width)\n .attr('height', this.getTrackHeight() - this.layout.track_vertical_spacing)\n .attr('x', 0)\n .attr('y', (this.track_split_field_index[key] - 1) * this.getTrackHeight())\n .style(sharedstatusnode_style);\n }.bind(this));\n\n var width, height, x, y, fill, fill_opacity;\n\n // Render interval groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-intervals')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n selection.enter().append('g')\n .attr('class', 'lz-data_layer-intervals');\n\n selection.attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .each(function(interval) {\n\n var data_layer = interval.parent;\n\n // Render interval status nodes (displayed behind intervals to show highlight\n // without needing to modify interval display element(s))\n var statusnode_style = {display: (data_layer.layout.split_tracks ? 'none' : null)};\n var statusnodes = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-statusnode-discrete')\n .data([interval], function(d) { return data_layer.getElementId(d) + '-statusnode'; });\n statusnodes.enter().insert('rect', ':first-child')\n .attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-statusnode-discrete');\n statusnodes\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '-statusnode';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .style(statusnode_style);\n width = function(d) {\n return d.display_range.width + (2 * data_layer.layout.bounding_box_padding);\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start - data_layer.layout.bounding_box_padding;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n statusnodes\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n statusnodes\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n statusnodes.exit().remove();\n\n // Render primary interval rects\n var rects = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-interval_rect')\n .data([interval], function(d) { return d[data_layer.layout.id_field] + '_interval_rect'; });\n\n rects.enter().append('rect')\n .attr('class', 'lz-data_layer-intervals lz-interval_rect');\n\n height = data_layer.layout.track_height;\n width = function(d) {\n return d.display_range.width;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding;\n };\n fill = function(d) {\n return data_layer.resolveScalableParameter(data_layer.layout.color, d);\n };\n fill_opacity = function(d) {\n return data_layer.resolveScalableParameter(data_layer.layout.fill_opacity, d);\n };\n\n\n if (data_layer.canTransition()) {\n rects\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height)\n .attr('x', x).attr('y', y)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity);\n } else {\n rects\n .attr('width', width).attr('height', height)\n .attr('x', x).attr('y', y)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity);\n }\n\n rects.exit().remove();\n\n // Render interval click areas\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-clickarea')\n .data([interval], function(d) { return d.interval_name + '_clickarea'; });\n\n clickareas.enter().append('rect')\n .attr('class', 'lz-data_layer-intervals lz-clickarea');\n\n clickareas\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '_clickarea';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n clickareas\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n // Remove old clickareas as needed\n clickareas.exit().remove();\n\n // Apply default event emitters to clickareas\n clickareas.on('click', function(element_data) {\n element_data.parent.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n\n });\n\n // Remove old elements as needed\n selection.exit().remove();\n\n // Update the legend axis if the number of ticks changed\n if (this.previous_tracks !== this.tracks) {\n this.updateSplitTrackAxis();\n }\n\n return this;\n\n };\n\n // Reimplement the positionTooltip() method to be interval-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var interval_bbox = d3.select('#' + this.getElementStatusNodeId(tooltip.data)).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the interval that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var interval_center_x = ((tooltip.data.display_range.start + tooltip.data.display_range.end) / 2) - (this.layout.bounding_box_padding / 2);\n var offset_right = Math.max((tooltip_box.width / 2) - interval_center_x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + interval_center_x - data_layer_width, 0);\n var left = page_origin.x + interval_center_x - (tooltip_box.width / 2) - offset_left + offset_right;\n var arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right;\n // Position vertically below the interval unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (interval_bbox.y + interval_bbox.height)) {\n top = page_origin.y + interval_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + interval_bbox.y + interval_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Redraw split track axis or hide it, and show/hide the legend, as determined\n // by current layout parameters and data\n this.updateSplitTrackAxis = function() {\n var legend_axis = this.layout.track_split_legend_to_y_axis ? 'y' + this.layout.track_split_legend_to_y_axis : false;\n if (this.layout.split_tracks) {\n var tracks = +this.tracks || 0;\n var track_height = +this.layout.track_height || 0;\n var track_spacing = 2 * (+this.layout.bounding_box_padding || 0) + (+this.layout.track_vertical_spacing || 0);\n var target_height = (tracks * track_height) + ((tracks - 1) * track_spacing);\n this.parent.scaleHeightToData(target_height);\n if (legend_axis && this.parent.legend) {\n this.parent.legend.hide();\n this.parent.layout.axes[legend_axis] = {\n render: true,\n ticks: [],\n range: {\n start: (target_height - (this.layout.track_height / 2)),\n end: (this.layout.track_height / 2)\n }\n };\n this.layout.legend.forEach(function(element) {\n var key = element[this.layout.track_split_field];\n var track = this.track_split_field_index[key];\n if (track) {\n if (this.layout.track_split_order === 'DESC') {\n track = Math.abs(track - tracks - 1);\n }\n this.parent.layout.axes[legend_axis].ticks.push({\n y: track,\n text: element.label\n });\n }\n }.bind(this));\n this.layout.y_axis = {\n axis: this.layout.track_split_legend_to_y_axis,\n floor: 1,\n ceiling: tracks\n };\n this.parent.render();\n }\n this.parent_plot.positionPanels();\n } else {\n if (legend_axis && this.parent.legend) {\n if (!this.layout.always_hide_legend) { this.parent.legend.show(); }\n this.parent.layout.axes[legend_axis] = { render: false };\n this.parent.render();\n }\n }\n return this;\n };\n\n // Method to not only toggle the split tracks boolean but also update\n // necessary display values to animate a complete merge/split\n this.toggleSplitTracks = function() {\n this.layout.split_tracks = !this.layout.split_tracks;\n if (this.parent.legend && !this.layout.always_hide_legend) {\n this.parent.layout.margin.bottom = 5 + (this.layout.split_tracks ? 0 : this.parent.legend.layout.height + 5);\n }\n this.render();\n this.updateSplitTrackAxis();\n return this;\n };\n\n return this;\n\n});\n","'use strict';\n\n/*********************\n * Line Data Layer\n * Implements a standard line plot, representing either a trace or a filled curve.\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('line', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n /** @member {Object} */\n this.DefaultLayout = {\n style: {\n fill: 'none',\n 'stroke-width': '2px'\n },\n interpolate: 'linear',\n x_axis: { field: 'x' },\n y_axis: { field: 'y', axis: 1 },\n hitarea_width: 5\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Var for storing mouse events for use in tool tip positioning\n /** @member {String} */\n this.mouse_event = null;\n\n /**\n * Var for storing the generated line function itself\n * @member {d3.svg.line}\n * */\n this.line = null;\n\n /**\n * The timeout identifier returned by setTimeout\n * @member {Number}\n */\n this.tooltip_timeout = null;\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n\n /**\n * Helper function to get display and data objects representing\n * the x/y coordinates of the current mouse event with respect to the line in terms of the display\n * and the interpolated values of the x/y fields with respect to the line\n * @returns {{display: {x: *, y: null}, data: {}, slope: null}}\n */\n this.getMouseDisplayAndData = function() {\n var ret = {\n display: {\n x: d3.mouse(this.mouse_event)[0],\n y: null\n },\n data: {},\n slope: null\n };\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n ret.data[x_field] = this.parent[x_scale].invert(ret.display.x);\n var bisect = d3.bisector(function(datum) { return +datum[x_field]; }).left;\n var index = bisect(this.data, ret.data[x_field]) - 1;\n var startDatum = this.data[index];\n var endDatum = this.data[index + 1];\n var interpolate = d3.interpolateNumber(+startDatum[y_field], +endDatum[y_field]);\n var range = +endDatum[x_field] - +startDatum[x_field];\n ret.data[y_field] = interpolate((ret.data[x_field] % range) / range);\n ret.display.y = this.parent[y_scale](ret.data[y_field]);\n if (this.layout.tooltip.x_precision) {\n ret.data[x_field] = ret.data[x_field].toPrecision(this.layout.tooltip.x_precision);\n }\n if (this.layout.tooltip.y_precision) {\n ret.data[y_field] = ret.data[y_field].toPrecision(this.layout.tooltip.y_precision);\n }\n ret.slope = (this.parent[y_scale](endDatum[y_field]) - this.parent[y_scale](startDatum[y_field]))\n / (this.parent[x_scale](endDatum[x_field]) - this.parent[x_scale](startDatum[x_field]));\n return ret;\n };\n\n /**\n * Reimplement the positionTooltip() method to be line-specific\n * @param {String} id Identify the tooltip to be positioned\n */\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var arrow_width = 7; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var stroke_width = parseFloat(this.layout.style['stroke-width']) || 1;\n var page_origin = this.getPageOrigin();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n var top, left, arrow_top, arrow_left, arrow_type;\n\n // Determine x/y coordinates for display and data\n var dd = this.getMouseDisplayAndData();\n\n // If the absolute value of the slope of the line at this point is above 1 (including Infinity)\n // then position the tool tip left/right. Otherwise position top/bottom.\n if (Math.abs(dd.slope) > 1) {\n\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (dd.display.x <= this.parent.layout.width / 2) {\n left = page_origin.x + dd.display.x + stroke_width + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + dd.display.x - tooltip_box.width - stroke_width - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n if (dd.display.y - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + dd.display.y - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (dd.display.y + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + dd.display.y + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + dd.display.y - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n\n } else {\n\n // Position horizontally: attempt to center on the mouse's x coordinate\n // pad to either side if bumping up against the edge of the data layer\n var offset_right = Math.max((tooltip_box.width / 2) - dd.display.x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + dd.display.x - data_layer_width, 0);\n left = page_origin.x + dd.display.x - (tooltip_box.width / 2) - offset_left + offset_right;\n var min_arrow_left = arrow_width / 2;\n var max_arrow_left = tooltip_box.width - (2.5 * arrow_width);\n arrow_left = (tooltip_box.width / 2) - arrow_width + offset_left - offset_right;\n arrow_left = Math.min(Math.max(arrow_left, min_arrow_left), max_arrow_left);\n\n // Position vertically above the line unless there's insufficient space\n if (tooltip_box.height + stroke_width + arrow_width > dd.display.y) {\n top = page_origin.y + dd.display.y + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n } else {\n top = page_origin.y + dd.display.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n }\n }\n\n // Apply positions to the main div\n tooltip.selector.style({ left: left + 'px', top: top + 'px' });\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style({ 'left': arrow_left + 'px', top: arrow_top + 'px' });\n\n };\n\n /**\n * Implement the main render function\n */\n this.render = function() {\n\n // Several vars needed to be in scope\n var data_layer = this;\n var panel = this.parent;\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n // Join data to the line selection\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-line')\n .data([this.data]);\n\n // Create path element, apply class\n this.path = selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line');\n\n // Generate the line\n if (this.layout.style.fill && this.layout.style.fill !== 'none') {\n // Filled curve: define the line as a filled boundary\n this.line = d3.svg.area()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y0(function(d) {return parseFloat(panel[y_scale](0));})\n .y1(function(d) { return parseFloat(panel[y_scale](d[y_field])); });\n } else {\n // Basic line\n this.line = d3.svg.line()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y(function(d) { return parseFloat(panel[y_scale](d[y_field])); })\n .interpolate(this.layout.interpolate);\n }\n\n // Apply line and style\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('d', this.line)\n .style(this.layout.style);\n } else {\n selection\n .attr('d', this.line)\n .style(this.layout.style);\n }\n\n // Apply tooltip, etc\n if (this.layout.tooltip) {\n // Generate an overlaying transparent \"hit area\" line for more intuitive mouse events\n var hitarea_width = parseFloat(this.layout.hitarea_width).toString() + 'px';\n var hitarea = this.svg.group\n .selectAll('path.lz-data_layer-line-hitarea')\n .data([this.data]);\n hitarea.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line-hitarea')\n .style('stroke-width', hitarea_width);\n var hitarea_line = d3.svg.line()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y(function(d) { return parseFloat(panel[y_scale](d[y_field])); })\n .interpolate(this.layout.interpolate);\n hitarea\n .attr('d', hitarea_line)\n .on('mouseover', function() {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.createTooltip(dd.data);\n })\n .on('mousemove', function() {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.updateTooltip(dd.data);\n data_layer.positionTooltip(data_layer.getElementId());\n })\n .on('mouseout', function() {\n data_layer.tooltip_timeout = setTimeout(function() {\n data_layer.mouse_event = null;\n data_layer.destroyTooltip(data_layer.getElementId());\n }, 300);\n });\n hitarea.exit().remove();\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n /**\n * Redefine setElementStatus family of methods as line data layers will only ever have a single path element\n * @param {String} status A member of `LocusZoom.DataLayer.Statuses.adjectives`\n * @param {String|Object} element\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\n this.setElementStatus = function(status, element, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setElementStatusByFilters = function(status, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setAllElementStatus = function(status, toggle) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; }\n\n // Update global status flag\n this.global_statuses[status] = toggle;\n\n // Apply class to path based on global status flags\n var path_class = 'lz-data_layer-line';\n Object.keys(this.global_statuses).forEach(function(global_status) {\n if (this.global_statuses[global_status]) { path_class += ' lz-data_layer-line-' + global_status; }\n }.bind(this));\n this.path.attr('class', path_class);\n\n // Trigger layout changed event hook\n this.parent.emit('layout_changed', true);\n return this;\n };\n\n return this;\n\n});\n\n\n/***************************\n * Orthogonal Line Data Layer\n * Implements a horizontal or vertical line given an orientation and an offset in the layout\n * Does not require a data source\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('orthogonal_line', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n style: {\n 'stroke': '#D3D3D3',\n 'stroke-width': '3px',\n 'stroke-dasharray': '10px 10px'\n },\n orientation: 'horizontal',\n x_axis: {\n axis: 1,\n decoupled: true\n },\n y_axis: {\n axis: 1,\n decoupled: true\n },\n offset: 0\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Require that orientation be \"horizontal\" or \"vertical\" only\n if (['horizontal','vertical'].indexOf(layout.orientation) === -1) {\n layout.orientation = 'horizontal';\n }\n\n // Vars for storing the data generated line\n /** @member {Array} */\n this.data = [];\n /** @member {d3.svg.line} */\n this.line = null;\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * Implement the main render function\n */\n this.render = function() {\n\n // Several vars needed to be in scope\n var panel = this.parent;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var x_extent = 'x_extent';\n var y_extent = 'y' + this.layout.y_axis.axis + '_extent';\n var x_range = 'x_range';\n\n // Generate data using extents depending on orientation\n if (this.layout.orientation === 'horizontal') {\n this.data = [\n { x: panel[x_extent][0], y: this.layout.offset },\n { x: panel[x_extent][1], y: this.layout.offset }\n ];\n } else if (this.layout.orientation === 'vertical') {\n this.data = [\n { x: this.layout.offset, y: panel[y_extent][0] },\n { x: this.layout.offset, y: panel[y_extent][1] }\n ];\n } else {\n throw new Error('Unrecognized vertical line type. Must be \"vertical\" or \"horizontal\"');\n }\n\n // Join data to the line selection\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-line')\n .data([this.data]);\n\n // Create path element, apply class\n this.path = selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line');\n\n // In some cases, a vertical line may overlay a track that has no inherent y-values (extent)\n // When that happens, provide a default height based on the current panel dimensions (accounting\n // for any resizing that happened after the panel was created)\n var default_y = [panel.layout.cliparea.height, 0];\n\n // Generate the line\n this.line = d3.svg.line()\n .x(function(d, i) {\n var x = parseFloat(panel[x_scale](d['x']));\n return isNaN(x) ? panel[x_range][i] : x;\n })\n .y(function(d, i) {\n var y = parseFloat(panel[y_scale](d['y']));\n return isNaN(y) ? default_y[i] : y;\n })\n .interpolate('linear');\n\n // Apply line and style\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('d', this.line)\n .style(this.layout.style);\n } else {\n selection\n .attr('d', this.line)\n .style(this.layout.style);\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n return this;\n\n});\n","'use strict';\n\n/**\n * Scatter Data Layer\n * Implements a standard scatter plot\n * @class LocusZoom.DataLayers.scatter\n */\nLocusZoom.DataLayers.add('scatter', function(layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'circle',\n tooltip_positioning: 'horizontal',\n color: '#888888',\n fill_opacity: 1,\n y_axis: {\n axis: 1\n },\n id_field: 'id'\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Extra default for layout spacing\n // Not in default layout since that would make the label attribute always present\n if (layout.label && isNaN(layout.label.spacing)) {\n layout.label.spacing = 4;\n }\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Reimplement the positionTooltip() method to be scatter-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var offset = Math.sqrt(point_size / Math.PI);\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n if (this.layout.tooltip_positioning === 'vertical') {\n // Position horizontally centered above the point\n var offset_right = Math.max((tooltip_box.width / 2) - x_center, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - (tooltip_box.width / 2) - offset_left + offset_right;\n arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right - offset;\n // Position vertically above the point unless there's insufficient space, then go below\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (y_center + offset)) {\n top = page_origin.y + y_center - (offset + tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + y_center + offset + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n } else {\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n if (y_center - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + y_center - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (y_center + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + y_center - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Function to flip labels from being anchored at the start of the text to the end\n // Both to keep labels from running outside the data layer and also as a first\n // pass on recursive separation\n this.flip_labels = function() {\n var data_layer = this;\n var point_size = data_layer.resolveScalableParameter(data_layer.layout.point_size, {});\n var spacing = data_layer.layout.label.spacing;\n var handle_lines = Boolean(data_layer.layout.label.lines);\n var min_x = 2 * spacing;\n var max_x = data_layer.parent.layout.width - data_layer.parent.layout.margin.left - data_layer.parent.layout.margin.right - (2 * spacing);\n var flip = function(dn, dnl) {\n var dnx = +dn.attr('x');\n var text_swing = (2 * spacing) + (2 * Math.sqrt(point_size));\n if (handle_lines) {\n var dnlx2 = +dnl.attr('x2');\n var line_swing = spacing + (2 * Math.sqrt(point_size));\n }\n if (dn.style('text-anchor') === 'start') {\n dn.style('text-anchor', 'end');\n dn.attr('x', dnx - text_swing);\n if (handle_lines) { dnl.attr('x2', dnlx2 - line_swing); }\n } else {\n dn.style('text-anchor', 'start');\n dn.attr('x', dnx + text_swing);\n if (handle_lines) { dnl.attr('x2', dnlx2 + line_swing); }\n }\n };\n // Flip any going over the right edge from the right side to the left side\n // (all labels start on the right side)\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n if (dax + abound.width + spacing > max_x) {\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n flip(da, dal);\n }\n });\n // Second pass to flip any others that haven't flipped yet if they collide with another label\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n if (da.style('text-anchor') === 'end') {\n return;\n }\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n data_layer.label_texts.each(function () {\n var b = this;\n var db = d3.select(b);\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + (2 * spacing) &&\n abound.left + abound.width + (2 * spacing) > bbound.left &&\n abound.top < bbound.top + bbound.height + (2 * spacing) &&\n abound.height + abound.top + (2 * spacing) > bbound.top;\n if (collision) {\n flip(da, dal);\n // Double check that this flip didn't push the label past min_x. If it did, immediately flip back.\n dax = +da.attr('x');\n if (dax - abound.width - spacing < min_x) {\n flip(da, dal);\n }\n }\n return;\n });\n });\n };\n\n // Recursive function to space labels apart immediately after initial render\n // Adapted from thudfactor's fiddle here: https://jsfiddle.net/thudfactor/HdwTH/\n // TODO: Make labels also aware of data elements\n this.separate_labels = function() {\n this.seperate_iterations++;\n var data_layer = this;\n var alpha = 0.5;\n if (!this.layout.label) {\n // Guard against layout changing in the midst of iterative rerender\n return;\n }\n var spacing = this.layout.label.spacing;\n var again = false;\n data_layer.label_texts.each(function () {\n var a = this;\n var da = d3.select(a);\n var y1 = da.attr('y');\n data_layer.label_texts.each(function () {\n var b = this;\n // a & b are the same element and don't collide.\n if (a === b) {\n return;\n }\n var db = d3.select(b);\n // a & b are on opposite sides of the chart and\n // don't collide\n if (da.attr('text-anchor') !== db.attr('text-anchor')) {\n return;\n }\n // Determine if the bounding rects for the two text elements collide\n var abound = da.node().getBoundingClientRect();\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + (2 * spacing) &&\n abound.left + abound.width + (2 * spacing) > bbound.left &&\n abound.top < bbound.top + bbound.height + (2 * spacing) &&\n abound.height + abound.top + (2 * spacing) > bbound.top;\n if (!collision) {\n return;\n }\n again = true;\n // If the labels collide, we'll push each\n // of the two labels up and down a little bit.\n var y2 = db.attr('y');\n var sign = abound.top < bbound.top ? 1 : -1;\n var adjust = sign * alpha;\n var new_a_y = +y1 - adjust;\n var new_b_y = +y2 + adjust;\n // Keep new values from extending outside the data layer\n var min_y = 2 * spacing;\n var max_y = data_layer.parent.layout.height - data_layer.parent.layout.margin.top - data_layer.parent.layout.margin.bottom - (2 * spacing);\n var delta;\n if (new_a_y - (abound.height / 2) < min_y) {\n delta = +y1 - new_a_y;\n new_a_y = +y1;\n new_b_y += delta;\n } else if (new_b_y - (bbound.height / 2) < min_y) {\n delta = +y2 - new_b_y;\n new_b_y = +y2;\n new_a_y += delta;\n }\n if (new_a_y + (abound.height / 2) > max_y) {\n delta = new_a_y - +y1;\n new_a_y = +y1;\n new_b_y -= delta;\n } else if (new_b_y + (bbound.height / 2) > max_y) {\n delta = new_b_y - +y2;\n new_b_y = +y2;\n new_a_y -= delta;\n }\n da.attr('y',new_a_y);\n db.attr('y',new_b_y);\n });\n });\n if (again) {\n // Adjust lines to follow the labels\n if (data_layer.layout.label.lines) {\n var label_elements = data_layer.label_texts[0];\n data_layer.label_lines.attr('y2',function(d,i) {\n var label_line = d3.select(label_elements[i]);\n return label_line.attr('y');\n });\n }\n // After ~150 iterations we're probably beyond diminising returns, so stop recursing\n if (this.seperate_iterations < 150) {\n setTimeout(function() {\n this.separate_labels();\n }.bind(this), 1);\n }\n }\n };\n\n // Implement the main render function\n this.render = function() {\n\n var data_layer = this;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n if (this.layout.label) {\n // Apply filters to generate a filtered data set\n var filtered_data = this.data.filter(function(d) {\n if (!data_layer.layout.label.filters) {\n return true;\n } else {\n // Start by assuming a match, run through all filters to test if not a match on any one\n var match = true;\n data_layer.layout.label.filters.forEach(function(filter) {\n var field_value = (new LocusZoom.Data.Field(filter.field)).resolve(d);\n if (['!=', '='].indexOf(filter.operator) === -1 && isNaN(field_value)) {\n // If the filter can only be used with numbers, then the value must be numeric.\n match = false;\n } else {\n switch (filter.operator) {\n case '<':\n if (!(field_value < filter.value)) { match = false; }\n break;\n case '<=':\n if (!(field_value <= filter.value)) { match = false; }\n break;\n case '>':\n if (!(field_value > filter.value)) { match = false; }\n break;\n case '>=':\n if (!(field_value >= filter.value)) { match = false; }\n break;\n case '=':\n if (!(field_value === filter.value)) { match = false; }\n break;\n case '!=':\n // Deliberately allow weak comparisons to test for \"anything with a value present\" (null or undefined)\n // eslint-disable-next-line eqeqeq\n if (field_value == filter.value) { match = false; }\n break;\n default:\n // If we got here the operator is not valid, so the filter should fail\n match = false;\n break;\n }\n }\n });\n return match;\n }\n });\n // Render label groups\n var self = this;\n this.label_groups = this.svg.group\n .selectAll('g.lz-data_layer-' + this.layout.type + '-label')\n .data(filtered_data, function(d) { return d[self.layout.id_field] + '_label'; });\n this.label_groups.enter()\n .append('g')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n // Render label texts\n if (this.label_texts) { this.label_texts.remove(); }\n this.label_texts = this.label_groups.append('text')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_texts\n .text(function(d) {\n return LocusZoom.parseFields(d, data_layer.layout.label.text || '');\n })\n .style(data_layer.layout.label.style || {})\n .attr({\n 'x': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field])\n + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d))\n + data_layer.layout.label.spacing;\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n },\n 'text-anchor': function() {\n return 'start';\n }\n });\n // Render label lines\n if (data_layer.layout.label.lines) {\n if (this.label_lines) { this.label_lines.remove(); }\n this.label_lines = this.label_groups.append('line')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_lines\n .style(data_layer.layout.label.lines.style || {})\n .attr({\n 'x1': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]);\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y1': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n },\n 'x2': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field])\n + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d))\n + (data_layer.layout.label.spacing / 2);\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y2': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n }\n });\n }\n // Remove labels when they're no longer in the filtered data set\n this.label_groups.exit().remove();\n } else {\n // If the layout definition has changed (& no longer specifies labels), strip any previously rendered\n if (this.label_groups) { this.label_groups.remove(); }\n if (this.label_lines) { this.label_lines.remove(); }\n }\n\n // Generate main scatter data elements\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-' + this.layout.type)\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .attr('transform', 'translate(0,' + initial_y + ')');\n\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n\n var fill = function(d) { return this.resolveScalableParameter(this.layout.color, d); }.bind(this);\n var fill_opacity = function(d) { return this.resolveScalableParameter(this.layout.fill_opacity, d); }.bind(this);\n\n var shape = d3.svg.symbol()\n .size(function(d) { return this.resolveScalableParameter(this.layout.point_size, d); }.bind(this))\n .type(function(d) { return this.resolveScalableParameter(this.layout.point_shape, d); }.bind(this));\n\n // Apply position and color, using a transition if necessary\n\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n } else {\n selection\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n // Apply default event emitters to selection\n selection.on('click.event_emitter', function(element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n\n // Apply mouse behaviors\n this.applyBehaviors(selection);\n\n // Apply method to keep labels from overlapping each other\n if (this.layout.label) {\n this.flip_labels();\n this.seperate_iterations = 0;\n this.separate_labels();\n // Apply default event emitters to selection\n this.label_texts.on('click.event_emitter', function(element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n // Extend mouse behaviors to labels\n this.applyBehaviors(this.label_texts);\n }\n\n };\n\n // Method to set a passed element as the LD reference in the plot-level state\n this.makeLDReference = function(element) {\n var ref = null;\n if (typeof element == 'undefined') {\n throw new Error('makeLDReference requires one argument of any type');\n } else if (typeof element == 'object') {\n if (this.layout.id_field && typeof element[this.layout.id_field] != 'undefined') {\n ref = element[this.layout.id_field].toString();\n } else if (typeof element['id'] != 'undefined') {\n ref = element['id'].toString();\n } else {\n ref = element.toString();\n }\n } else {\n ref = element.toString();\n }\n this.parent_plot.applyState({ ldrefvar: ref });\n };\n\n return this;\n\n});\n\n/**\n * A scatter plot in which the x-axis represents categories, rather than individual positions.\n * For example, this can be used by PheWAS plots to show related groups. This plot allows the categories to be\n * determined dynamically when data is first loaded.\n *\n * @class LocusZoom.DataLayers.category_scatter\n * @augments LocusZoom.DataLayers.scatter\n */\nLocusZoom.DataLayers.extend('scatter', 'category_scatter', {\n /**\n * This plot layer makes certain assumptions about the data passed in. Transform the raw array of records from\n * the datasource to prepare it for plotting, as follows:\n * 1. The scatter plot assumes that all records are given in sequence (pre-grouped by `category_field`)\n * 2. It assumes that all records have an x coordinate for individual plotting\n * @private\n */\n _prepareData: function() {\n var xField = this.layout.x_axis.field || 'x';\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n // Sort the data so that things in the same category are adjacent (case-insensitive by specified field)\n var sourceData = this.data\n .sort(function(a, b) {\n var ak = a[category_field];\n var bk = b[category_field];\n var av = (typeof ak === 'string') ? ak.toLowerCase() : ak;\n var bv = (typeof bk === 'string') ? bk.toLowerCase() : bk;\n return (av === bv) ? 0 : (av < bv ? -1 : 1);});\n sourceData.forEach(function(d, i) {\n // Implementation detail: Scatter plot requires specifying an x-axis value, and most datasources do not\n // specify plotting positions. If a point is missing this field, fill in a synthetic value.\n d[xField] = d[xField] || i;\n });\n return sourceData;\n },\n\n /**\n * Identify the unique categories on the plot, and update the layout with an appropriate color scheme.\n * Also identify the min and max x value associated with the category, which will be used to generate ticks\n * @private\n * @returns {Object.} Series of entries used to build category name ticks {category_name: [min_x, max_x]}\n */\n _generateCategoryBounds: function() {\n // TODO: API may return null values in category_field; should we add placeholder category label?\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n var xField = this.layout.x_axis.field || 'x';\n var uniqueCategories = {};\n this.data.forEach(function(item) {\n var category = item[category_field];\n var x = item[xField];\n var bounds = uniqueCategories[category] || [x, x];\n uniqueCategories[category] = [Math.min(bounds[0], x), Math.max(bounds[1], x)];\n });\n\n var categoryNames = Object.keys(uniqueCategories);\n this._setDynamicColorScheme(categoryNames);\n\n return uniqueCategories;\n },\n\n /**\n * This layer relies on defining its own category-based color scheme. Find the correct color config object to\n * be modified.\n * @param [from_source]\n * @returns {Object} A mutable reference to the layout configuration object\n * @private\n */\n _getColorScale: function(from_source) {\n from_source = from_source || this.layout;\n // If the layout does not use a supported coloring scheme, or is already complete, this method should do nothing\n\n // For legacy reasons, layouts can specify color as an object (only one way to set color), as opposed to the\n // preferred mechanism of array (multiple coloring options)\n var color_params = from_source.color || []; // Object or scalar, no other options allowed\n if (Array.isArray(color_params)) {\n color_params = color_params.find(function(item) { return item.scale_function === 'categorical_bin'; });\n }\n if (!color_params || color_params.scale_function !== 'categorical_bin') {\n throw new Error('This layer requires that color options be provided as a `categorical_bin`');\n }\n return color_params;\n },\n\n /**\n * Automatically define a color scheme for the layer based on data returned from the server.\n * If part of the color scheme has been specified, it will fill in remaining missing information.\n *\n * There are three scenarios:\n * 1. The layout does not specify either category names or (color) values. Dynamically build both based on\n * the data and update the layout.\n * 2. The layout specifies colors, but not categories. Use that exact color information provided, and dynamically\n * determine what categories are present in the data. (cycle through the available colors, reusing if there\n * are a lot of categories)\n * 3. The layout specifies exactly what colors and categories to use (and they match the data!). This is useful to\n * specify an explicit mapping between color scheme and category names, when you want to be sure that the\n * plot matches a standard color scheme.\n * (If the layout specifies categories that do not match the data, the user specified categories will be ignored)\n *\n * This method will only act if the layout defines a `categorical_bin` scale function for coloring. It may be\n * overridden in a subclass to suit other types of coloring methods.\n *\n * @param {String[]} categoryNames\n * @private\n */\n _setDynamicColorScheme: function(categoryNames) {\n var colorParams = this._getColorScale(this.layout).parameters;\n var baseParams = this._getColorScale(this._base_layout).parameters;\n\n if (baseParams.categories.length && baseParams.values.length) {\n // If there are preset category/color combos, make sure that they apply to the actual dataset\n var parameters_categories_hash = {};\n baseParams.categories.forEach(function (category) { parameters_categories_hash[category] = 1; });\n if (categoryNames.every(function (name) { return parameters_categories_hash.hasOwnProperty(name); })) {\n // The layout doesn't have to specify categories in order, but make sure they are all there\n colorParams.categories = baseParams.categories;\n } else {\n colorParams.categories = categoryNames;\n }\n } else {\n colorParams.categories = categoryNames;\n }\n // Prefer user-specified colors if provided. Make sure that there are enough colors for all the categories.\n var colors;\n if (baseParams.values.length) {\n colors = baseParams.values;\n } else {\n var color_scale = categoryNames.length <= 10 ? d3.scale.category10 : d3.scale.category20;\n colors = color_scale().range();\n }\n while (colors.length < categoryNames.length) { colors = colors.concat(colors); }\n colors = colors.slice(0, categoryNames.length); // List of hex values, should be of same length as categories array\n colorParams.values = colors;\n },\n\n /**\n *\n * @param dimension\n * @param {Object} [config] Parameters that customize how ticks are calculated (not style)\n * @param {('left'|'center'|'right')} [config.position='left'] Align ticks with the center or edge of category\n * @returns {Array}\n */\n getTicks: function(dimension, config) { // Overrides parent method\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier');\n }\n var position = config.position || 'left';\n if (['left', 'center', 'right'].indexOf(position) === -1) {\n throw new Error('Invalid tick position');\n }\n\n var categoryBounds = this._categories;\n if (!categoryBounds || !Object.keys(categoryBounds).length) {\n return [];\n }\n\n if (dimension === 'y') {\n return [];\n }\n\n if (dimension === 'x') {\n // If colors have been defined by this layer, use them to make tick colors match scatterplot point colors\n var colors = this._getColorScale(this.layout);\n var knownCategories = colors.parameters.categories || [];\n var knownColors = colors.parameters.values || [];\n\n return Object.keys(categoryBounds).map(function (category, index) {\n var bounds = categoryBounds[category];\n var xPos;\n\n switch(position) {\n case 'left':\n xPos = bounds[0];\n break;\n case 'center':\n // Center tick under one or many elements as appropriate\n var diff = bounds[1] - bounds[0];\n xPos = bounds[0] + (diff !== 0 ? diff : bounds[0]) / 2;\n break;\n case 'right':\n xPos = bounds[1];\n break;\n }\n return {\n x: xPos,\n text: category,\n style: {\n 'fill': knownColors[knownCategories.indexOf(category)] || '#000000'\n }\n };\n });\n }\n },\n\n applyCustomDataMethods: function() {\n this.data = this._prepareData();\n /**\n * Define category names and extents (boundaries) for plotting. TODO: properties in constructor\n * @member {Object.} Category names and extents, in the form {category_name: [min_x, max_x]}\n */\n this._categories = this._generateCategoryBounds();\n return this;\n }\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n *\n * LocusZoom has various singleton objects that are used for registering functions or classes.\n * These objects provide safe, standard methods to redefine or delete existing functions/classes\n * as well as define new custom functions/classes to be used in a plot.\n *\n * @namespace Singletons\n */\n\n\n/*\n * The Collection of \"Known\" Data Sources. This registry is used internally by the `DataSources` class\n * @class\n * @static\n */\nLocusZoom.KnownDataSources = (function() {\n /** @lends LocusZoom.KnownDataSources */\n var obj = {};\n /* @member {function[]} */\n var sources = [];\n\n var findSourceByName = function(x) {\n for(var i = 0; i < sources.length; i++) {\n if (!sources[i].SOURCE_NAME) {\n throw new Error('KnownDataSources at position ' + i + \" does not have a 'SOURCE_NAME' static property\");\n }\n if (sources[i].SOURCE_NAME === x) {\n return sources[i];\n }\n }\n return null;\n };\n\n /**\n * Identify the datasource associated with a given name\n * @param {String} name\n * @returns {function} The constructor for the data source; will usually extend `Data.Source`\n */\n obj.get = function(name) {\n return findSourceByName(name);\n };\n\n /**\n * Register a data source constructor so that it may be located by name\n * @param {function} source A constructor function for a data source; will usually extend `Data.Source`,\n * and should have a `SOURCE_NAME` property\n */\n obj.add = function(source) {\n if (!source.SOURCE_NAME) {\n console.warn('Data source added does not have a SOURCE_NAME');\n }\n sources.push(source);\n };\n\n /**\n * Create a custom source type that extends the behavior of an existing source, and registers that\n * source by the provided name\n * @param {String} parent_name The name of a previously registered data source type to use as a template\n * @param {String} source_name The new name to use when registering this data source\n * @param {Object} overrides An object of additional properties and methods to add/override behavior\n * @returns {LocusZoom.Data.Source} The newly defined class for this source\n */\n obj.extend = function(parent_name, source_name, overrides) {\n var parent = findSourceByName(parent_name);\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered data source');\n }\n if (!source_name) {\n throw new Error('Must provide a name for the new data source');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n child.SOURCE_NAME = source_name;\n sources.push(child);\n return child;\n };\n\n /** @deprecated */\n obj.push = function(source) {\n console.warn('Warning: KnownDataSources.push() is deprecated. Use .add() instead');\n obj.add(source);\n };\n\n /**\n * List the names of all registered datasources\n * @returns {String[]}\n */\n obj.list = function() {\n return sources.map(function(x) {return x.SOURCE_NAME;});\n };\n\n /**\n * Create a datasource instance\n * @param {String} name The name of the desired datasource to instantiate (must be defined in the registry)\n * @returns {LocusZoom.Data.Source}\n */\n obj.create = function(name) {\n //create new object (pass additional parameters to constructor)\n var newObj = findSourceByName(name);\n if (newObj) {\n var params = arguments;\n params[0] = null;\n return new (Function.prototype.bind.apply(newObj, params));\n } else {\n throw new Error('Unable to find data source for name: ' + name);\n }\n };\n\n /**\n * Get the array of all registered constructors\n * Generally only used for unit tests internally\n * @private\n * @returns {function[]}\n */\n obj.getAll = function() {\n return sources;\n };\n\n /**\n * Register an entire collection of data sources\n * Generally only used for unit tests internally\n * @private\n * @param {function[]} x An array of datasource constructors\n */\n obj.setAll = function(x) {\n sources = x;\n };\n\n /**\n * Unregister all known data sources\n * Generally only used for unit tests internally\n * @private\n */\n obj.clear = function() {\n sources = [];\n };\n\n return obj;\n})();\n\n/**************************\n * Transformation Functions\n *\n * Singleton for formatting or transforming a single input, for instance turning raw p values into negative log10 form\n * Transformation functions are chainable with a pipe on a field name, like so: \"pvalue|neglog10\"\n *\n * NOTE: Because these functions are chainable the FUNCTION is returned by get(), not the result of that function.\n *\n * All transformation functions must accept an object of parameters and a value to process.\n * @class\n */\nLocusZoom.TransformationFunctions = (function() {\n /** @lends LocusZoom.TransformationFunctions */\n var obj = {};\n var transformations = {};\n\n var getTrans = function(name) {\n if (!name) {\n return null;\n }\n var fun = transformations[name];\n if (fun) {\n return fun;\n } else {\n throw new Error('transformation ' + name + ' not found');\n }\n };\n\n //a single transformation with any parameters\n //(parameters not currently supported)\n var parseTrans = function(name) {\n return getTrans(name);\n };\n\n //a \"raw\" transformation string with a leading pipe\n //and one or more transformations\n var parseTransString = function(x) {\n var funs = [];\n var re = /\\|([^|]+)/g;\n var result;\n while((result = re.exec(x)) !== null) {\n funs.push(result[1]);\n }\n if (funs.length === 1) {\n return parseTrans(funs[0]);\n } else if (funs.length > 1) {\n return function(x) {\n var val = x;\n for(var i = 0; i < funs.length; i++) {\n val = parseTrans(funs[i])(val);\n }\n return val;\n };\n }\n return null;\n };\n\n /**\n * Retrieve a transformation function by name\n * @param {String} name The name of the transformation function to retrieve. May optionally be prefixed with a\n * pipe (`|`) when chaining multiple transformation functions.\n * @returns {function} The constructor for the transformation function\n */\n obj.get = function(name) {\n if (name && name.substring(0,1) === '|') {\n return parseTransString(name);\n } else {\n return parseTrans(name);\n }\n };\n /**\n * Internal logic that registers a transformation function\n * @protected\n * @param {String} name\n * @param {function} fn\n */\n obj.set = function(name, fn) {\n if (name.substring(0,1) === '|') {\n throw new Error('transformation name should not start with a pipe');\n } else {\n if (fn) {\n transformations[name] = fn;\n } else {\n delete transformations[name];\n }\n }\n };\n\n /**\n * Register a transformation function\n * @param {String} name\n * @param {function} fn A transformation function (should accept one argument with the value)\n */\n obj.add = function(name, fn) {\n if (transformations[name]) {\n throw new Error('transformation already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n /**\n * List the names of all registered transformation functions\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(transformations);\n };\n\n return obj;\n})();\n\n/**\n * Return the -log (base 10)\n * @function neglog10\n */\nLocusZoom.TransformationFunctions.add('neglog10', function(x) {\n if (isNaN(x) || x <= 0) { return null; }\n return -Math.log(x) / Math.LN10;\n});\n\n/**\n * Convert a number from logarithm to scientific notation. Useful for, eg, a datasource that returns -log(p) by default\n * @function logtoscinotation\n */\nLocusZoom.TransformationFunctions.add('logtoscinotation', function(x) {\n if (isNaN(x)) { return 'NaN'; }\n if (x === 0) { return '1'; }\n var exp = Math.ceil(x);\n var diff = exp - x;\n var base = Math.pow(10, diff);\n if (exp === 1) {\n return (base / 10).toFixed(4);\n } else if (exp === 2) {\n return (base / 100).toFixed(3);\n } else {\n return base.toFixed(2) + ' × 10^-' + exp;\n }\n});\n\n/**\n * Represent a number in scientific notation\n * @function scinotation\n * @param {Number} x\n * @returns {String}\n */\nLocusZoom.TransformationFunctions.add('scinotation', function(x) {\n if (isNaN(x)) { return 'NaN'; }\n if (x === 0) { return '0'; }\n\n var abs = Math.abs(x);\n var log;\n if (abs > 1) {\n log = Math.ceil(Math.log(abs) / Math.LN10);\n } else { // 0...1\n log = Math.floor(Math.log(abs) / Math.LN10);\n }\n if (Math.abs(log) <= 3) {\n return x.toFixed(3);\n } else {\n return x.toExponential(2).replace('+', '').replace('e', ' × 10^');\n }\n});\n\n/**\n * URL-encode the provided text, eg for constructing hyperlinks\n * @function urlencode\n * @param {String} str\n */\nLocusZoom.TransformationFunctions.add('urlencode', function(str) {\n return encodeURIComponent(str);\n});\n\n/**\n * HTML-escape user entered values for use in constructed HTML fragments\n *\n * For example, this filter can be used on tooltips with custom HTML display\n * @function htmlescape\n * @param {String} str HTML-escape the provided value\n */\nLocusZoom.TransformationFunctions.add('htmlescape', function(str) {\n if ( !str ) {\n return '';\n }\n str = str + '';\n\n return str.replace( /['\"<>&`]/g, function( s ) {\n switch ( s ) {\n case \"'\":\n return ''';\n case '\"':\n return '"';\n case '<':\n return '<';\n case '>':\n return '>';\n case '&':\n return '&';\n case '`':\n return '`';\n }\n });\n});\n\n/**\n * Singleton for accessing/storing functions that will convert arbitrary data points to values in a given scale\n * Useful for anything that needs to scale discretely with data (e.g. color, point size, etc.)\n *\n * A Scale Function can be thought of as a modifier to a layout directive that adds extra logic to how a piece of data\n * can be resolved to a value.\n *\n * All scale functions must accept an object of parameters and a value to process.\n * @class\n * @static\n */\nLocusZoom.ScaleFunctions = (function() {\n /** @lends LocusZoom.ScaleFunctions */\n var obj = {};\n var functions = {};\n\n /**\n * Find a scale function and return it. If parameters and values are passed, calls the function directly; otherwise\n * returns a callable.\n * @param {String} name\n * @param {Object} [parameters] Configuration parameters specific to the specified scale function\n * @param {*} [value] The value to operate on\n * @returns {*}\n */\n obj.get = function(name, parameters, value) {\n if (!name) {\n return null;\n } else if (functions[name]) {\n if (typeof parameters === 'undefined' && typeof value === 'undefined') {\n return functions[name];\n } else {\n return functions[name](parameters, value);\n }\n } else {\n throw new Error('scale function [' + name + '] not found');\n }\n };\n\n /**\n * @protected\n * @param {String} name The name of the function to set/unset\n * @param {Function} [fn] The function to register. If blank, removes this function name from the registry.\n */\n obj.set = function(name, fn) {\n if (fn) {\n functions[name] = fn;\n } else {\n delete functions[name];\n }\n };\n\n /**\n * Add a new scale function to the registry\n * @param {String} name The name of the scale function\n * @param {function} fn A scale function that accepts two parameters: an object of configuration and a value\n */\n obj.add = function(name, fn) {\n if (functions[name]) {\n throw new Error('scale function already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n\n /**\n * List the names of all registered scale functions\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(functions);\n };\n\n return obj;\n})();\n\n/**\n * Basic conditional function to evaluate the value of the input field and return based on equality.\n * @param {Object} parameters\n * @param {*} parameters.field_value The value against which to test the input value.\n * @param {*} parameters.then The value to return if the input value matches the field value\n * @param {*} parameters.else The value to return if the input value does not match the field value. Optional. If not\n * defined this scale function will return null (or value of null_value parameter, if defined) when input value fails\n * to match field_value.\n * @param {*} input value\n */\nLocusZoom.ScaleFunctions.add('if', function(parameters, input) {\n if (typeof input == 'undefined' || parameters.field_value !== input) {\n if (typeof parameters.else != 'undefined') {\n return parameters.else;\n } else {\n return null;\n }\n } else {\n return parameters.then;\n }\n});\n\n/**\n * Function to sort numerical values into bins based on numerical break points. Will only operate on numbers and\n * return null (or value of null_value parameter, if defined) if provided a non-numeric input value. Parameters:\n * @function numerical_bin\n * @param {Object} parameters\n * @param {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter. If the input value is greater than or equal to break n and less than\n * or equal to break n+1 (or break n+1 doesn't exist) then returned value is the nth entry in the values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against break points. Must be of\n * equal length to breaks parameter. Each entry n represents the value to return if the input value is greater than\n * or equal to break n and less than or equal to break n+1 (or break n+1 doesn't exist).\n * @param {*} null_value\n * @param {*} input value\n * @returns\n */\nLocusZoom.ScaleFunctions.add('numerical_bin', function(parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n if (typeof input == 'undefined' || input === null || isNaN(+input)) {\n return (parameters.null_value ? parameters.null_value : null);\n }\n var threshold = breaks.reduce(function(prev, curr) {\n if (+input < prev || (+input >= prev && +input < curr)) {\n return prev;\n } else {\n return curr;\n }\n });\n return values[breaks.indexOf(threshold)];\n});\n\n/**\n * Function to sort values of any type into bins based on direct equality testing with a list of categories.\n * Will return null if provided an input value that does not match to a listed category.\n * @function categorical_bin\n * @param {Object} parameters\n * @param {Array} parameters.categories Array of values against which to evaluate the input value. Must be of equal\n * length to values parameter. If the input value is equal to category n then returned value is the nth entry in the\n * values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against categories. Must be of equal\n * length to categories parameter. Each entry n represents the value to return if the input value is equal to the nth\n * value in the categories parameter.\n * @param {*} parameters.null_value Value to return if the input value fails to match to any categories. Optional.\n */\nLocusZoom.ScaleFunctions.add('categorical_bin', function(parameters, value) {\n if (typeof value == 'undefined' || parameters.categories.indexOf(value) === -1) {\n return (parameters.null_value ? parameters.null_value : null);\n } else {\n return parameters.values[parameters.categories.indexOf(value)];\n }\n});\n\n/**\n * Function for continuous interpolation of numerical values along a gradient with arbitrarily many break points.\n * @function interpolate\n * @parameters {Object} parameters\n * @parameters {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter and contain at least two elements. Input value will be evaluated for\n * relative position between two break points n and n+1 and the returned value will be interpolated at a relative\n * position between values n and n+1.\n * @parameters {*[]} parameters.values Array of values to interpolate and return given evaluations against break\n * points. Must be of equal length to breaks parameter and contain at least two elements. Each entry n represents\n * the value to return if the input value matches the nth entry in breaks exactly. Note that this scale function\n * uses d3.interpolate to provide for effective interpolation of many different value types, including numbers,\n * colors, shapes, etc.\n * @parameters {*} parameters.null_value\n */\nLocusZoom.ScaleFunctions.add('interpolate', function(parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n var nullval = (parameters.null_value ? parameters.null_value : null);\n if (breaks.length < 2 || breaks.length !== values.length) { return nullval; }\n if (typeof input == 'undefined' || input === null || isNaN(+input)) { return nullval; }\n if (+input <= parameters.breaks[0]) {\n return values[0];\n } else if (+input >= parameters.breaks[parameters.breaks.length - 1]) {\n return values[breaks.length - 1];\n } else {\n var upper_idx = null;\n breaks.forEach(function(brk, idx) {\n if (!idx) { return; }\n if (breaks[idx - 1] <= +input && breaks[idx] >= +input) { upper_idx = idx; }\n });\n if (upper_idx === null) { return nullval; }\n var normalized_input = (+input - breaks[upper_idx - 1]) / (breaks[upper_idx] - breaks[upper_idx - 1]);\n if (!isFinite(normalized_input)) { return nullval; }\n return d3.interpolate(values[upper_idx - 1], values[upper_idx])(normalized_input);\n }\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A Dashboard is an HTML element used for presenting arbitrary user interface components. Dashboards are anchored\n * to either the entire Plot or to individual Panels.\n *\n * Each dashboard is an HTML-based (read: not SVG) collection of components used to display information or provide\n * user interface. Dashboards can exist on entire plots, where their visibility is permanent and vertically adjacent\n * to the plot, or on individual panels, where their visibility is tied to a behavior (e.g. a mouseover) and is as\n * an overlay.\n * @class\n */\nLocusZoom.Dashboard = function(parent) {\n // parent must be a locuszoom plot or panel\n if (!(parent instanceof LocusZoom.Plot) && !(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create dashboard, parent must be a locuszoom plot or panel');\n }\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.dashboard';\n /** @member {('plot'|'panel')} */\n this.type = (this.parent instanceof LocusZoom.Plot) ? 'plot' : 'panel';\n /** @member {LocusZoom.Plot} */\n this.parent_plot = this.type === 'plot' ? this.parent : this.parent.parent;\n\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {LocusZoom.Dashboard.Component[]} */\n this.components = [];\n /**\n * The timer identifier as returned by setTimeout\n * @member {Number}\n */\n this.hide_timeout = null;\n /**\n * Whether to hide the dashboard. Can be overridden by a child component. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n\n // TODO: Return value from constructor function?\n return this.initialize();\n};\n\n/**\n * Prepare the dashboard for first use: generate all component instances for this dashboard, based on the provided\n * layout of the parent. Connects event listeners and shows/hides as appropriate.\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.initialize = function() {\n // Parse layout to generate component instances\n if (Array.isArray(this.parent.layout.dashboard.components)) {\n this.parent.layout.dashboard.components.forEach(function(layout) {\n try {\n var component = LocusZoom.Dashboard.Components.get(layout.type, layout, this);\n this.components.push(component);\n } catch (e) {\n console.warn(e);\n }\n }.bind(this));\n }\n\n // Add mouseover event handlers to show/hide panel dashboard\n if (this.type === 'panel') {\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseover.' + this.id, function() {\n clearTimeout(this.hide_timeout);\n if (!this.selector || this.selector.style('visibility') === 'hidden') { this.show(); }\n }.bind(this));\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseout.' + this.id, function() {\n clearTimeout(this.hide_timeout);\n this.hide_timeout = setTimeout(function() { this.hide(); }.bind(this), 300);\n }.bind(this));\n }\n\n return this;\n\n};\n\n/**\n * Whether to persist the dashboard. Returns true if at least one component should persist, or if the panel is engaged\n * in an active drag event.\n * @returns {boolean}\n */\nLocusZoom.Dashboard.prototype.shouldPersist = function() {\n if (this.persist) { return true; }\n var persist = false;\n // Persist if at least one component should also persist\n this.components.forEach(function(component) {\n persist = persist || component.shouldPersist();\n });\n // Persist if in a parent drag event\n persist = persist || (this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.dragging);\n return !!persist;\n};\n\n/**\n * Make the dashboard appear. If it doesn't exist yet create it, including creating/positioning all components within,\n * and make sure it is set to be visible.\n */\nLocusZoom.Dashboard.prototype.show = function() {\n if (!this.selector) {\n switch (this.type) {\n case 'plot':\n this.selector = d3.select(this.parent.svg.node().parentNode)\n .insert('div',':first-child');\n break;\n case 'panel':\n this.selector = d3.select(this.parent.parent.svg.node().parentNode)\n .insert('div', '.lz-data_layer-tooltip, .lz-dashboard-menu, .lz-curtain').classed('lz-panel-dashboard', true);\n break;\n }\n this.selector.classed('lz-dashboard', true).classed('lz-' + this.type + '-dashboard', true).attr('id', this.id);\n }\n this.components.forEach(function(component) { component.show(); });\n this.selector.style({ visibility: 'visible' });\n return this.update();\n};\n\n/**\n * Update the dashboard and rerender all child components. This can be called whenever plot state changes.\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.update = function() {\n if (!this.selector) { return this; }\n this.components.forEach(function(component) { component.update(); });\n return this.position();\n};\n\n/**\n * Position the dashboard (and child components) within the panel\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.position = function() {\n if (!this.selector) { return this; }\n // Position the dashboard itself (panel only)\n if (this.type === 'panel') {\n var page_origin = this.parent.getPageOrigin();\n var top = (page_origin.y + 3.5).toString() + 'px';\n var left = page_origin.x.toString() + 'px';\n var width = (this.parent.layout.width - 4).toString() + 'px';\n this.selector.style({ position: 'absolute', top: top, left: left, width: width });\n }\n // Recursively position components\n this.components.forEach(function(component) { component.position(); });\n return this;\n};\n\n/**\n * Hide the dashboard (make invisible but do not destroy). Will do nothing if `shouldPersist` returns true.\n *\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.hide = function() {\n if (!this.selector || this.shouldPersist()) { return this; }\n this.components.forEach(function(component) { component.hide(); });\n this.selector.style({ visibility: 'hidden' });\n return this;\n};\n\n/**\n * Completely remove dashboard and all child components. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.destroy = function(force) {\n if (typeof force == 'undefined') { force = false; }\n if (!this.selector) { return this; }\n if (this.shouldPersist() && !force) { return this; }\n this.components.forEach(function(component) { component.destroy(true); });\n this.components = [];\n this.selector.remove();\n this.selector = null;\n return this;\n};\n\n/**\n *\n * A dashboard component is an empty div rendered on a dashboard that can display custom\n * html of user interface elements. LocusZoom.Dashboard.Components is a singleton used to\n * define and manage an extendable collection of dashboard components.\n * (e.g. by LocusZoom.Dashboard.Components.add())\n * @class\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @param {('left'|'right')} [layout.position='left'] Whether to float the component left or right.\n * @param {('start'|'middle'|'end')} [layout.group_position] Buttons can optionally be gathered into a visually\n * distinctive group whose elements are closer together. If a button is identified as the start or end of a group,\n * it will be drawn with rounded corners and an extra margin of spacing from any button not part of the group.\n * For example, the region_nav_plot dashboard is a defined as a group.\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple'} [layout.color='gray'] Color scheme for the\n * component. Applies to buttons and menus.\n * @param {LocusZoom.Dashboard} parent The dashboard that contains this component\n*/\nLocusZoom.Dashboard.Component = function(layout, parent) {\n /** @member {Object} */\n this.layout = layout || {};\n if (!this.layout.color) { this.layout.color = 'gray'; }\n\n /** @member {LocusZoom.Dashboard|*} */\n this.parent = parent || null;\n /**\n * Some dashboards are attached to a panel, rather than directly to a plot\n * @member {LocusZoom.Panel|null}\n */\n this.parent_panel = null;\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n /**\n * This is a reference to either the panel or the plot, depending on what the dashboard is\n * tied to. Useful when absolutely positioning dashboard components relative to their SVG anchor.\n * @member {LocusZoom.Plot|LocusZoom.Panel}\n */\n this.parent_svg = null;\n if (this.parent instanceof LocusZoom.Dashboard) {\n // TODO: when is the immediate parent *not* a dashboard?\n if (this.parent.type === 'panel') {\n this.parent_panel = this.parent.parent;\n this.parent_plot = this.parent.parent.parent;\n this.parent_svg = this.parent_panel;\n } else {\n this.parent_plot = this.parent.parent;\n this.parent_svg = this.parent_plot;\n }\n }\n /** @member {d3.selection} */\n this.selector = null;\n /**\n * If this is an interactive component, it will contain a button or menu instance that handles the interactivity.\n * There is a 1-to-1 relationship of dashboard component to button\n * @member {null|LocusZoom.Dashboard.Component.Button}\n */\n this.button = null;\n /**\n * If any single component is marked persistent, it will bubble up to prevent automatic hide behavior on a\n * component's parent dashboard. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n if (!this.layout.position) { this.layout.position = 'left'; }\n\n // TODO: Return value in constructor\n return this;\n};\n/**\n * Perform all rendering of component, including toggling visibility to true. Will initialize and create SVG element\n * if necessary, as well as updating with new data and performing layout actions.\n */\nLocusZoom.Dashboard.Component.prototype.show = function() {\n if (!this.parent || !this.parent.selector) { return; }\n if (!this.selector) {\n var group_position = (['start','middle','end'].indexOf(this.layout.group_position) !== -1 ? ' lz-dashboard-group-' + this.layout.group_position : '');\n this.selector = this.parent.selector.append('div')\n .attr('class', 'lz-dashboard-' + this.layout.position + group_position);\n if (this.layout.style) { this.selector.style(this.layout.style); }\n if (typeof this.initialize == 'function') { this.initialize(); }\n }\n if (this.button && this.button.status === 'highlighted') { this.button.menu.show(); }\n this.selector.style({ visibility: 'visible' });\n this.update();\n return this.position();\n};\n/**\n * Update the dashboard component with any new data or plot state as appropriate. This method performs all\n * necessary rendering steps.\n */\nLocusZoom.Dashboard.Component.prototype.update = function() { /* stub */ };\n/**\n * Place the component correctly in the plot\n * @returns {LocusZoom.Dashboard.Component}\n */\nLocusZoom.Dashboard.Component.prototype.position = function() {\n if (this.button) { this.button.menu.position(); }\n return this;\n};\n/**\n * Determine whether the component should persist (will bubble up to parent dashboard)\n * @returns {boolean}\n */\nLocusZoom.Dashboard.Component.prototype.shouldPersist = function() {\n if (this.persist) { return true; }\n if (this.button && this.button.persist) { return true; }\n return false;\n};\n/**\n * Toggle visibility to hidden, unless marked as persistent\n * @returns {LocusZoom.Dashboard.Component}\n */\nLocusZoom.Dashboard.Component.prototype.hide = function() {\n if (!this.selector || this.shouldPersist()) { return this; }\n if (this.button) { this.button.menu.hide(); }\n this.selector.style({ visibility: 'hidden' });\n return this;\n};\n/**\n * Completely remove component and button. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.Component.prototype.destroy = function(force) {\n if (typeof force == 'undefined') { force = false; }\n if (!this.selector) { return this; }\n if (this.shouldPersist() && !force) { return this; }\n if (this.button && this.button.menu) { this.button.menu.destroy(); }\n this.selector.remove();\n this.selector = null;\n this.button = null;\n return this;\n};\n\n/**\n * Singleton registry of all known components\n * @class\n * @static\n */\nLocusZoom.Dashboard.Components = (function() {\n /** @lends LocusZoom.Dashboard.Components */\n var obj = {};\n var components = {};\n\n /**\n * Create a new component instance by name\n * @param {String} name The string identifier of the desired component\n * @param {Object} layout The layout to use to create the component\n * @param {LocusZoom.Dashboard} parent The containing dashboard to use when creating the component\n * @returns {LocusZoom.Dashboard.Component}\n */\n obj.get = function(name, layout, parent) {\n if (!name) {\n return null;\n } else if (components[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for dashboard component [' + name + ']');\n } else {\n return new components[name](layout, parent);\n }\n } else {\n throw new Error('dashboard component [' + name + '] not found');\n }\n };\n /**\n * Add a new component constructor to the registry and ensure that it extends the correct parent class\n * @protected\n * @param name\n * @param component\n */\n obj.set = function(name, component) {\n if (component) {\n if (typeof component != 'function') {\n throw new Error('unable to set dashboard component [' + name + '], argument provided is not a function');\n } else {\n components[name] = component;\n components[name].prototype = new LocusZoom.Dashboard.Component();\n }\n } else {\n delete components[name];\n }\n };\n\n /**\n * Register a new component constructor by name\n * @param {String} name\n * @param {function} component The component constructor\n */\n obj.add = function(name, component) {\n if (components[name]) {\n throw new Error('dashboard component already exists with name: ' + name);\n } else {\n obj.set(name, component);\n }\n };\n\n /**\n * List the names of all registered components\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(components);\n };\n\n return obj;\n})();\n\n/**\n * Plots and panels may have a \"dashboard\" element suited for showing HTML components that may be interactive.\n * When components need to incorporate a generic button, or additionally a button that generates a menu, this\n * class provides much of the necessary framework.\n * @class\n * @param {LocusZoom.Dashboard.Component} parent\n */\nLocusZoom.Dashboard.Component.Button = function(parent) {\n\n if (!(parent instanceof LocusZoom.Dashboard.Component)) {\n throw new Error('Unable to create dashboard component button, invalid parent');\n }\n /** @member {LocusZoom.Dashboard.Component} */\n this.parent = parent;\n /** @member {LocusZoom.Dashboard.Panel} */\n this.parent_panel = this.parent.parent_panel;\n /** @member {LocusZoom.Dashboard.Plot} */\n this.parent_plot = this.parent.parent_plot;\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent_svg = this.parent.parent_svg;\n\n /** @member {LocusZoom.Dashboard|null|*} */\n this.parent_dashboard = this.parent.parent;\n /** @member {d3.selection} */\n this.selector = null;\n\n /**\n * Tag to use for the button (default: a)\n * @member {String}\n */\n this.tag = 'a';\n\n /**\n * TODO This method does not appear to be used anywhere\n * @param {String} tag\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTag = function(tag) {\n if (typeof tag != 'undefined') { this.tag = tag.toString(); }\n return this;\n };\n\n /**\n * HTML for the button to show.\n * @protected\n * @member {String}\n */\n this.html = '';\n /**\n * Specify the HTML content of this button.\n * WARNING: The string provided will be inserted into the document as raw markup; XSS mitigation is the\n * responsibility of each button implementation.\n * @param {String} html\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setHtml = function(html) {\n if (typeof html != 'undefined') { this.html = html.toString(); }\n return this;\n };\n /**\n * @deprecated since 0.5.6; use setHtml instead\n */\n this.setText = this.setHtml;\n\n /**\n * Mouseover title text for the button to show\n * @protected\n * @member {String}\n */\n this.title = '';\n /**\n * Set the mouseover title text for the button (if any)\n * @param {String} title Simple text to display\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTitle = function(title) {\n if (typeof title != 'undefined') { this.title = title.toString(); }\n return this;\n };\n\n /**\n * Color of the button\n * @member {String}\n */\n this.color = 'gray';\n\n /**\n * Set the color associated with this button\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple')} color Any selection not in the preset list\n * will be replaced with gray.\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setColor = function(color) {\n if (typeof color != 'undefined') {\n if (['gray', 'red', 'orange', 'yellow', 'green', 'blue', 'purple'].indexOf(color) !== -1) { this.color = color; }\n else { this.color = 'gray'; }\n }\n return this;\n };\n\n /**\n * Hash of arbitrary button styles to apply as {name: value} entries\n * @protected\n * @member {Object}\n */\n this.style = {};\n /**\n * Set a collection of custom styles to be used by the button\n * @param {Object} style Hash of {name:value} entries\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setStyle = function(style) {\n if (typeof style != 'undefined') { this.style = style; }\n return this;\n };\n\n //\n /**\n * Method to generate a CSS class string\n * @returns {string}\n */\n this.getClass = function() {\n var group_position = (['start','middle','end'].indexOf(this.parent.layout.group_position) !== -1 ? ' lz-dashboard-button-group-' + this.parent.layout.group_position : '');\n return 'lz-dashboard-button lz-dashboard-button-' + this.color + (this.status ? '-' + this.status : '') + group_position;\n };\n\n // Permanence\n /**\n * Track internal state on whether to keep showing the button/ menu contents at the moment\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n /**\n * Configuration when defining a button: track whether this component should be allowed to keep open\n * menu/button contents in response to certain events\n * @protected\n * @member {Boolean}\n */\n this.permanent = false;\n /**\n * Allow code to change whether the button is allowed to be `permanent`\n * @param {boolean} bool\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setPermanent = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n this.permanent = bool;\n if (this.permanent) { this.persist = true; }\n return this;\n };\n /**\n * Determine whether the button/menu contents should persist in response to a specific event\n * @returns {Boolean}\n */\n this.shouldPersist = function() {\n return this.permanent || this.persist;\n };\n\n /**\n * Button status (highlighted / disabled/ etc)\n * @protected\n * @member {String}\n */\n this.status = '';\n /**\n * Change button state\n * @param {('highlighted'|'disabled'|'')} status\n */\n this.setStatus = function(status) {\n if (typeof status != 'undefined' && ['', 'highlighted', 'disabled'].indexOf(status) !== -1) { this.status = status; }\n return this.update();\n };\n /**\n * Toggle whether the button is highlighted\n * @param {boolean} bool If provided, explicitly set highlighted state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.highlight = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n if (bool) { return this.setStatus('highlighted'); }\n else if (this.status === 'highlighted') { return this.setStatus(''); }\n return this;\n };\n /**\n * Toggle whether the button is disabled\n * @param {boolean} bool If provided, explicitly set disabled state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.disable = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n if (bool) { return this.setStatus('disabled'); }\n else if (this.status === 'disabled') { return this.setStatus(''); }\n return this;\n };\n\n // Mouse events\n /** @member {function} */\n this.onmouseover = function() {};\n this.setOnMouseover = function(onmouseover) {\n if (typeof onmouseover == 'function') { this.onmouseover = onmouseover; }\n else { this.onmouseover = function() {}; }\n return this;\n };\n /** @member {function} */\n this.onmouseout = function() {};\n this.setOnMouseout = function(onmouseout) {\n if (typeof onmouseout == 'function') { this.onmouseout = onmouseout; }\n else { this.onmouseout = function() {}; }\n return this;\n };\n /** @member {function} */\n this.onclick = function() {};\n this.setOnclick = function(onclick) {\n if (typeof onclick == 'function') { this.onclick = onclick; }\n else { this.onclick = function() {}; }\n return this;\n };\n\n // Primary behavior functions\n /**\n * Show the button, including creating DOM elements if necessary for first render\n */\n this.show = function() {\n if (!this.parent) { return; }\n if (!this.selector) {\n this.selector = this.parent.selector.append(this.tag).attr('class', this.getClass());\n }\n return this.update();\n };\n /**\n * Hook for any actions or state cleanup to be performed before rerendering\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.preUpdate = function() { return this; };\n /**\n * Update button state and contents, and fully rerender\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.update = function() {\n if (!this.selector) { return this; }\n this.preUpdate();\n this.selector\n .attr('class', this.getClass())\n .attr('title', this.title).style(this.style)\n .on('mouseover', (this.status === 'disabled') ? null : this.onmouseover)\n .on('mouseout', (this.status === 'disabled') ? null : this.onmouseout)\n .on('click', (this.status === 'disabled') ? null : this.onclick)\n .html(this.html);\n this.menu.update();\n this.postUpdate();\n return this;\n };\n /**\n * Hook for any behavior to be added/changed after the button has been re-rendered\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.postUpdate = function() { return this; };\n /**\n * Hide the button by removing it from the DOM (may be overridden by current persistence setting)\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.hide = function() {\n if (this.selector && !this.shouldPersist()) {\n this.selector.remove();\n this.selector = null;\n }\n return this;\n };\n\n /**\n * Button Menu Object\n * The menu is an HTML overlay that can appear below a button. It can contain arbitrary HTML and\n * has logic to be automatically positioned and sized to behave more or less like a dropdown menu.\n * @member {Object}\n */\n this.menu = {\n outer_selector: null,\n inner_selector: null,\n scroll_position: 0,\n hidden: true,\n /**\n * Show the button menu, including setting up any DOM elements needed for first rendering\n */\n show: function() {\n if (!this.menu.outer_selector) {\n this.menu.outer_selector = d3.select(this.parent_plot.svg.node().parentNode).append('div')\n .attr('class', 'lz-dashboard-menu lz-dashboard-menu-' + this.color)\n .attr('id', this.parent_svg.getBaseId() + '.dashboard.menu');\n this.menu.inner_selector = this.menu.outer_selector.append('div')\n .attr('class', 'lz-dashboard-menu-content');\n this.menu.inner_selector.on('scroll', function() {\n this.menu.scroll_position = this.menu.inner_selector.node().scrollTop;\n }.bind(this));\n }\n this.menu.outer_selector.style({ visibility: 'visible' });\n this.menu.hidden = false;\n return this.menu.update();\n }.bind(this),\n /**\n * Update the rendering of the menu\n */\n update: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.populate(); // This function is stubbed for all buttons by default and custom implemented in component definition\n if (this.menu.inner_selector) { this.menu.inner_selector.node().scrollTop = this.menu.scroll_position; }\n return this.menu.position();\n }.bind(this),\n position: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n // Unset any explicitly defined outer selector height so that menus dynamically shrink if content is removed\n this.menu.outer_selector.style({ height: null });\n var padding = 3;\n var scrollbar_padding = 20;\n var menu_height_padding = 14; // 14: 2x 6px padding, 2x 1px border\n var page_origin = this.parent_svg.getPageOrigin();\n var page_scroll_top = document.documentElement.scrollTop || document.body.scrollTop;\n var container_offset = this.parent_plot.getContainerOffset();\n var dashboard_client_rect = this.parent_dashboard.selector.node().getBoundingClientRect();\n var button_client_rect = this.selector.node().getBoundingClientRect();\n var menu_client_rect = this.menu.outer_selector.node().getBoundingClientRect();\n var total_content_height = this.menu.inner_selector.node().scrollHeight;\n var top = 0; var left = 0;\n if (this.parent_dashboard.type === 'panel') {\n top = (page_origin.y + dashboard_client_rect.height + (2 * padding));\n left = Math.max(page_origin.x + this.parent_svg.layout.width - menu_client_rect.width - padding, page_origin.x + padding);\n } else {\n top = button_client_rect.bottom + page_scroll_top + padding - container_offset.top;\n left = Math.max(button_client_rect.left + button_client_rect.width - menu_client_rect.width - container_offset.left, page_origin.x + padding);\n }\n var base_max_width = Math.max(this.parent_svg.layout.width - (2 * padding) - scrollbar_padding, scrollbar_padding);\n var container_max_width = base_max_width;\n var content_max_width = (base_max_width - (4 * padding));\n var base_max_height = Math.max(this.parent_svg.layout.height - (10 * padding) - menu_height_padding, menu_height_padding);\n var height = Math.min(total_content_height, base_max_height);\n var max_height = base_max_height;\n this.menu.outer_selector.style({\n 'top': top.toString() + 'px',\n 'left': left.toString() + 'px',\n 'max-width': container_max_width.toString() + 'px',\n 'max-height': max_height.toString() + 'px',\n 'height': height.toString() + 'px'\n });\n this.menu.inner_selector.style({ 'max-width': content_max_width.toString() + 'px' });\n this.menu.inner_selector.node().scrollTop = this.menu.scroll_position;\n return this.menu;\n }.bind(this),\n hide: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.outer_selector.style({ visibility: 'hidden' });\n this.menu.hidden = true;\n return this.menu;\n }.bind(this),\n destroy: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.inner_selector.remove();\n this.menu.outer_selector.remove();\n this.menu.inner_selector = null;\n this.menu.outer_selector = null;\n return this.menu;\n }.bind(this),\n /**\n * Internal method definition\n * By convention populate() does nothing and should be reimplemented with each dashboard button definition\n * Reimplement by way of Dashboard.Component.Button.menu.setPopulate to define the populate method and hook\n * up standard menu click-toggle behavior prototype.\n * @protected\n */\n populate: function() { /* stub */ }.bind(this),\n /**\n * Define how the menu is populated with items, and set up click and display properties as appropriate\n * @public\n */\n setPopulate: function(menu_populate_function) {\n if (typeof menu_populate_function == 'function') {\n this.menu.populate = menu_populate_function;\n this.setOnclick(function() {\n if (this.menu.hidden) {\n this.menu.show();\n this.highlight().update();\n this.persist = true;\n } else {\n this.menu.hide();\n this.highlight(false).update();\n if (!this.permanent) { this.persist = false; }\n }\n }.bind(this));\n } else {\n this.setOnclick();\n }\n return this;\n }.bind(this)\n };\n\n};\n\n/**\n * Renders arbitrary text with title formatting\n * @class LocusZoom.Dashboard.Components.title\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.title Text to render\n */\nLocusZoom.Dashboard.Components.add('title', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.show = function() {\n if (!this.div_selector) {\n this.div_selector = this.parent.selector.append('div')\n .attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position);\n this.title_selector = this.div_selector.append('h3');\n }\n return this.update();\n };\n this.update = function() {\n var title = layout.title.toString();\n if (this.layout.subtitle) { title += ' ' + this.layout.subtitle + ''; }\n this.title_selector.html(title);\n return this;\n };\n});\n\n/**\n * Renders text to display the current dimensions of the plot. Automatically updated as plot dimensions change\n * @class LocusZoom.Dashboard.Components.dimensions\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('dimensions', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n var display_width = this.parent_plot.layout.width.toString().indexOf('.') === -1 ? this.parent_plot.layout.width : this.parent_plot.layout.width.toFixed(2);\n var display_height = this.parent_plot.layout.height.toString().indexOf('.') === -1 ? this.parent_plot.layout.height : this.parent_plot.layout.height.toFixed(2);\n this.selector.html(display_width + 'px × ' + display_height + 'px');\n if (layout.class) { this.selector.attr('class', layout.class); }\n if (layout.style) { this.selector.style(layout.style); }\n return this;\n };\n});\n\n/**\n * Display the current scale of the genome region displayed in the plot, as defined by the difference between\n * `state.end` and `state.start`.\n * @class LocusZoom.Dashboard.Components.region_scale\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('region_scale', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (!isNaN(this.parent_plot.state.start) && !isNaN(this.parent_plot.state.end)\n && this.parent_plot.state.start !== null && this.parent_plot.state.end !== null) {\n this.selector.style('display', null);\n this.selector.html(LocusZoom.positionIntToString(this.parent_plot.state.end - this.parent_plot.state.start, null, true));\n } else {\n this.selector.style('display', 'none');\n }\n if (layout.class) { this.selector.attr('class', layout.class); }\n if (layout.style) { this.selector.style(layout.style); }\n return this;\n };\n});\n\n/**\n * Button to export current plot to an SVG image\n * @class LocusZoom.Dashboard.Components.download\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Download Image\"]\n * @param {string} [layout.button_title=\"Download image of the current plot as locuszoom.svg\"]\n * @param {string} [layout.filename=\"locuszoom.svg\"] The default filename to use when saving the image\n */\nLocusZoom.Dashboard.Components.add('download', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html || 'Download Image')\n .setTitle(layout.button_title || 'Download image of the current plot as locuszoom.svg')\n .setOnMouseover(function() {\n this.button.selector\n .classed('lz-dashboard-button-gray-disabled', true)\n .html('Preparing Image');\n this.generateBase64SVG().then(function(url) {\n var old = this.button.selector.attr('href');\n if (old) { URL.revokeObjectURL(old); } // Clean up old url instance to prevent memory leaks\n this.button.selector\n .attr('href', url)\n .classed('lz-dashboard-button-gray-disabled', false)\n .classed('lz-dashboard-button-gray-highlighted', true)\n .html(layout.button_html || 'Download Image');\n }.bind(this));\n }.bind(this))\n .setOnMouseout(function() {\n this.button.selector.classed('lz-dashboard-button-gray-highlighted', false);\n }.bind(this));\n this.button.show();\n this.button.selector.attr('href-lang', 'image/svg+xml').attr('download', layout.filename || 'locuszoom.svg');\n return this;\n };\n this.css_string = '';\n for (var stylesheet in Object.keys(document.styleSheets)) {\n if ( document.styleSheets[stylesheet].href !== null\n && document.styleSheets[stylesheet].href.indexOf('locuszoom.css') !== -1) {\n // TODO: \"Download image\" button will render the image incorrectly if the stylesheet has been renamed or concatenated\n LocusZoom.createCORSPromise('GET', document.styleSheets[stylesheet].href)\n .then(function(response) {\n this.css_string = response.replace(/[\\r\\n]/g,' ').replace(/\\s+/g,' ');\n if (this.css_string.indexOf('/* ! LocusZoom HTML Styles */')) {\n this.css_string = this.css_string.substring(0, this.css_string.indexOf('/* ! LocusZoom HTML Styles */'));\n }\n }.bind(this));\n break;\n }\n }\n this.generateBase64SVG = function() {\n return new Promise(function (resolve, reject) {\n // Insert a hidden div, clone the node into that so we can modify it with d3\n var container = this.parent.selector.append('div').style('display', 'none')\n .html(this.parent_plot.svg.node().outerHTML);\n // Remove unnecessary elements\n container.selectAll('g.lz-curtain').remove();\n container.selectAll('g.lz-mouse_guide').remove();\n // Convert units on axis tick dy attributes from ems to pixels\n container.selectAll('g.tick text').each(function() {\n var dy = +(d3.select(this).attr('dy').substring(-2).slice(0,-2)) * 10;\n d3.select(this).attr('dy', dy);\n });\n // Pull the svg into a string and add the contents of the locuszoom stylesheet\n // Don't add this with d3 because it will escape the CDATA declaration incorrectly\n var initial_html = d3.select(container.select('svg').node().parentNode).html();\n var style_def = '';\n var insert_at = initial_html.indexOf('>') + 1;\n initial_html = initial_html.slice(0,insert_at) + style_def + initial_html.slice(insert_at);\n // Delete the container node\n container.remove();\n // Create an object URL based on the rendered markup\n var content = new Blob([initial_html], { type: 'image/svg+xml' });\n resolve(URL.createObjectURL(content));\n }.bind(this));\n };\n});\n\n/**\n * Button to remove panel from plot.\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.remove_panel\n * @augments LocusZoom.Dashboard.Component\n * @param {Boolean} [layout.suppress_confirm=false] If true, removes the panel without prompting user for confirmation\n */\nLocusZoom.Dashboard.Components.add('remove_panel', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('×')\n .setTitle('Remove panel')\n .setOnclick(function() {\n if (!layout.suppress_confirm && !confirm('Are you sure you want to remove this panel? This cannot be undone!')) {\n return false;\n }\n var panel = this.parent_panel;\n panel.dashboard.hide(true);\n d3.select(panel.parent.svg.node().parentNode).on('mouseover.' + panel.getBaseId() + '.dashboard', null);\n d3.select(panel.parent.svg.node().parentNode).on('mouseout.' + panel.getBaseId() + '.dashboard', null);\n return panel.parent.removePanel(panel.id);\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Button to move panel up relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_up\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('move_panel_up', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) {\n var is_at_top = (this.parent_panel.layout.y_index === 0);\n this.button.disable(is_at_top);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('▴')\n .setTitle('Move panel up')\n .setOnclick(function() {\n this.parent_panel.moveUp();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n});\n\n/**\n * Button to move panel down relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_down\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('move_panel_down', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) {\n var is_at_bottom = (this.parent_panel.layout.y_index === this.parent_plot.panel_ids_by_y_index.length - 1);\n this.button.disable(is_at_bottom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('▾')\n .setTitle('Move panel down')\n .setOnclick(function() {\n this.parent_panel.moveDown();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n});\n\n/**\n * Button to shift plot region forwards or back by a `step` increment provided in the layout\n * @class LocusZoom.Dashboard.Components.shift_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=50000] The stepsize to change the region by\n * @param {string} [layout.button_html]\n * @param {string} [layout.button_title]\n */\nLocusZoom.Dashboard.Components.add('shift_region', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function() {};\n console.warn('Unable to add shift_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) { layout.step = 50000; }\n if (typeof layout.button_html !== 'string') { layout.button_html = layout.step > 0 ? '>' : '<'; }\n if (typeof layout.button_title !== 'string') {\n layout.button_title = 'Shift region by ' + (layout.step > 0 ? '+' : '-') + LocusZoom.positionIntToString(Math.abs(layout.step),null,true);\n }\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start + layout.step, 1),\n end: this.parent_plot.state.end + layout.step\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Zoom in or out on the plot, centered on the middle of the plot region, by the specified amount\n * @class LocusZoom.Dashboard.Components.zoom_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=0.2] The amount to zoom in by (where 1 indicates 100%)\n */\nLocusZoom.Dashboard.Components.add('zoom_region', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function() {};\n console.warn('Unable to add zoom_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) { layout.step = 0.2; }\n if (typeof layout.button_html != 'string') { layout.button_html = layout.step > 0 ? 'z–' : 'z+'; }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Zoom region ' + (layout.step > 0 ? 'out' : 'in') + ' by ' + (Math.abs(layout.step) * 100).toFixed(1) + '%';\n }\n this.update = function() {\n if (this.button) {\n var can_zoom = true;\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n if (layout.step > 0 && !isNaN(this.parent_plot.layout.max_region_scale) && current_region_scale >= this.parent_plot.layout.max_region_scale) {\n can_zoom = false;\n }\n if (layout.step < 0 && !isNaN(this.parent_plot.layout.min_region_scale) && current_region_scale <= this.parent_plot.layout.min_region_scale) {\n can_zoom = false;\n }\n this.button.disable(!can_zoom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n var zoom_factor = 1 + layout.step;\n var new_region_scale = current_region_scale * zoom_factor;\n if (!isNaN(this.parent_plot.layout.max_region_scale)) {\n new_region_scale = Math.min(new_region_scale, this.parent_plot.layout.max_region_scale);\n }\n if (!isNaN(this.parent_plot.layout.min_region_scale)) {\n new_region_scale = Math.max(new_region_scale, this.parent_plot.layout.min_region_scale);\n }\n var delta = Math.floor((new_region_scale - current_region_scale) / 2);\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start - delta, 1),\n end: this.parent_plot.state.end + delta\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Renders button with arbitrary text that, when clicked, shows a dropdown containing arbitrary HTML\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @class LocusZoom.Dashboard.Components.menu\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n * @param {string} layout.menu_html The HTML content of the dropdown menu\n */\nLocusZoom.Dashboard.Components.add('menu', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title);\n this.button.menu.setPopulate(function() {\n this.button.menu.inner_selector.html(layout.menu_html);\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Special button/menu to allow model building by tracking individual covariants. Will track a list of covariate\n * objects and store them in the special `model.covariates` field of plot `state`.\n * @class LocusZoom.Dashboard.Components.covariates_model\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n */\nLocusZoom.Dashboard.Components.add('covariates_model', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n this.initialize = function() {\n // Initialize state.model.covariates\n this.parent_plot.state.model = this.parent_plot.state.model || {};\n this.parent_plot.state.model.covariates = this.parent_plot.state.model.covariates || [];\n // Create an object at the plot level for easy access to interface methods in custom client-side JS\n /**\n * When a covariates model dashboard element is present, create (one) object at the plot level that exposes\n * component data and state for custom interactions with other plot elements.\n * @class LocusZoom.Plot.CovariatesModel\n */\n this.parent_plot.CovariatesModel = {\n /** @member {LocusZoom.Dashboard.Component.Button} */\n button: this,\n /**\n * Add an element to the model and show a representation of it in the dashboard component menu. If the\n * element is already part of the model, do nothing (to avoid adding duplicates).\n * When plot state is changed, this will automatically trigger requests for new data accordingly.\n * @param {string|object} element_reference Can be any value that can be put through JSON.stringify()\n * to create a serialized representation of itself.\n */\n add: function(element_reference) {\n var element = JSON.parse(JSON.stringify(element_reference));\n if (typeof element_reference == 'object' && typeof element.html != 'string') {\n element.html = ( (typeof element_reference.toHTML == 'function') ? element_reference.toHTML() : element_reference.toString());\n }\n // Check if the element is already in the model covariates array and return if it is.\n for (var i = 0; i < this.state.model.covariates.length; i++) {\n if (JSON.stringify(this.state.model.covariates[i]) === JSON.stringify(element)) {\n return this;\n }\n }\n this.state.model.covariates.push(element);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Remove an element from `state.model.covariates` (and from the dashboard component menu's\n * representation of the state model). When plot state is changed, this will automatically trigger\n * requests for new data accordingly.\n * @param {number} idx Array index of the element, in the `state.model.covariates array`.\n */\n removeByIdx: function(idx) {\n if (typeof this.state.model.covariates[idx] == 'undefined') {\n throw new Error('Unable to remove model covariate, invalid index: ' + idx.toString());\n }\n this.state.model.covariates.splice(idx, 1);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Empty the `state.model.covariates` array (and dashboard component menu representation thereof) of all\n * elements. When plot state is changed, this will automatically trigger requests for new data accordingly\n */\n removeAll: function() {\n this.state.model.covariates = [];\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Manually trigger the update methods on the dashboard component's button and menu elements to force\n * display of most up-to-date content. Can be used to force the dashboard to reflect changes made, eg if\n * modifying `state.model.covariates` directly instead of via `plot.CovariatesModel`\n */\n updateComponent: function() {\n this.button.update();\n this.button.menu.update();\n }.bind(this)\n };\n }.bind(this);\n\n this.update = function() {\n\n if (this.button) { return this; }\n\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.button.menu.populate();\n }.bind(this));\n\n this.button.menu.setPopulate(function() {\n var selector = this.button.menu.inner_selector;\n selector.html('');\n // General model HTML representation\n if (typeof this.parent_plot.state.model.html != 'undefined') {\n selector.append('div').html(this.parent_plot.state.model.html);\n }\n // Model covariates table\n if (!this.parent_plot.state.model.covariates.length) {\n selector.append('i').html('no covariates in model');\n } else {\n selector.append('h5').html('Model Covariates (' + this.parent_plot.state.model.covariates.length + ')');\n var table = selector.append('table');\n this.parent_plot.state.model.covariates.forEach(function(covariate, idx) {\n var html = ( (typeof covariate == 'object' && typeof covariate.html == 'string') ? covariate.html : covariate.toString() );\n var row = table.append('tr');\n row.append('td').append('button')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color)\n .style({ 'margin-left': '0em' })\n .on('click', function() {\n this.parent_plot.CovariatesModel.removeByIdx(idx);\n }.bind(this))\n .html('×');\n row.append('td').html(html);\n }.bind(this));\n selector.append('button')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color)\n .style({ 'margin-left': '4px' }).html('× Remove All Covariates')\n .on('click', function() {\n this.parent_plot.CovariatesModel.removeAll();\n }.bind(this));\n }\n }.bind(this));\n\n this.button.preUpdate = function() {\n var html = 'Model';\n if (this.parent_plot.state.model.covariates.length) {\n var cov = this.parent_plot.state.model.covariates.length > 1 ? 'covariates' : 'covariate';\n html += ' (' + this.parent_plot.state.model.covariates.length + ' ' + cov + ')';\n }\n this.button.setHtml(html).disable(false);\n }.bind(this);\n\n this.button.show();\n\n return this;\n };\n});\n\n/**\n * Button to toggle split tracks\n * @class LocusZoom.Dashboard.Components.toggle_split_tracks\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('toggle_split_tracks', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (!layout.data_layer_id) { layout.data_layer_id = 'intervals'; }\n if (!this.parent_panel.data_layers[layout.data_layer_id]) {\n throw new Error('Dashboard toggle split tracks component missing valid data layer ID');\n }\n this.update = function() {\n var data_layer = this.parent_panel.data_layers[layout.data_layer_id];\n var html = data_layer.layout.split_tracks ? 'Merge Tracks' : 'Split Tracks';\n if (this.button) {\n this.button.setHtml(html);\n this.button.show();\n this.parent.position();\n return this;\n } else {\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(html)\n .setTitle('Toggle whether tracks are split apart or merged together')\n .setOnclick(function() {\n data_layer.toggleSplitTracks();\n if (this.scale_timeout) { clearTimeout(this.scale_timeout); }\n var timeout = data_layer.layout.transition ? +data_layer.layout.transition.duration || 0 : 0;\n this.scale_timeout = setTimeout(function() {\n this.parent_panel.scaleHeightToData();\n this.parent_plot.positionPanels();\n }.bind(this), timeout);\n this.update();\n }.bind(this));\n return this.update();\n }\n };\n});\n\n/**\n * Button to resize panel height to fit available data (eg when showing a list of tracks)\n * @class LocusZoom.Dashboard.Components.resize_to_data\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Resize to Data\"]\n * @param {string} [layout.button_title]\n */\nLocusZoom.Dashboard.Components.add('resize_to_data', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html || 'Resize to Data')\n .setTitle(layout.button_title || 'Automatically resize this panel to show all data available')\n .setOnclick(function() {\n this.parent_panel.scaleHeightToData();\n this.update();\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Button to toggle legend\n * @class LocusZoom.Dashboard.Components.toggle_legend\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('toggle_legend', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n var html = this.parent_panel.legend.layout.hidden ? 'Show Legend' : 'Hide Legend';\n if (this.button) {\n this.button.setHtml(html).show();\n this.parent.position();\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setTitle('Show or hide the legend for this panel')\n .setOnclick(function() {\n this.parent_panel.legend.layout.hidden = !this.parent_panel.legend.layout.hidden;\n this.parent_panel.legend.render();\n this.update();\n }.bind(this));\n return this.update();\n };\n});\n\n/**\n * Menu for manipulating multiple data layers in a single panel: show/hide, change order, etc.\n * @class LocusZoom.Dashboard.Components.data_layers\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('data_layers', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n this.update = function() {\n\n if (typeof layout.button_html != 'string') { layout.button_html = 'Data Layers'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Manipulate Data Layers (sort, dim, show/hide, etc.)'; }\n\n if (this.button) { return this; }\n\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.button.menu.populate();\n }.bind(this));\n\n this.button.menu.setPopulate(function() {\n this.button.menu.inner_selector.html('');\n var table = this.button.menu.inner_selector.append('table');\n this.parent_panel.data_layer_ids_by_z_index.slice().reverse().forEach(function(id, idx) {\n var data_layer = this.parent_panel.data_layers[id];\n var name = (typeof data_layer.layout.name != 'string') ? data_layer.id : data_layer.layout.name;\n var row = table.append('tr');\n // Layer name\n row.append('td').html(name);\n // Status toggle buttons\n layout.statuses.forEach(function(status_adj) {\n var status_idx = LocusZoom.DataLayer.Statuses.adjectives.indexOf(status_adj);\n var status_verb = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n var html, onclick, highlight;\n if (data_layer.global_statuses[status_adj]) {\n html = LocusZoom.DataLayer.Statuses.menu_antiverbs[status_idx];\n onclick = 'un' + status_verb + 'AllElements';\n highlight = '-highlighted';\n } else {\n html = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n onclick = status_verb + 'AllElements';\n highlight = '';\n }\n row.append('td').append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color + highlight)\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer[onclick](); this.button.menu.populate(); }.bind(this))\n .html(html);\n }.bind(this));\n // Sort layer buttons\n var at_top = (idx === 0);\n var at_bottom = (idx === (this.parent_panel.data_layer_ids_by_z_index.length - 1));\n var td = row.append('td');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-start lz-dashboard-button-' + this.layout.color + (at_bottom ? '-disabled' : ''))\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer.moveDown(); this.button.menu.populate(); }.bind(this))\n .html('▾').attr('title', 'Move layer down (further back)');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-middle lz-dashboard-button-' + this.layout.color + (at_top ? '-disabled' : ''))\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer.moveUp(); this.button.menu.populate(); }.bind(this))\n .html('▴').attr('title', 'Move layer up (further front)');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-end lz-dashboard-button-red')\n .style({ 'margin-left': '0em' })\n .on('click', function() {\n if (confirm('Are you sure you want to remove the ' + name + ' layer? This cannot be undone!')) {\n data_layer.parent.removeDataLayer(id);\n }\n return this.button.menu.populate();\n }.bind(this))\n .html('×').attr('title', 'Remove layer');\n }.bind(this));\n return this;\n }.bind(this));\n\n this.button.show();\n\n return this;\n };\n});\n\n/**\n * Dropdown menu allowing the user to choose between different display options for a single specific data layer\n * within a panel.\n *\n * This allows controlling how points on a datalayer can be displayed- any display options supported via the layout for the target datalayer. This includes point\n * size/shape, coloring, etc.\n *\n * This button intentionally limits display options it can control to those available on common plot types.\n * Although the list of options it sets can be overridden (to control very special custom plot types), this\n * capability should be used sparingly if at all.\n *\n * @class LocusZoom.Dashboard.Components.display_options\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Display options...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Control how plot items are displayed\"] Hover text for the toolbar button\n * @param {string} layout.layer_name Specify the datalayer that this button should affect\n * @param {string} [layout.default_config_display_name] Store the default configuration for this datalayer\n * configuration, and show a button to revert to the \"default\" (listing the human-readable display name provided)\n * @param {Array} [layout.fields_whitelist='see code'] The list of presentation fields that this button can control.\n * This can be overridden if this button needs to be used on a custom layer type with special options.\n * @typedef {{display_name: string, display: Object}} DisplayOptionsButtonConfigField\n * @param {DisplayOptionsButtonConfigField[]} layout.options Specify a label and set of layout directives associated\n * with this `display` option. Display field should include all changes to datalayer presentation options.\n */\nLocusZoom.Dashboard.Components.add('display_options', function (layout) {\n if (typeof layout.button_html != 'string') { layout.button_html = 'Display options...'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Control how plot items are displayed'; }\n\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n // List of layout fields that this button is allowed to control. This ensures that we don't override any other\n // information (like plot height etc) while changing point rendering\n var allowed_fields = layout.fields_whitelist || ['color', 'fill_opacity', 'label', 'legend',\n 'point_shape', 'point_size', 'tooltip', 'tooltip_positioning'];\n\n var dataLayer = this.parent_panel.data_layers[layout.layer_name];\n if (!dataLayer) {\n throw new Error(\"Display options could not locate the specified layer_name: '\" + layout.layer_name + \"'\");\n }\n var dataLayerLayout = dataLayer.layout;\n\n // Store default configuration for the layer as a clean deep copy, so we may revert later\n var defaultConfig = {};\n allowed_fields.forEach(function(name) {\n var configSlot = dataLayerLayout[name];\n if (configSlot !== undefined) {\n defaultConfig[name] = JSON.parse(JSON.stringify(configSlot));\n }\n });\n\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n this._selected_item = 'default';\n\n // Define the button + menu that provides the real functionality for this dashboard component\n var self = this;\n this.button = new LocusZoom.Dashboard.Component.Button(self)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 1e4).toString();\n\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n\n var menuLayout = self.layout;\n\n var renderRow = function(display_name, display_options, row_id) { // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td')\n .append('input')\n .attr({id: radioId, type: 'radio', name: 'display-option-' + uniqueID, value: row_id})\n .style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n .property('checked', (row_id === self._selected_item))\n .on('click', function () {\n // If an option is not specified in these display options, use the original defaults\n allowed_fields.forEach(function(field_name) {\n dataLayer.layout[field_name] = display_options[field_name] || defaultConfig[field_name];\n });\n\n self._selected_item = row_id;\n self.parent_panel.render();\n var legend = self.parent_panel.legend;\n if (legend) {\n legend.render();\n }\n });\n row.append('td').append('label')\n .style('font-weight', 'normal')\n .attr('for', radioId)\n .text(display_name);\n };\n // Render the \"display options\" menu: default and special custom options\n var defaultName = menuLayout.default_config_display_name || 'Default style';\n renderRow(defaultName, defaultConfig, 'default');\n menuLayout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.display, index);\n });\n return self;\n });\n\n this.update = function () {\n this.button.show();\n return this;\n };\n});\n\n\n/**\n * Dropdown menu allowing the user to set the value of a specific `state_field` in plot.state\n * This is useful for things (like datasources) that allow dynamic configuration based on global information in state\n *\n * For example, the LDLZ2 data source can use it to change LD reference population (for all panels) after render\n *\n * @class LocusZoom.Dashboard.Components.set_state\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Set option...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Choose an option to customize the plot\"] Hover text for the toolbar button\n * @param {bool} [layout.show_selected=false] Whether to append the selected value to the button label\n * @param {string} [layout.state_field] The name of the field in plot.state that will be set by this button\n * @typedef {{display_name: string, value: *}} SetStateOptionsConfigField\n * @param {SetStateOptionsConfigField[]} layout.options Specify human labels and associated values for the dropdown menu\n */\nLocusZoom.Dashboard.Components.add('set_state', function (layout) {\n var self = this;\n if (typeof layout.button_html != 'string') { layout.button_html = 'Set option...'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Choose an option to customize the plot'; }\n\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n if (this.parent_panel) {\n throw new Error('This widget is designed to set global options, so it can only be used at the top (plot) level');\n }\n if (!layout.state_field) {\n throw new Error('Must specify the `state_field` that this widget controls');\n }\n\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n // The first option listed is automatically assumed to be the default, unless a value exists in plot.state\n this._selected_item = this.parent_plot.state[layout.state_field] || layout.options[0].value;\n if (!layout.options.find(function(item) { return item.value === self._selected_item; })) {\n // Check only gets run at widget creation, but generally this widget is assumed to be an exclusive list of options\n throw new Error('There is an existing state value that does not match the known values in this widget');\n }\n\n // Define the button + menu that provides the real functionality for this dashboard component\n this.button = new LocusZoom.Dashboard.Component.Button(self)\n .setColor(layout.color)\n .setHtml(layout.button_html + (layout.show_selected ? this._selected_item : ''))\n .setTitle(layout.button_title)\n .setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 1e4).toString();\n\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n\n var renderRow = function(display_name, value, row_id) { // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td')\n .append('input')\n .attr({id: radioId, type: 'radio', name: 'set-state-' + uniqueID, value: row_id})\n .style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n .property('checked', (value === self._selected_item))\n .on('click', function () {\n var new_state = {};\n new_state[layout.state_field] = value;\n self._selected_item = value;\n self.parent_plot.applyState(new_state);\n self.button.setHtml(layout.button_html + (layout.show_selected ? self._selected_item : ''));\n });\n row.append('td').append('label')\n .style('font-weight', 'normal')\n .attr('for', radioId)\n .text(display_name);\n };\n layout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.value, index);\n });\n return self;\n });\n\n this.update = function () {\n this.button.show();\n return this;\n };\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * An SVG object used to display contextual information about a panel.\n * Panel layouts determine basic features of a legend - its position in the panel, orientation, title, etc.\n * Layouts of child data layers of the panel determine the actual content of the legend.\n *\n * @class\n * @param {LocusZoom.Panel} parent\n*/\nLocusZoom.Legend = function(parent) {\n if (!(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create legend, parent must be a locuszoom panel');\n }\n /** @member {LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.legend';\n\n this.parent.layout.legend = LocusZoom.Layouts.merge(this.parent.layout.legend || {}, LocusZoom.Legend.DefaultLayout);\n /** @member {Object} */\n this.layout = this.parent.layout.legend;\n\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {d3.selection} */\n this.background_rect = null;\n /** @member {d3.selection[]} */\n this.elements = [];\n /**\n * SVG selector for the group containing all elements in the legend\n * @protected\n * @member {d3.selection|null}\n */\n this.elements_group = null;\n\n /**\n * TODO: Not sure if this property is used; the external-facing methods are setting `layout.hidden` instead. Tentatively mark deprecated.\n * @deprecated\n * @protected\n * @member {Boolean}\n */\n this.hidden = false;\n\n // TODO Revisit constructor return value; see https://stackoverflow.com/a/3350364/1422268\n return this.render();\n};\n\n/**\n * The default layout used by legends (used internally)\n * @protected\n * @member {Object}\n */\nLocusZoom.Legend.DefaultLayout = {\n orientation: 'vertical',\n origin: { x: 0, y: 0 },\n width: 10,\n height: 10,\n padding: 5,\n label_size: 12,\n hidden: false\n};\n\n/**\n * Render the legend in the parent panel\n */\nLocusZoom.Legend.prototype.render = function() {\n\n // Get a legend group selector if not yet defined\n if (!this.selector) {\n this.selector = this.parent.svg.group.append('g')\n .attr('id', this.parent.getBaseId() + '.legend').attr('class', 'lz-legend');\n }\n\n // Get a legend background rect selector if not yet defined\n if (!this.background_rect) {\n this.background_rect = this.selector.append('rect')\n .attr('width', 100).attr('height', 100).attr('class', 'lz-legend-background');\n }\n\n // Get a legend elements group selector if not yet defined\n if (!this.elements_group) {\n this.elements_group = this.selector.append('g');\n }\n\n // Remove all elements from the document and re-render from scratch\n this.elements.forEach(function(element) {\n element.remove();\n });\n this.elements = [];\n\n // Gather all elements from data layers in order (top to bottom) and render them\n var padding = +this.layout.padding || 1;\n var x = padding;\n var y = padding;\n var line_height = 0;\n this.parent.data_layer_ids_by_z_index.slice().reverse().forEach(function(id) {\n if (Array.isArray(this.parent.data_layers[id].layout.legend)) {\n this.parent.data_layers[id].layout.legend.forEach(function(element) {\n var selector = this.elements_group.append('g')\n .attr('transform', 'translate(' + x + ',' + y + ')');\n var label_size = +element.label_size || +this.layout.label_size || 12;\n var label_x = 0;\n var label_y = (label_size / 2) + (padding / 2);\n line_height = Math.max(line_height, label_size + padding);\n // Draw the legend element symbol (line, rect, shape, etc)\n if (element.shape === 'line') {\n // Line symbol\n var length = +element.length || 16;\n var path_y = (label_size / 4) + (padding / 2);\n selector.append('path').attr('class', element.class || '')\n .attr('d', 'M0,' + path_y + 'L' + length + ',' + path_y)\n .style(element.style || {});\n label_x = length + padding;\n } else if (element.shape === 'rect') {\n // Rect symbol\n var width = +element.width || 16;\n var height = +element.height || width;\n selector.append('rect').attr('class', element.class || '')\n .attr('width', width).attr('height', height)\n .attr('fill', element.color || {})\n .style(element.style || {});\n label_x = width + padding;\n line_height = Math.max(line_height, height + padding);\n } else if (d3.svg.symbolTypes.indexOf(element.shape) !== -1) {\n // Shape symbol (circle, diamond, etc.)\n var size = +element.size || 40;\n var radius = Math.ceil(Math.sqrt(size / Math.PI));\n selector.append('path').attr('class', element.class || '')\n .attr('d', d3.svg.symbol().size(size).type(element.shape))\n .attr('transform', 'translate(' + radius + ',' + (radius + (padding / 2)) + ')')\n .attr('fill', element.color || {})\n .style(element.style || {});\n label_x = (2 * radius) + padding;\n label_y = Math.max((2 * radius) + (padding / 2), label_y);\n line_height = Math.max(line_height, (2 * radius) + padding);\n }\n // Draw the legend element label\n selector.append('text').attr('text-anchor', 'left').attr('class', 'lz-label')\n .attr('x', label_x).attr('y', label_y).style({'font-size': label_size}).text(element.label);\n // Position the legend element group based on legend layout orientation\n var bcr = selector.node().getBoundingClientRect();\n if (this.layout.orientation === 'vertical') {\n y += bcr.height + padding;\n line_height = 0;\n } else {\n // Ensure this element does not exceed the panel width\n // (E.g. drop to the next line if it does, but only if it's not the only element on this line)\n var right_x = this.layout.origin.x + x + bcr.width;\n if (x > padding && right_x > this.parent.layout.width) {\n y += line_height;\n x = padding;\n selector.attr('transform', 'translate(' + x + ',' + y + ')');\n }\n x += bcr.width + (3 * padding);\n }\n // Store the element\n this.elements.push(selector);\n }.bind(this));\n }\n }.bind(this));\n\n // Scale the background rect to the elements in the legend\n var bcr = this.elements_group.node().getBoundingClientRect();\n this.layout.width = bcr.width + (2 * this.layout.padding);\n this.layout.height = bcr.height + (2 * this.layout.padding);\n this.background_rect\n .attr('width', this.layout.width)\n .attr('height', this.layout.height);\n\n // Set the visibility on the legend from the \"hidden\" flag\n // TODO: `show()` and `hide()` call a full rerender; might be able to make this more lightweight?\n this.selector.style({ visibility: this.layout.hidden ? 'hidden' : 'visible' });\n\n // TODO: Annotate return type and make consistent\n return this.position();\n};\n\n/**\n * Place the legend in position relative to the panel, as specified in the layout configuration\n * @returns {LocusZoom.Legend | null}\n * TODO: should this always be chainable?\n */\nLocusZoom.Legend.prototype.position = function() {\n if (!this.selector) { return this; }\n var bcr = this.selector.node().getBoundingClientRect();\n if (!isNaN(+this.layout.pad_from_bottom)) {\n this.layout.origin.y = this.parent.layout.height - bcr.height - +this.layout.pad_from_bottom;\n }\n if (!isNaN(+this.layout.pad_from_right)) {\n this.layout.origin.x = this.parent.layout.width - bcr.width - +this.layout.pad_from_right;\n }\n this.selector.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n};\n\n/**\n * Hide the legend (triggers a re-render)\n * @public\n */\nLocusZoom.Legend.prototype.hide = function() {\n this.layout.hidden = true;\n this.render();\n};\n\n/**\n * Show the legend (triggers a re-render)\n * @public\n */\nLocusZoom.Legend.prototype.show = function() {\n this.layout.hidden = false;\n this.render();\n};\n","/* global LocusZoom */\n'use strict';\n\nfunction validateBuildSource(class_name, build, source) {\n // Build OR Source, not both\n if ((build && source) || !(build || source)) {\n throw new Error(class_name + ' must provide a parameter specifying either \"build\" or \"source\". It should not specify both.');\n }\n // If the build isn't recognized, our APIs can't transparently select a source to match\n if (build && ['GRCh37', 'GRCh38'].indexOf(build) === -1) {\n throw new Error(class_name + ' must specify a valid genome build number');\n }\n}\n\n/**\n * LocusZoom functionality used for data parsing and retrieval\n * @namespace\n * @public\n */\nLocusZoom.Data = LocusZoom.Data || {};\n\n/**\n * Create and coordinate an ensemble of (namespaced) data source instances\n * @public\n * @class\n */\nLocusZoom.DataSources = function() {\n /** @member {Object.} */\n this.sources = {};\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.addSource = function(ns, x) {\n console.warn('Warning: .addSource() is deprecated. Use .add() instead');\n return this.add(ns, x);\n};\n\n/**\n * Add a (namespaced) datasource to the plot\n * @public\n * @param {String} ns A namespace used for fields from this data source\n * @param {LocusZoom.Data.Source|Array|null} x An instantiated datasource, or an array of arguments that can be used to\n * create a known datasource type.\n */\nLocusZoom.DataSources.prototype.add = function(ns, x) {\n // FIXME: Some existing sites create sources with arbitrary names. This leads to subtle breakage\n // of namespaced fields in layouts. To avoid breaking existing usages outright, issue a deprecation warning.\n if (ns.match(/[^A-Za-z0-9_]/)) {\n console.warn(\"Deprecation warning: source name '\" + ns + \"' should contain only alphanumeric characters or underscores. Use of other characters may break layouts, and will be disallowed in the future.\");\n }\n return this.set(ns, x);\n};\n\n/** @protected */\nLocusZoom.DataSources.prototype.set = function(ns, x) {\n if (Array.isArray(x)) {\n // If passed array of source name and options, make the source\n var dsobj = LocusZoom.KnownDataSources.create.apply(null, x);\n // Each datasource in the chain should be aware of its assigned namespace\n dsobj.source_id = ns;\n this.sources[ns] = dsobj;\n } else {\n // If passed the already-created source object\n if (x !== null) {\n x.source_id = ns;\n this.sources[ns] = x;\n } else {\n delete this.sources[ns];\n }\n }\n return this;\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.getSource = function(ns) {\n console.warn('Warning: .getSource() is deprecated. Use .get() instead');\n return this.get(ns);\n};\n\n/**\n * Return the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n * @returns {LocusZoom.Data.Source}\n */\nLocusZoom.DataSources.prototype.get = function(ns) {\n return this.sources[ns];\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.removeSource = function(ns) {\n console.warn('Warning: .removeSource() is deprecated. Use .remove() instead');\n return this.remove(ns);\n};\n\n/**\n * Remove the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n */\nLocusZoom.DataSources.prototype.remove = function(ns) {\n return this.set(ns, null);\n};\n\n/**\n * Populate a list of datasources specified as a JSON object\n * @public\n * @param {String|Object} x An object or JSON representation containing {ns: configArray} entries\n * @returns {LocusZoom.DataSources}\n */\nLocusZoom.DataSources.prototype.fromJSON = function(x) {\n if (typeof x === 'string') {\n x = JSON.parse(x);\n }\n var ds = this;\n Object.keys(x).forEach(function(ns) {\n ds.set(ns, x[ns]);\n });\n return ds;\n};\n\n/**\n * Return the names of all currently recognized datasources\n * @public\n * @returns {Array}\n */\nLocusZoom.DataSources.prototype.keys = function() {\n return Object.keys(this.sources);\n};\n\n/**\n * Datasources can be instantiated from a JSON object instead of code. This represents existing sources in that format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n * @public\n */\nLocusZoom.DataSources.prototype.toJSON = function() {\n return this.sources;\n};\n\n/**\n * Represents an addressable unit of data from a namespaced datasource, subject to specified value transformations.\n *\n * When used by a data layer, fields will automatically be re-fetched from the appropriate data source whenever the\n * state of a plot fetches, eg pan or zoom operations that would affect what data is displayed.\n *\n * @public\n * @class\n * @param {String} field A string representing the namespace of the datasource, the name of the desired field to fetch\n * from that datasource, and arbitrarily many transformations to apply to the value. The namespace and\n * transformation(s) are optional and information is delimited according to the general syntax\n * `[namespace:]name[|transformation][|transformation]`. For example, `association:pvalue|neglog10`\n */\nLocusZoom.Data.Field = function(field) {\n\n var parts = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/.exec(field);\n /** @member {String} */\n this.full_name = field;\n /** @member {String} */\n this.namespace = parts[1] || null;\n /** @member {String} */\n this.name = parts[2] || null;\n /** @member {Array} */\n this.transformations = [];\n\n if (typeof parts[3] == 'string' && parts[3].length > 1) {\n this.transformations = parts[3].substring(1).split('|');\n this.transformations.forEach(function(transform, i) {\n this.transformations[i] = LocusZoom.TransformationFunctions.get(transform);\n }.bind(this));\n }\n\n this.applyTransformations = function(val) {\n this.transformations.forEach(function(transform) {\n val = transform(val);\n });\n return val;\n };\n\n // Resolve the field for a given data element.\n // First look for a full match with transformations already applied by the data requester.\n // Otherwise prefer a namespace match and fall back to just a name match, applying transformations on the fly.\n this.resolve = function(d) {\n if (typeof d[this.full_name] == 'undefined') {\n var val = null;\n if (typeof (d[this.namespace + ':' + this.name]) != 'undefined') { val = d[this.namespace + ':' + this.name]; }\n else if (typeof d[this.name] != 'undefined') { val = d[this.name]; }\n d[this.full_name] = this.applyTransformations(val);\n }\n return d[this.full_name];\n };\n\n};\n\n/**\n * The Requester manages fetching of data across multiple data sources. It is used internally by LocusZoom data layers.\n * It passes state information and ensures that data is formatted in the manner expected by the plot.\n *\n * It is also responsible for constructing a \"chain\" of dependent requests, by requesting each datasource\n * sequentially in the order specified in the datalayer `fields` array. Data sources are only chained within a\n * data layer, and only if that layer requests more than one kind of data source.\n * @param {LocusZoom.DataSources} sources An object of {ns: LocusZoom.Data.Source} instances\n * @class\n */\nLocusZoom.Data.Requester = function(sources) {\n\n function split_requests(fields) {\n // Given a fields array, return an object specifying what datasource names the data layer should make requests\n // to, and how to handle the returned data\n var requests = {};\n // Regular expression finds namespace:field|trans\n var re = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/;\n fields.forEach(function(raw) {\n var parts = re.exec(raw);\n var ns = parts[1] || 'base';\n var field = parts[2];\n var trans = LocusZoom.TransformationFunctions.get(parts[3]);\n if (typeof requests[ns] == 'undefined') {\n requests[ns] = {outnames:[], fields:[], trans:[]};\n }\n requests[ns].outnames.push(raw);\n requests[ns].fields.push(field);\n requests[ns].trans.push(trans);\n });\n return requests;\n }\n\n /**\n * Fetch data, and create a chain that only connects two data sources if they depend on each other\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields The list of data fields specified in the `layout` for a specific data layer\n * @returns {Promise}\n */\n this.getData = function(state, fields) {\n var requests = split_requests(fields);\n // Create an array of functions that, when called, will trigger the request to the specified datasource\n var request_handles = Object.keys(requests).map(function(key) {\n if (!sources.get(key)) {\n throw new Error('Datasource for namespace ' + key + ' not found');\n }\n return sources.get(key).getData(state, requests[key].fields,\n requests[key].outnames, requests[key].trans);\n });\n //assume the fields are requested in dependent order\n //TODO: better manage dependencies\n var ret = Promise.resolve({header:{}, body: [], discrete: {}});\n for(var i = 0; i < request_handles.length; i++) {\n // If a single datalayer uses multiple sources, perform the next request when the previous one completes\n ret = ret.then(request_handles[i]);\n }\n return ret;\n };\n};\n\n/**\n * Base class for LocusZoom data sources\n * This can be extended with .extend() to create custom data sources\n * @class\n * @public\n */\nLocusZoom.Data.Source = function() {\n /**\n * Whether this source should enable caching\n * @member {Boolean}\n */\n this.enableCache = true;\n /**\n * Whether this data source type is dependent on previous requests- for example, the LD source cannot annotate\n * association data if no data was found for that region.\n * @member {boolean}\n */\n this.dependentSource = false;\n};\n\n/**\n * A default constructor that can be used when creating new data sources\n * @param {String|Object} init Basic configuration- either a url, or a config object\n * @param {String} [init.url] The datasource URL\n * @param {String} [init.params] Initial config params for the datasource\n */\nLocusZoom.Data.Source.prototype.parseInit = function(init) {\n if (typeof init === 'string') {\n /** @member {String} */\n this.url = init;\n /** @member {String} */\n this.params = {};\n } else {\n this.url = init.url;\n this.params = init.params || {};\n }\n if (!this.url) {\n throw new Error('Source not initialized with required URL');\n }\n\n};\n\n/**\n * A unique identifier that indicates whether cached data is valid for this request\n * @protected\n * @param state\n * @param chain\n * @param fields\n * @returns {String|undefined}\n */\nLocusZoom.Data.Source.prototype.getCacheKey = function(state, chain, fields) {\n return this.getURL && this.getURL(state, chain, fields);\n};\n\n/**\n * Stub: build the URL for any requests made by this source.\n */\nLocusZoom.Data.Source.prototype.getURL = function(state, chain, fields) { return this.url; };\n\n/**\n * Perform a network request to fetch data for this source\n * @protected\n * @param {Object} state The state of the parent plot\n * @param chain\n * @param fields\n * @returns {Promise}\n */\nLocusZoom.Data.Source.prototype.fetchRequest = function(state, chain, fields) {\n var url = this.getURL(state, chain, fields);\n return LocusZoom.createCORSPromise('GET', url);\n};\n\n/**\n * Gets the data for just this source, typically via a network request (caching where possible)\n * @protected\n */\nLocusZoom.Data.Source.prototype.getRequest = function(state, chain, fields) {\n var req;\n var cacheKey = this.getCacheKey(state, chain, fields);\n if (this.enableCache && typeof(cacheKey) !== 'undefined' && cacheKey === this._cachedKey) {\n req = Promise.resolve(this._cachedResponse); // Resolve to the value of the current promise\n } else {\n req = this.fetchRequest(state, chain, fields);\n if (this.enableCache) {\n this._cachedKey = cacheKey;\n this._cachedResponse = req;\n }\n }\n return req;\n};\n\n/**\n * Fetch the data from the specified data source, and apply transformations requested by an external consumer.\n * This is the public-facing datasource method that will most commonly be called by external code.\n *\n * @public\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields Array of field names that the plot has requested from this data source. (without the \"namespace\" prefix)\n * @param {String[]} outnames Array describing how the output data should refer to this field. This represents the\n * originally requested field name, including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {function} A callable operation that can be used as part of the data chain\n */\nLocusZoom.Data.Source.prototype.getData = function(state, fields, outnames, trans) {\n if (this.preGetData) {\n var pre = this.preGetData(state, fields, outnames, trans);\n if(this.pre) {\n state = pre.state || state;\n fields = pre.fields || fields;\n outnames = pre.outnames || outnames;\n trans = pre.trans || trans;\n }\n }\n\n var self = this;\n return function (chain) {\n if (self.dependentSource && chain && chain.body && !chain.body.length) {\n // A \"dependent\" source should not attempt to fire a request if there is no data for it to act on.\n // Therefore, it should simply return the previous data chain.\n return Promise.resolve(chain);\n }\n\n return self.getRequest(state, chain, fields).then(function(resp) {\n return self.parseResponse(resp, chain, fields, outnames, trans);\n });\n };\n};\n\n/**\n * Ensure the server response is in a canonical form, an array of one object per record. [ {field: oneval} ].\n * If the server response contains columns, reformats the response from {column1: [], column2: []} to the above.\n *\n * Does not apply namespacing, transformations, or field extraction.\n *\n * May be overridden by data sources that inherently return more complex payloads, or that exist to annotate other\n * sources (eg, if the payload provides extra data rather than a series of records).\n *\n * @param {Object[]|Object} data The original parsed server response\n * @protected\n */\nLocusZoom.Data.Source.prototype.normalizeResponse = function (data) {\n if (Array.isArray(data)) {\n // Already in the desired form\n return data;\n }\n\n // Otherwise, assume the server response is an object representing columns of data.\n // Each array should have the same length (verify), and a given array index corresponds to a single row.\n var keys = Object.keys(data);\n var N = data[keys[0]].length;\n var sameLength = keys.every(function(key) {\n var item = data[key];\n return item.length === N;\n });\n if (!sameLength) {\n throw new Error(this.constructor.SOURCE_NAME + ' expects a response in which all arrays of data are the same length');\n }\n\n // Go down the rows, and create an object for each record\n var records = [];\n var fields = Object.keys(data);\n for(var i = 0; i < N; i++) {\n var record = {};\n for(var j = 0; j < fields.length; j++) {\n record[fields[j]] = data[fields[j]][i];\n }\n records.push(record);\n }\n return records;\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.prepareData = function (records) {\n console.warn('Warning: .prepareData() is deprecated. Use .annotateData() instead');\n return this.annotateData(records);\n};\n\n/**\n * Hook to post-process the data returned by this source with new, additional behavior.\n * (eg cleaning up API values or performing complex calculations on the returned data)\n *\n * @param {Object[]} records The parsed data from the source (eg standardized api response)\n * @param {Object} chain The data chain object. For example, chain.headers may provide useful annotation metadata\n * @returns {Object[]|Promise} The modified set of records\n */\nLocusZoom.Data.Source.prototype.annotateData = function(records, chain) {\n // Default behavior: no transformations\n return records;\n};\n\n/**\n * Clean up the server records for use by datalayers: extract only certain fields, with the specified names.\n * Apply per-field transformations as appropriate.\n *\n * This hook can be overridden, eg to create a source that always returns all records and ignores the \"fields\" array.\n * This is particularly common for sources at the end of a chain- many \"dependent\" sources do not allow\n * cherry-picking individual fields, in which case by **convention** the fields array specifies \"last_source_name:all\"\n *\n * @param {Object[]} data One record object per element\n * @param {String[]} fields The names of fields to extract (as named in the source data). Eg \"afield\"\n * @param {String[]} outnames How to represent the source fields in the output. Eg \"namespace:afield|atransform\"\n * @param {function[]} trans An array of transformation functions (if any). One function per data element, or null.\n * @protected\n */\nLocusZoom.Data.Source.prototype.extractFields = function (data, fields, outnames, trans) {\n //intended for an array of objects\n // [ {\"id\":1, \"val\":5}, {\"id\":2, \"val\":10}]\n // Since a number of sources exist that do not obey this format, we will provide a convenient pass-through\n if (!Array.isArray(data)) {\n return data;\n }\n\n if (!data.length) {\n // Sometimes there are regions that just don't have data- this should not trigger a missing field error message!\n return data;\n }\n\n var fieldFound = [];\n for (var k = 0; k < fields.length; k++) {\n fieldFound[k] = 0;\n }\n\n var records = data.map(function (item) {\n var output_record = {};\n for (var j = 0; j < fields.length; j++) {\n var val = item[fields[j]];\n if (typeof val != 'undefined') {\n fieldFound[j] = 1;\n }\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n output_record[outnames[j]] = val;\n }\n return output_record;\n });\n fieldFound.forEach(function(v, i) {\n if (!v) {throw new Error('field ' + fields[i] + ' not found in response for ' + outnames[i]);}\n });\n return records;\n};\n\n/**\n * Combine records from this source with others in the chain to yield final chain body.\n * Handles merging this data with other sources (if applicable).\n *\n * @param {Object[]} data The data That would be returned from this source alone\n * @param {Object} chain The data chain built up during previous requests\n * @param {String[]} fields\n * @param {String[]} outnames\n * @return {Promise|Object[]} The new chain body\n * @protected\n */\nLocusZoom.Data.Source.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n return data;\n};\n\n/**\n * Coordinates the work of parsing a response and returning records. This is broken into 4 steps, which may be\n * overridden separately for fine-grained control. Each step can return either raw data or a promise.\n *\n * @public\n * @param {String|Object} resp The raw data associated with the response\n * @param {Object} chain The combined parsed response data from this and all other requests made in the chain\n * @param {String[]} fields Array of requested field names (as they would appear in the response payload)\n * @param {String[]} outnames Array of field names as they will be represented in the data returned by this source,\n * including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {Promise|{header: ({}|*), discrete: {}, body: []}} A promise that resolves to an object containing\n * request metadata (headers), the consolidated data for plotting (body), and the individual responses that would be\n * returned by each source in the chain in isolation (discrete)\n */\nLocusZoom.Data.Source.prototype.parseResponse = function(resp, chain, fields, outnames, trans) {\n var source_id = this.source_id || this.constructor.SOURCE_NAME;\n if (!chain.discrete) {\n chain.discrete = {};\n }\n\n if (!resp) {\n // FIXME: Hack. Certain browser issues (such as mixed content warnings) are reported as a successful promise\n // resolution, even though the request was aborted. This is difficult to reliably detect, and is most likely\n // to occur for annotation sources (such as from ExAC). If empty response is received, skip parsing and log.\n // FIXME: Throw an error after pending, eg https://github.com/konradjk/exac_browser/issues/345\n console.error(\"No usable response was returned for source: '\" + source_id + \"'. Parsing will be skipped.\");\n return Promise.resolve(chain);\n }\n\n var json = typeof resp == 'string' ? JSON.parse(resp) : resp;\n\n var self = this;\n // Perform the 4 steps of parsing the payload and return a combined chain object\n return Promise.resolve(self.normalizeResponse(json.data || json))\n .then(function(standardized) {\n // Perform calculations on the data from just this source\n return Promise.resolve(self.annotateData(standardized, chain));\n }).then(function (data) {\n return Promise.resolve(self.extractFields(data, fields, outnames, trans));\n }).then(function (one_source_body) {\n // Store a copy of the data that would be returned by parsing this source in isolation (and taking the\n // fields array into account). This is useful when we want to re-use the source output in many ways.\n chain.discrete[source_id] = one_source_body;\n return Promise.resolve(self.combineChainBody(one_source_body, chain, fields, outnames, trans));\n }).then(function (new_body) {\n return { header: chain.header || {}, discrete: chain.discrete, body: new_body };\n });\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseArraysToObjects = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseArraysToObjects() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseObjectsToObjects = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseObjectsToObjects() is deprecated. Use .extractFields() instead');\n return this.extractFields(data, fields, outnames, trans);\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseData = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseData() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n};\n\n/**\n * Method to define new custom datasources based on a provided constructor. (does not allow registering any additional methods)\n * @public\n * @param {Function} constructorFun Constructor function that is used to create the specified class\n * @param {String} [uniqueName] The name by which the class should be listed in `KnownDataSources`\n * @param {String|Function} [base=LocusZoomData.Source] The name or constructor of a base class to use\n * @returns {*|Function}\n */\nLocusZoom.Data.Source.extend = function(constructorFun, uniqueName, base) {\n if (base) {\n if (Array.isArray(base)) {\n base = LocusZoom.KnownDataSources.create.apply(null, base);\n } else if (typeof base === 'string') {\n base = LocusZoom.KnownDataSources.get(base).prototype;\n } else if (typeof base === 'function') {\n base = base.prototype;\n }\n } else {\n base = new LocusZoom.Data.Source();\n }\n constructorFun = constructorFun || function() {};\n constructorFun.prototype = base;\n constructorFun.prototype.constructor = constructorFun;\n if (uniqueName) {\n /** @member {String} LocusZoom.Data.Source.SOURCENAME */\n constructorFun.SOURCE_NAME = uniqueName;\n LocusZoom.KnownDataSources.add(constructorFun);\n }\n return constructorFun;\n};\n\n/**\n * Datasources can be instantiated from a JSON object instead of code. This represents an existing source in that data format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n *\n * Custom sources with their own parameters may need to re-implement this method\n *\n * @public\n * @returns {Object}\n */\nLocusZoom.Data.Source.prototype.toJSON = function() {\n return [Object.getPrototypeOf(this).constructor.SOURCE_NAME,\n {url:this.url, params:this.params}];\n};\n\n/**\n * Data Source for Association Data, as fetched from the LocusZoom API server (or compatible)\n * @class\n * @public\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.AssociationSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'AssociationLZ');\n\nLocusZoom.Data.AssociationSource.prototype.preGetData = function(state, fields, outnames, trans) {\n var id_field = this.params.id_field || 'id';\n [id_field, 'position'].forEach(function(x) {\n if (fields.indexOf(x) === -1) {\n fields.unshift(x);\n outnames.unshift(x);\n trans.unshift(null);\n }\n });\n return {fields: fields, outnames:outnames, trans:trans};\n};\n\nLocusZoom.Data.AssociationSource.prototype.getURL = function(state, chain, fields) {\n var analysis = chain.header.analysis || this.params.source || this.params.analysis; // Old usages called this param \"analysis\"\n if (typeof analysis == 'undefined') {\n throw new Error('Association source must specify an analysis ID to plot');\n }\n return this.url + 'results/?filter=analysis in ' + analysis +\n \" and chromosome in '\" + state.chr + \"'\" +\n ' and position ge ' + state.start +\n ' and position le ' + state.end;\n};\n\nLocusZoom.Data.AssociationSource.prototype.normalizeResponse = function (data) {\n // Some association sources do not sort their data in a predictable order, which makes it hard to reliably\n // align with other sources (such as LD). For performance reasons, sorting is an opt-in argument.\n // TODO: Consider more fine grained sorting control in the future\n data = LocusZoom.Data.Source.prototype.normalizeResponse.call(this, data);\n if (this.params && this.params.sort && data.length && data[0]['position']) {\n data.sort(function (a, b) { return a['position'] - b['position']; });\n }\n return data;\n};\n\n/**\n * Data Source for LD Data, as fetched from the LocusZoom API server (or compatible)\n * This source is designed to connect its results to association data, and therefore depends on association data having\n * been loaded by a previous request in the data chain.\n *\n * This source is deprecated in favor of a new, standalone LD server. For new usages, see LDLZ2.\n *\n * @class\n * @deprecated\n * @public\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.LDSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n this.dependentSource = true;\n}, 'LDLZ');\n\nLocusZoom.Data.LDSource.prototype.preGetData = function(state, fields) {\n if (fields.length > 1) {\n if (fields.length !== 2 || fields.indexOf('isrefvar') === -1) {\n throw new Error('LD does not know how to get all fields: ' + fields.join(', '));\n }\n }\n};\n\nLocusZoom.Data.LDSource.prototype.findMergeFields = function(chain) {\n // Find the fields (as provided by a previous step in the chain, like an association source) that will be needed to\n // combine LD data with existing information\n\n // Since LD information may be shared across multiple assoc sources with different namespaces,\n // we use regex to find columns to join on, rather than requiring exact matches\n var exactMatch = function(arr) {return function() {\n var regexes = arguments;\n for(var i = 0; i < regexes.length; i++) {\n var regex = regexes[i];\n var m = arr.filter(function(x) {return x.match(regex);});\n if (m.length) {\n return m[0];\n }\n }\n return null;\n };};\n var dataFields = {\n id: this.params.id_field,\n position: this.params.position_field,\n pvalue: this.params.pvalue_field,\n _names_:null\n };\n if (chain && chain.body && chain.body.length > 0) {\n var names = Object.keys(chain.body[0]);\n var nameMatch = exactMatch(names);\n // Internally, fields are generally prefixed with the name of the source they come from.\n // If the user provides an id_field (like `variant`), it should work across data sources( `assoc1:variant`,\n // assoc2:variant), but not match fragments of other field names (assoc1:variant_thing)\n // Note: these lookups hard-code a couple of common fields that will work based on known APIs in the wild\n var id_match = dataFields.id && nameMatch(new RegExp(dataFields.id + '\\\\b'));\n dataFields.id = id_match || nameMatch(/\\bvariant\\b/) || nameMatch(/\\bid\\b/);\n dataFields.position = dataFields.position || nameMatch(/\\bposition\\b/i, /\\bpos\\b/i);\n dataFields.pvalue = dataFields.pvalue || nameMatch(/\\bpvalue\\b/i, /\\blog_pvalue\\b/i);\n dataFields._names_ = names;\n }\n return dataFields;\n};\n\nLocusZoom.Data.LDSource.prototype.findRequestedFields = function(fields, outnames) {\n // Assumption: all usages of this source will only ever ask for \"isrefvar\" or \"state\". This maps to output names.\n var obj = {};\n for(var i = 0; i < fields.length; i++) {\n if(fields[i] === 'isrefvar') {\n obj.isrefvarin = fields[i];\n obj.isrefvarout = outnames && outnames[i];\n } else {\n obj.ldin = fields[i];\n obj.ldout = outnames && outnames[i];\n }\n }\n return obj;\n};\n\nLocusZoom.Data.LDSource.prototype.normalizeResponse = function (data) { return data; };\n\n\n/**\n * Get the LD reference variant, which by default will be the most significant hit in the assoc results\n * This will be used in making the original query to the LD server for pairwise LD information\n * @returns {*|string} The marker id (expected to be in `chr:pos_ref/alt` format) of the reference variant\n */\nLocusZoom.Data.LDSource.prototype.getRefvar = function (state, chain, fields) {\n var findExtremeValue = function(records, pval_field) {\n // Finds the most significant hit (smallest pvalue, or largest -log10p). Will try to auto-detect the appropriate comparison.\n pval_field = pval_field || 'log_pvalue'; // The official LZ API returns log_pvalue\n var is_log = /log/.test(pval_field);\n var cmp;\n if (is_log) {\n cmp = function(a, b) { return a > b; };\n } else {\n cmp = function(a, b) { return a < b; };\n }\n var extremeVal = records[0][pval_field], extremeIdx = 0;\n for(var i = 1; i < records.length; i++) {\n if (cmp(records[i][pval_field], extremeVal)) {\n extremeVal = records[i][pval_field];\n extremeIdx = i;\n }\n }\n return extremeIdx;\n };\n\n var reqFields = this.findRequestedFields(fields);\n var refVar = reqFields.ldin;\n if (refVar === 'state') {\n refVar = state.ldrefvar || chain.header.ldrefvar || 'best';\n }\n if (refVar === 'best') {\n if (!chain.body) {\n throw new Error('No association data found to find best pvalue');\n }\n var keys = this.findMergeFields(chain);\n if (!keys.pvalue || !keys.id) {\n var columns = '';\n if (!keys.id) { columns += (columns.length ? ', ' : '') + 'id'; }\n if (!keys.pvalue) { columns += (columns.length ? ', ' : '') + 'pvalue'; }\n throw new Error('Unable to find necessary column(s) for merge: ' + columns + ' (available: ' + keys._names_ + ')');\n }\n refVar = chain.body[findExtremeValue(chain.body, keys.pvalue)][keys.id];\n }\n return refVar;\n};\n\nLocusZoom.Data.LDSource.prototype.getURL = function(state, chain, fields) {\n var refSource = state.ldrefsource || chain.header.ldrefsource || 1;\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n return this.url + 'results/?filter=reference eq ' + refSource +\n \" and chromosome2 eq '\" + state.chr + \"'\" +\n ' and position2 ge ' + state.start +\n ' and position2 le ' + state.end +\n \" and variant1 eq '\" + refVar + \"'\" +\n '&fields=chr,pos,rsquare';\n};\n\nLocusZoom.Data.LDSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n var keys = this.findMergeFields(chain);\n var reqFields = this.findRequestedFields(fields, outnames);\n if (!keys.position) {\n throw new Error('Unable to find position field for merge: ' + keys._names_);\n }\n var leftJoin = function(left, right, lfield, rfield) {\n var i = 0, j = 0;\n while (i < left.length && j < right.position2.length) {\n if (left[i][keys.position] === right.position2[j]) {\n left[i][lfield] = right[rfield][j];\n i++;\n j++;\n } else if (left[i][keys.position] < right.position2[j]) {\n i++;\n } else {\n j++;\n }\n }\n };\n var tagRefVariant = function(data, refvar, idfield, outrefname, outldname) {\n for(var i = 0; i < data.length; i++) {\n if (data[i][idfield] && data[i][idfield] === refvar) {\n data[i][outrefname] = 1;\n data[i][outldname] = 1; // For label/filter purposes, implicitly mark the ref var as LD=1 to itself\n } else {\n data[i][outrefname] = 0;\n }\n }\n };\n\n // LD servers vary slightly. Some report corr as \"rsquare\", others as \"correlation\"\n var corrField = data.rsquare ? 'rsquare' : 'correlation';\n leftJoin(chain.body, data, reqFields.ldout, corrField);\n if(reqFields.isrefvarin && chain.header.ldrefvar) {\n tagRefVariant(chain.body, chain.header.ldrefvar, keys.id, reqFields.isrefvarout, reqFields.ldout);\n }\n return chain.body;\n};\n\n/**\n * Fetch LD directly from the standalone Portal LD server\n *\n * @class\n * @public\n * @augments LocusZoom.Data.LDSource\n */\nLocusZoom.Data.LDSource2 = LocusZoom.KnownDataSources.extend('LDLZ', 'LDLZ2', {\n getURL: function(state, chain, fields) {\n // Accept the following params in this.params:\n // - method (r, rsquare, cov)\n // - source (aka panel)\n // - population (ALL, AFR, EUR, etc)\n // - build\n // The LD source/pop can be overridden from plot.state for dynamic layouts\n var build = state.genome_build || this.params.build || 'GRCh37';\n var source = state.ld_source || this.params.source || '1000G';\n var population = state.ld_pop || this.params.population || 'ALL'; // LDServer panels will always have an ALL\n var method = this.params.method || 'rsquare';\n\n validateBuildSource(this.constructor.SOURCE_NAME, build, null); // LD doesn't need to validate `source` option\n\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n\n return [\n this.url, 'genome_builds/', build, '/references/', source, '/populations/', population, '/variants',\n '?correlation=', method,\n '&variant=', encodeURIComponent(refVar),\n '&chrom=', encodeURIComponent(state.chr),\n '&start=', encodeURIComponent(state.start),\n '&stop=', encodeURIComponent(state.end)\n ].join('');\n },\n fetchRequest: function(state, chain, fields) {\n // The API is paginated, but we need all of the data to render a plot. Depaginate and combine where appropriate.\n var url = this.getURL(state, chain, fields);\n var combined = { data: {} };\n var chainRequests = function (url) {\n return LocusZoom.createCORSPromise('GET', url)\n .then(function(payload) {\n payload = JSON.parse(payload);\n Object.keys(payload.data).forEach(function (key) {\n combined.data[key] = (combined.data[key] || []).concat(payload.data[key]);\n });\n if (payload.next) {\n return chainRequests(payload.next);\n }\n return combined;\n });\n };\n\n return chainRequests(url);\n }\n});\n\n/**\n * Data source for GWAS catalogs of known variants\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object|String} init Configuration (URL or object)\n * @param {Object} [init.params] Optional configuration parameters\n * @param {Number} [init.params.source=2] The ID of the chosen catalog. Defaults to EBI GWAS catalog, GRCh37\n * @param {('strict'|'loose')} [init.params.match_type='strict'] Whether to match on exact variant, or just position.\n */\nLocusZoom.Data.GwasCatalog = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n this.dependentSource = true;\n}, 'GwasCatalogLZ');\n\nLocusZoom.Data.GwasCatalog.prototype.getURL = function(state, chain, fields) {\n // This is intended to be aligned with another source- we will assume they are always ordered by position, asc\n // (regardless of the actual match field)\n var build_option = state.genome_build || this.params.build;\n validateBuildSource(this.constructor.SOURCE_NAME, build_option, null); // Source can override build- not mutually exclusive\n\n // Most of our annotations will respect genome build before any other option.\n // But there can be more than one GWAS catalog for the same build, so an explicit config option will always take\n // precedence.\n var default_source = (build_option === 'GRCh38') ? 1 : 2; // EBI GWAS catalog\n var source = this.params.source || default_source;\n return this.url + '?format=objects&sort=pos&filter=id eq ' + source +\n \" and chrom eq '\" + state.chr + \"'\" +\n ' and pos ge ' + state.start +\n ' and pos le ' + state.end;\n};\n\nLocusZoom.Data.GwasCatalog.prototype.findMergeFields = function (records) {\n // Data from previous sources is already namespaced. Find the alignment field by matching.\n var knownFields = Object.keys(records);\n // Note: All API endoints involved only give results for 1 chromosome at a time; match is implied\n var posMatch = knownFields.find(function (item) { return item.match(/\\b(position|pos)\\b/i); });\n\n if (!posMatch) {\n throw new Error('Could not find data to align with GWAS catalog results');\n }\n return { 'pos': posMatch };\n};\n\n// Skip the \"individual field extraction\" step; extraction will be handled when building chain body instead\nLocusZoom.Data.GwasCatalog.prototype.extractFields = function (data, fields, outnames, trans) { return data; };\n\nLocusZoom.Data.GwasCatalog.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data.length) {\n return chain.body;\n }\n\n var decider = 'log_pvalue'; // TODO: Better reuse options in the future\n var decider_out = outnames[fields.indexOf(decider)];\n\n function leftJoin(left, right, fields, outnames, trans) { // Add `fields` from `right` to `left`\n // Add a synthetic, un-namespaced field to all matching records\n var n_matches = left['n_catalog_matches'] || 0;\n left['n_catalog_matches'] = n_matches + 1;\n if (decider && left[decider_out] && left[decider_out] > right[decider]) {\n // There may be more than one GWAS catalog entry for the same SNP. This source is intended for a 1:1\n // annotation scenario, so for now it only joins the catalog entry that has the best -log10 pvalue\n return;\n }\n\n for (var j = 0; j < fields.length; j++) {\n var fn = fields[j];\n var outn = outnames[j];\n\n var val = right[fn];\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n left[outn] = val;\n }\n }\n\n var chainNames = this.findMergeFields(chain.body[0]);\n var catNames = this.findMergeFields(data[0]);\n\n var i = 0, j = 0;\n while (i < chain.body.length && j < data.length) {\n var left = chain.body[i];\n var right = data[j];\n\n if (left[chainNames.pos] === right[catNames.pos]) {\n // There may be multiple catalog entries for each matching SNP; evaluate match one at a time\n leftJoin(left, right, fields, outnames, trans);\n j += 1;\n } else if (left[chainNames.pos] < right[catNames.pos]) {\n i += 1;\n } else {\n j += 1;\n }\n }\n return chain.body;\n};\n\n\n/**\n * Data Source for Gene Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.GeneSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'GeneLZ');\n\nLocusZoom.Data.GeneSource.prototype.getURL = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n\n if (build) { // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = (build === 'GRCh38') ? 1 : 3;\n }\n return this.url + '?filter=source in ' + source +\n \" and chrom eq '\" + state.chr + \"'\" +\n ' and start le ' + state.end +\n ' and end ge ' + state.start;\n};\n\n// Genes have a very complex internal data format. Bypass any record parsing, and provide the data layer with the\n// exact information returned by the API. (ignoring the fields array in the layout)\nLocusZoom.Data.GeneSource.prototype.normalizeResponse = function (data) { return data; };\nLocusZoom.Data.GeneSource.prototype.extractFields = function (data, fields, outnames, trans) { return data; };\n\n/**\n * Data Source for Gene Constraint Data, as fetched from the gnomAD server (or compatible)\n *\n * In the past, this source used ExAC, which has been completely decommissioned. Since the old source referenced a\n * server that no longer exists, this was redefined in 0.11.0 in a backwards-incompatible manner.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n*/\nLocusZoom.Data.GeneConstraintSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'GeneConstraintLZ');\n\nLocusZoom.Data.GeneConstraintSource.prototype.getURL = function() {\n return this.url;\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.normalizeResponse = function (data) { return data; };\n\nLocusZoom.Data.GeneConstraintSource.prototype.getCacheKey = function(state, chain, fields) {\n return this.url + JSON.stringify(state);\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n if (!build) {\n throw new Error(['Data source', this.constructor.SOURCE_NAME, 'requires that you specify a genome_build'].join(' '));\n }\n\n var query = chain.body.map(function (gene) {\n var gene_name = gene.gene_name;\n // GraphQL alias names must match a specific set of allowed characters: https://stackoverflow.com/a/45757065/1422268\n var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_');\n // Each gene is a separate graphQL query, grouped into one request using aliases\n return alias + ': gene(gene_symbol: \"' + gene_name + '\", reference_genome: ' + build + ') { gnomad_constraint { exp_syn obs_syn syn_z oe_syn oe_syn_lower oe_syn_upper exp_mis obs_mis mis_z oe_mis oe_mis_lower oe_mis_upper exp_lof obs_lof pLI oe_lof oe_lof_lower oe_lof_upper } } ';\n });\n\n if (!query.length) {\n // If there are no genes, skip the network request\n return Promise.resolve({ data: null });\n }\n\n query = '{' + query.join(' ') + ' }'; // GraphQL isn't quite JSON; items are separated by spaces but not commas\n var url = this.getURL(state, chain, fields);\n // See: https://graphql.org/learn/serving-over-http/\n var body = JSON.stringify({ query: query });\n var headers = { 'Content-Type': 'application/json' };\n return LocusZoom.createCORSPromise('POST', url, body, headers);\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data) {\n return chain;\n }\n\n chain.body.forEach(function(gene) {\n // Find payload keys that match gene names in this response\n var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_'); // aliases are modified gene names\n var constraint = data[alias] && data[alias]['gnomad_constraint']; // gnomad API has two ways of specifying missing data for a requested gene\n if (constraint) {\n // Add all fields from constraint data- do not override fields present in the gene source\n Object.keys(constraint).forEach(function (key) {\n var val = constraint[key];\n if (typeof gene[key] === 'undefined') {\n if (typeof val == 'number' && val.toString().indexOf('.') !== -1) {\n val = parseFloat(val.toFixed(2));\n }\n gene[key] = val; // These two sources are both designed to bypass namespacing\n }\n });\n }\n });\n return chain.body;\n};\n\n/**\n * Data Source for Recombination Rate Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.RecombinationRateSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'RecombLZ');\n\nLocusZoom.Data.RecombinationRateSource.prototype.getURL = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n\n if (build) { // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = (build === 'GRCh38') ? 16 : 15;\n }\n return this.url + '?filter=id in ' + source +\n \" and chromosome eq '\" + state.chr + \"'\" +\n ' and position le ' + state.end +\n ' and position ge ' + state.start;\n};\n\n/**\n * Data Source for Interval Annotation Data (e.g. BED Tracks), as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.IntervalSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'IntervalLZ');\n\nLocusZoom.Data.IntervalSource.prototype.getURL = function(state, chain, fields) {\n var source = chain.header.bedtracksource || this.params.source;\n return this.url + '?filter=id in ' + source +\n \" and chromosome eq '\" + state.chr + \"'\" +\n ' and start le ' + state.end +\n ' and end ge ' + state.start;\n};\n\n/**\n * Data Source for static blobs of JSON Data. This does not perform additional parsing, and therefore it is the\n * responsibility of the user to pass information in a format that can be read and understood by the chosen plot.\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.StaticSource = LocusZoom.Data.Source.extend(function(data) {\n /** @member {Object} */\n this._data = data;\n},'StaticJSON');\n\nLocusZoom.Data.StaticSource.prototype.getRequest = function(state, chain, fields) {\n return Promise.resolve(this._data);\n};\n\nLocusZoom.Data.StaticSource.prototype.toJSON = function() {\n return [Object.getPrototypeOf(this).constructor.SOURCE_NAME, this._data];\n};\n\n/**\n * Data source for PheWAS data\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {String[]} init.params.build This datasource expects to be provided the name of the genome build that will\n * be used to provide pheWAS results for this position. Note positions may not translate between builds.\n */\nLocusZoom.Data.PheWASSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'PheWASLZ');\nLocusZoom.Data.PheWASSource.prototype.getURL = function(state, chain, fields) {\n var build = (state.genome_build ? [state.genome_build] : null) || this.params.build;\n if (!build || !Array.isArray(build) || !build.length) {\n throw new Error(['Data source', this.constructor.SOURCE_NAME, 'requires that you specify array of one or more desired genome build names'].join(' '));\n }\n var url = [\n this.url,\n \"?filter=variant eq '\", encodeURIComponent(state.variant), \"'&format=objects&\",\n build.map(function(item) {return 'build=' + encodeURIComponent(item);}).join('&')\n ];\n return url.join('');\n};\n\n/**\n * Base class for \"connectors\"- this is meant to be subclassed, rather than used directly.\n *\n * A connector is a source that makes no server requests and caches no data of its own. Instead, it decides how to\n * combine data from other sources in the chain. Connectors are useful when we want to request (or calculate) some\n * useful piece of information once, but apply it to many different kinds of record types.\n *\n * Typically, a subclass will implement the field merging logic in `combineChainBody`.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object} init Configuration for this source\n * @param {Object} init.sources Specify how the hard-coded logic should find the data it relies on in the chain,\n * as {internal_name: chain_source_id} pairs. This allows writing a reusable connector that does not need to make\n * assumptions about what namespaces a source is using.\n * @type {*|Function}\n */\nLocusZoom.Data.ConnectorSource = LocusZoom.Data.Source.extend(function(init) {\n if (!init || !init.sources) {\n throw new Error('Connectors must specify the data they require as init.sources = {internal_name: chain_source_id}} pairs');\n }\n\n /**\n * Tells the connector how to find the data it relies on\n *\n * For example, a connector that applies burden test information to the genes layer might specify:\n * {gene_ns: \"gene\", aggregation_ns: \"aggregation\"}\n *\n * @member {Object}\n */\n this._source_name_mapping = init.sources;\n\n // Validate that this source has been told how to find the required information\n var specified_ids = Object.keys(init.sources);\n var self = this;\n this.REQUIRED_SOURCES.forEach(function (k) {\n if (specified_ids.indexOf(k) === -1) {\n throw new Error('Configuration for ' + self.constructor.SOURCE_NAME + ' must specify a source ID corresponding to ' + k);\n }\n });\n this.parseInit(init);\n}, 'ConnectorSource');\n\n/** @property {String[]} Specifies the sources that must be provided in the original config object */\nLocusZoom.Data.ConnectorSource.prototype.REQUIRED_SOURCES = [];\n\nLocusZoom.Data.ConnectorSource.prototype.parseInit = function(init) {}; // Stub\n\nLocusZoom.Data.ConnectorSource.prototype.getRequest = function(state, chain, fields) {\n // Connectors do not request their own data by definition, but they *do* depend on other sources having been loaded\n // first. This method performs basic validation, and preserves the accumulated body from the chain so far.\n var self = this;\n Object.keys(this._source_name_mapping).forEach(function(ns) {\n var chain_source_id = self._source_name_mapping[ns];\n if (chain.discrete && !chain.discrete[chain_source_id]) {\n throw new Error(self.constructor.SOURCE_NAME + ' cannot be used before loading required data for: ' + chain_source_id);\n }\n });\n return Promise.resolve(chain.body || []);\n};\n\nLocusZoom.Data.ConnectorSource.prototype.parseResponse = function(data, chain, fields, outnames, trans) {\n // A connector source does not update chain.discrete, but it may use it. It bypasses data formatting\n // and field selection (both are assumed to have been done already, by the previous sources this draws from)\n\n // Because of how the chain works, connectors are not very good at applying new transformations or namespacing.\n // Typically connectors are called with `connector_name:all` in the fields array.\n return Promise.resolve(this.combineChainBody(data, chain, fields, outnames, trans))\n .then(function(new_body) {\n return {header: chain.header || {}, discrete: chain.discrete || {}, body: new_body};\n });\n};\n\nLocusZoom.Data.ConnectorSource.prototype.combineChainBody = function(records, chain) {\n // Stub method: specifies how to combine the data\n throw new Error('This method must be implemented in a subclass');\n};\n","/* global LocusZoom */\n'use strict';\n\n/**\n * An independent LocusZoom object that renders a unique set of data and subpanels.\n * Many such LocusZoom objects can exist simultaneously on a single page, each having its own layout.\n *\n * This creates a new plot instance, but does not immediately render it. For practical use, it may be more convenient\n * to use the `LocusZoom.populate` helper method.\n *\n * @class\n * @param {String} id The ID of the plot. Often corresponds to the ID of the container element on the page\n * where the plot is rendered..\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n*/\nLocusZoom.Plot = function(id, datasource, layout) {\n /** @member Boolean} */\n this.initialized = false;\n // TODO: This makes sense for all other locuszoom elements to have; determine whether this is interface boilerplate or something that can be removed\n this.parent_plot = this;\n\n /** @member {String} */\n this.id = id;\n\n /** @member {Element} */\n this.container = null;\n /**\n * Selector for a node that will contain the plot. (set externally by populate methods)\n * @member {d3.selection}\n */\n this.svg = null;\n\n /** @member {Object.} */\n this.panels = {};\n /**\n * TODO: This is currently used by external classes that manipulate the parent and may indicate room for a helper method in the api to coordinate boilerplate\n * @protected\n * @member {String[]}\n */\n this.panel_ids_by_y_index = [];\n\n /**\n * Notify each child panel of the plot of changes in panel ordering/ arrangement\n */\n this.applyPanelYIndexesToPanelLayouts = function() {\n this.panel_ids_by_y_index.forEach(function(pid, idx) {\n this.panels[pid].layout.y_index = idx;\n }.bind(this));\n };\n\n /**\n * Get the qualified ID pathname for the plot\n * @returns {String}\n */\n this.getBaseId = function() {\n return this.id;\n };\n\n /**\n * Track update operations (reMap) performed on all child panels, and notify the parent plot when complete\n * TODO: Reconsider whether we need to be tracking this as global state outside of context of specific operations\n * @protected\n * @member {Promise[]}\n */\n this.remap_promises = [];\n\n if (typeof layout == 'undefined') {\n /**\n * The layout is a serializable object used to describe the composition of the Plot\n * If no layout was passed, use the Standard Association Layout\n * Otherwise merge whatever was passed with the Default Layout\n * TODO: Review description; we *always* merge with default layout?\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge({}, LocusZoom.Layouts.get('plot', 'standard_association'));\n } else {\n this.layout = layout;\n }\n LocusZoom.Layouts.merge(this.layout, LocusZoom.Plot.DefaultLayout);\n\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original plot state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n\n\n /**\n * Create a shortcut to the state in the layout on the Plot. Tracking in the layout allows the plot to be created\n * with initial state/setup.\n *\n * Tracks state of the plot, eg start and end position\n * @member {Object}\n */\n this.state = this.layout.state;\n\n /** @member {LocusZoom.Data.Requester} */\n this.lzd = new LocusZoom.Data.Requester(datasource);\n\n /**\n * Window.onresize listener (responsive layouts only)\n * TODO: .on appears to return a selection, not a listener? Check logic here\n * https://github.com/d3/d3-selection/blob/00b904b9bcec4dfaf154ae0bbc777b1fc1d7bc08/test/selection/on-test.js#L11\n * @deprecated\n * @member {d3.selection}\n */\n this.window_onresize = null;\n\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [], // Select or unselect\n 'element_selection': [], // Element becomes active (only)\n 'match_requested': [], // A data layer is attempting to highlight matching points (internal use only)\n 'panel_removed': [],\n 'state_changed': [] // Only triggered when a state change causes rerender\n };\n\n /**\n * @callback eventCallback\n * @param {object} eventData A description of the event\n * @param {String|null} eventData.sourceID The unique identifier (eg plot or parent name) of the element that\n * triggered the event. Will be automatically filled in if not explicitly provided.\n * @param {Object|null} eventData.context Any additional information to be passed to the callback, eg the data\n * associated with a clicked plot element\n */\n\n /**\n * There are several events that a LocusZoom plot can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following plot-level events are currently supported:\n * - `layout_changed` - context: plot - Any aspect of the plot's layout (including dimensions or state) has changed.\n * - `data_requested` - context: plot - A request for new data from any data source used in the plot has been made.\n * - `data_rendered` - context: plot - Data from a request has been received and rendered in the plot.\n * - `element_clicked` - context: plot - A data element in any of the plot's data layers has been clicked.\n * - `element_selection` - context: plot - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `plot.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * plot itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} hook\n * @returns {function} The registered event listener\n */\n this.on = function(event, hook) {\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Plot}\n */\n this.off = function(event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n * @param {string} event A known event name\n * @param {*} eventData Data or event description that will be passed to the event listener\n * @returns {LocusZoom.Plot}\n */\n this.emit = function(event, eventData) {\n // TODO: there are small differences between the emit implementation between plots and panels. In the future,\n // DRY this code via mixins, and make sure to keep the interfaces compatible when refactoring.\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n var sourceID = this.getBaseId();\n var self = this;\n this.event_hooks[event].forEach(function(hookToRun) {\n var eventContext;\n if (eventData && eventData.sourceID) {\n // If we detect that an event originated elsewhere (via bubbling or externally), preserve the context\n // when re-emitting the event to plot-level listeners\n eventContext = eventData;\n } else {\n eventContext = {sourceID: sourceID, data: eventData || null};\n }\n // By default, any handlers fired here (either directly, or bubbled) will see the plot as the\n // value of `this`. If a bound function is registered as a handler, the previously bound `this` will\n // override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n return this;\n };\n\n /**\n * Get an object with the x and y coordinates of the plot's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the plot\n * @returns {{x: Number, y: Number, width: Number, height: Number}}\n */\n this.getPageOrigin = function() {\n var bounding_client_rect = this.svg.node().getBoundingClientRect();\n var x_offset = document.documentElement.scrollLeft || document.body.scrollLeft;\n var y_offset = document.documentElement.scrollTop || document.body.scrollTop;\n var container = this.svg.node();\n while (container.parentNode !== null) {\n container = container.parentNode;\n if (container !== document && d3.select(container).style('position') !== 'static') {\n x_offset = -1 * container.getBoundingClientRect().left;\n y_offset = -1 * container.getBoundingClientRect().top;\n break;\n }\n }\n return {\n x: x_offset + bounding_client_rect.left,\n y: y_offset + bounding_client_rect.top,\n width: bounding_client_rect.width,\n height: bounding_client_rect.height\n };\n };\n\n /**\n * Get the top and left offset values for the plot's container element (the div that was populated)\n * @returns {{top: number, left: number}}\n */\n this.getContainerOffset = function() {\n var offset = { top: 0, left: 0 };\n var container = this.container.offsetParent || null;\n while (container !== null) {\n offset.top += container.offsetTop;\n offset.left += container.offsetLeft;\n container = container.offsetParent || null;\n }\n return offset;\n };\n\n //\n /**\n * Event information describing interaction (e.g. panning and zooming) is stored on the plot\n * TODO: Add/ document details of interaction structure as we expand\n * @member {{panel_id: String, linked_panel_ids: Array, x_linked: *, dragging: *, zooming: *}}\n * @returns {LocusZoom.Plot}\n */\n this.interaction = {};\n\n /**\n * Track whether the target panel can respond to mouse interaction events\n * @param {String} panel_id\n * @returns {boolean}\n */\n this.canInteract = function(panel_id) {\n panel_id = panel_id || null;\n if (panel_id) {\n return ((typeof this.interaction.panel_id == 'undefined' || this.interaction.panel_id === panel_id) && !this.loading_data);\n } else {\n return !(this.interaction.dragging || this.interaction.zooming || this.loading_data);\n }\n };\n\n // Initialize the layout\n this.initializeLayout();\n return this;\n};\n\n/**\n * Default/ expected configuration parameters for basic plotting; most plots will override\n *\n * @protected\n * @static\n * @type {Object}\n */\nLocusZoom.Plot.DefaultLayout = {\n state: {},\n width: 1,\n height: 1,\n min_width: 1,\n min_height: 1,\n responsive_resize: false, // Allowed values: false, \"width_only\", \"both\" (synonym for true)\n aspect_ratio: 1,\n panels: [],\n dashboard: {\n components: []\n },\n panel_boundaries: true,\n mouse_guide: true\n};\n\n/**\n * Helper method to sum the proportional dimensions of panels, a value that's checked often as panels are added/removed\n * @param {('Height'|'Width')} dimension\n * @returns {number}\n */\nLocusZoom.Plot.prototype.sumProportional = function(dimension) {\n if (dimension !== 'height' && dimension !== 'width') {\n throw new Error('Bad dimension value passed to LocusZoom.Plot.prototype.sumProportional');\n }\n var total = 0;\n for (var id in this.panels) {\n // Ensure every panel contributing to the sum has a non-zero proportional dimension\n if (!this.panels[id].layout['proportional_' + dimension]) {\n this.panels[id].layout['proportional_' + dimension] = 1 / Object.keys(this.panels).length;\n }\n total += this.panels[id].layout['proportional_' + dimension];\n }\n return total;\n};\n\n/**\n * Resize the plot to fit the bounding container\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.rescaleSVG = function() {\n var clientRect = this.svg.node().getBoundingClientRect();\n this.setDimensions(clientRect.width, clientRect.height);\n return this;\n};\n\n/**\n * Prepare the plot for first use by performing parameter validation, setting up panels, and calculating dimensions\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.initializeLayout = function() {\n\n // Sanity check layout values\n if (isNaN(this.layout.width) || this.layout.width <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.height) || this.layout.height <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.aspect_ratio) || this.layout.aspect_ratio <= 0) {\n throw new Error('Plot layout parameter `aspect_ratio` must be a positive number');\n }\n if (this.layout.responsive_resize === true) {\n // Backwards compatible support\n console.warn('LocusZoom \"responsive_resize\" specifies a deprecated value. The new value should be \"both\". Please update your layout.');\n this.layout.responsive_resize = 'both';\n }\n var RESIZE_MODES = [false, 'both', 'width_only'];\n if (RESIZE_MODES.indexOf(this.layout.responsive_resize) === -1) {\n throw new Error('LocusZoom option \"responsive_resize\" should specify one of the following modes: ' + RESIZE_MODES.join(', '));\n }\n\n // If this is a responsive layout then set a namespaced/unique onresize event listener on the window\n if (this.layout.responsive_resize) {\n this.window_onresize = d3.select(window).on('resize.lz-' + this.id, function() {\n this.rescaleSVG();\n }.bind(this));\n // Forcing one additional setDimensions() call after the page is loaded clears up\n // any disagreements between the initial layout and the loaded responsive container's size\n d3.select(window).on('load.lz-' + this.id, function() {\n this.setDimensions();\n }.bind(this));\n }\n\n // Add panels\n this.layout.panels.forEach(function(panel_layout) {\n this.addPanel(panel_layout);\n }.bind(this));\n\n return this;\n};\n\n/**\n * Set the dimensions for a plot, and ensure that panels are sized and positioned correctly.\n *\n * If dimensions are provided, resizes each panel proportionally to match the new plot dimensions. Otherwise,\n * calculates the appropriate plot dimensions based on all panels.\n * @param {Number} [width] If provided and larger than minimum size, set plot to this width\n * @param {Number} [height] If provided and larger than minimum size, set plot to this height\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.setDimensions = function(width, height) {\n\n var id;\n\n // Update minimum allowable width and height by aggregating minimums from panels, then apply minimums to containing element.\n var min_width = parseFloat(this.layout.min_width) || 0;\n var min_height = parseFloat(this.layout.min_height) || 0;\n for (id in this.panels) {\n min_width = Math.max(min_width, this.panels[id].layout.min_width);\n if (parseFloat(this.panels[id].layout.min_height) > 0 && parseFloat(this.panels[id].layout.proportional_height) > 0) {\n min_height = Math.max(min_height, (this.panels[id].layout.min_height / this.panels[id].layout.proportional_height));\n }\n }\n this.layout.min_width = Math.max(min_width, 1);\n this.layout.min_height = Math.max(min_height, 1);\n d3.select(this.svg.node().parentNode).style({\n 'min-width': this.layout.min_width + 'px',\n 'min-height': this.layout.min_height + 'px'\n });\n\n // If width and height arguments were passed then adjust them against plot minimums if necessary.\n // Then resize the plot and proportionally resize panels to fit inside the new plot dimensions.\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n // Override discrete values if resizing responsively\n if (this.layout.responsive_resize) {\n // All resize modes will affect width\n if (this.svg) {\n this.layout.width = Math.max(this.svg.node().parentNode.getBoundingClientRect().width, this.layout.min_width);\n }\n\n if (this.layout.responsive_resize === 'both') { // Then also change the height\n this.layout.height = this.layout.width / this.layout.aspect_ratio;\n if (this.layout.height < this.layout.min_height) {\n this.layout.height = this.layout.min_height;\n this.layout.width = this.layout.height * this.layout.aspect_ratio;\n }\n }\n }\n // Resize/reposition panels to fit, update proportional origins if necessary\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n var panel_width = this.layout.width;\n var panel_height = this.panels[panel_id].layout.proportional_height * this.layout.height;\n this.panels[panel_id].setDimensions(panel_width, panel_height);\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n this.panels[panel_id].layout.proportional_origin.y = y_offset / this.layout.height;\n y_offset += panel_height;\n this.panels[panel_id].dashboard.update();\n }.bind(this));\n }\n\n // If width and height arguments were NOT passed (and panels exist) then determine the plot dimensions\n // by making it conform to panel dimensions, assuming panels are already positioned correctly.\n else if (Object.keys(this.panels).length) {\n this.layout.width = 0;\n this.layout.height = 0;\n for (id in this.panels) {\n this.layout.width = Math.max(this.panels[id].layout.width, this.layout.width);\n this.layout.height += this.panels[id].layout.height;\n }\n this.layout.width = Math.max(this.layout.width, this.layout.min_width);\n this.layout.height = Math.max(this.layout.height, this.layout.min_height);\n }\n\n // Keep aspect ratio in agreement with dimensions\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n\n // Apply layout width and height as discrete values or viewbox values\n if (this.svg !== null) {\n if (this.layout.responsive_resize === 'both') {\n this.svg\n .attr('viewBox', '0 0 ' + this.layout.width + ' ' + this.layout.height)\n .attr('preserveAspectRatio', 'xMinYMin meet');\n } else {\n this.svg.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n }\n\n // If the plot has been initialized then trigger some necessary render functions\n if (this.initialized) {\n this.panel_boundaries.position();\n this.dashboard.update();\n this.curtain.update();\n this.loader.update();\n }\n\n return this.emit('layout_changed');\n};\n\n/**\n * Create a new panel from a layout, and handle the work of initializing and placing the panel on the plot\n * @param {Object} layout\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Plot.prototype.addPanel = function(layout) {\n\n // Sanity checks\n if (typeof layout !== 'object') {\n throw new Error('Invalid panel layout passed to LocusZoom.Plot.prototype.addPanel()');\n }\n\n // Create the Panel and set its parent\n var panel = new LocusZoom.Panel(layout, this);\n\n // Store the Panel on the Plot\n this.panels[panel.id] = panel;\n\n // If a discrete y_index was set in the layout then adjust other panel y_index values to accommodate this one\n if (panel.layout.y_index !== null && !isNaN(panel.layout.y_index)\n && this.panel_ids_by_y_index.length > 0) {\n // Negative y_index values should count backwards from the end, so convert negatives to appropriate values here\n if (panel.layout.y_index < 0) {\n panel.layout.y_index = Math.max(this.panel_ids_by_y_index.length + panel.layout.y_index, 0);\n }\n this.panel_ids_by_y_index.splice(panel.layout.y_index, 0, panel.id);\n this.applyPanelYIndexesToPanelLayouts();\n } else {\n var length = this.panel_ids_by_y_index.push(panel.id);\n this.panels[panel.id].layout.y_index = length - 1;\n }\n\n // Determine if this panel was already in the layout.panels array.\n // If it wasn't, add it. Either way store the layout.panels array index on the panel.\n var layout_idx = null;\n this.layout.panels.forEach(function(panel_layout, idx) {\n if (panel_layout.id === panel.id) { layout_idx = idx; }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.panels.push(this.panels[panel.id].layout) - 1;\n }\n this.panels[panel.id].layout_idx = layout_idx;\n\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n this.positionPanels();\n // Initialize and load data into the new panel\n this.panels[panel.id].initialize();\n this.panels[panel.id].reMap();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n\n return this.panels[panel.id];\n};\n\n\n/**\n * Clear all state, tooltips, and other persisted data associated with one (or all) panel(s) in the plot\n *\n * This is useful when reloading an existing plot with new data, eg \"click for genome region\" links.\n * This is a utility method for custom usage. It is not fired automatically during normal rerender of existing panels\n * @param {String} [panelId] If provided, clear state for only this panel. Otherwise, clear state for all panels.\n * @param {('wipe'|'reset')} [mode='wipe'] Optionally specify how state should be cleared. `wipe` deletes all data\n * and is useful for when the panel is being removed; `reset` is best when the panel will be reused in place.\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.clearPanelData = function(panelId, mode) {\n mode = mode || 'wipe';\n\n // TODO: Add unit tests for this method\n var panelsList;\n if (panelId) {\n panelsList = [panelId];\n } else {\n panelsList = Object.keys(this.panels);\n }\n var self = this;\n panelsList.forEach(function(pid) {\n self.panels[pid].data_layer_ids_by_z_index.forEach(function(dlid) {\n var layer = self.panels[pid].data_layers[dlid];\n layer.destroyAllTooltips();\n\n delete self.layout.state[pid + '.' + dlid];\n if(mode === 'reset') {\n layer.setDefaultState();\n }\n });\n });\n return this;\n};\n\n/**\n * Remove the panel from the plot, and clear any state, tooltips, or other visual elements belonging to nested content\n * @param {String} id\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.removePanel = function(id) {\n if (!this.panels[id]) {\n throw new Error('Unable to remove panel, ID not found: ' + id);\n }\n\n // Hide all panel boundaries\n this.panel_boundaries.hide();\n\n // Destroy all tooltips and state vars for all data layers on the panel\n this.clearPanelData(id);\n\n // Remove all panel-level HTML overlay elements\n this.panels[id].loader.hide();\n this.panels[id].dashboard.destroy(true);\n this.panels[id].curtain.hide();\n\n // Remove the svg container for the panel if it exists\n if (this.panels[id].svg.container) {\n this.panels[id].svg.container.remove();\n }\n\n // Delete the panel and its presence in the plot layout and state\n this.layout.panels.splice(this.panels[id].layout_idx, 1);\n delete this.panels[id];\n delete this.layout.state[id];\n\n // Update layout_idx values for all remaining panels\n this.layout.panels.forEach(function(panel_layout, idx) {\n this.panels[panel_layout.id].layout_idx = idx;\n }.bind(this));\n\n // Remove the panel id from the y_index array\n this.panel_ids_by_y_index.splice(this.panel_ids_by_y_index.indexOf(id), 1);\n this.applyPanelYIndexesToPanelLayouts();\n\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n // Allow the plot to shrink when panels are removed, by forcing it to recalculate min dimensions from scratch\n this.layout.min_height = this._base_layout.min_height;\n this.layout.min_width = this._base_layout.min_width;\n\n this.positionPanels();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n\n this.emit('panel_removed', id);\n\n return this;\n};\n\n\n/**\n * Automatically position panels based on panel positioning rules and values.\n * Keep panels from overlapping vertically by adjusting origins, and keep the sum of proportional heights at 1.\n *\n * TODO: This logic currently only supports dynamic positioning of panels to prevent overlap in a VERTICAL orientation.\n * Some framework exists for positioning panels in horizontal orientations as well (width, proportional_width, origin.x, etc.)\n * but the logic for keeping these user-definable values straight approaches the complexity of a 2D box-packing algorithm.\n * That's complexity we don't need right now, and may not ever need, so it's on hiatus until a use case materializes.\n */\nLocusZoom.Plot.prototype.positionPanels = function() {\n\n var id;\n\n // We want to enforce that all x-linked panels have consistent horizontal margins\n // (to ensure that aligned items stay aligned despite inconsistent initial layout parameters)\n // NOTE: This assumes panels have consistent widths already. That should probably be enforced too!\n var x_linked_margins = { left: 0, right: 0 };\n\n // Proportional heights for newly added panels default to null unless explicitly set, so determine appropriate\n // proportional heights for all panels with a null value from discretely set dimensions.\n // Likewise handle default nulls for proportional widths, but instead just force a value of 1 (full width)\n for (id in this.panels) {\n if (this.panels[id].layout.proportional_height === null) {\n this.panels[id].layout.proportional_height = this.panels[id].layout.height / this.layout.height;\n }\n if (this.panels[id].layout.proportional_width === null) {\n this.panels[id].layout.proportional_width = 1;\n }\n if (this.panels[id].layout.interaction.x_linked) {\n x_linked_margins.left = Math.max(x_linked_margins.left, this.panels[id].layout.margin.left);\n x_linked_margins.right = Math.max(x_linked_margins.right, this.panels[id].layout.margin.right);\n }\n }\n\n // Sum the proportional heights and then adjust all proportionally so that the sum is exactly 1\n var total_proportional_height = this.sumProportional('height');\n if (!total_proportional_height) {\n return this;\n }\n var proportional_adjustment = 1 / total_proportional_height;\n for (id in this.panels) {\n this.panels[id].layout.proportional_height *= proportional_adjustment;\n }\n\n // Update origins on all panels without changing plot-level dimensions yet\n // Also apply x-linked margins to x-linked panels, updating widths as needed\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n y_offset += this.panels[panel_id].layout.height;\n if (this.panels[panel_id].layout.interaction.x_linked) {\n var delta = Math.max(x_linked_margins.left - this.panels[panel_id].layout.margin.left, 0)\n + Math.max(x_linked_margins.right - this.panels[panel_id].layout.margin.right, 0);\n this.panels[panel_id].layout.width += delta;\n this.panels[panel_id].layout.margin.left = x_linked_margins.left;\n this.panels[panel_id].layout.margin.right = x_linked_margins.right;\n this.panels[panel_id].layout.cliparea.origin.x = x_linked_margins.left;\n }\n }.bind(this));\n var calculated_plot_height = y_offset;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].layout.proportional_origin.y = this.panels[panel_id].layout.origin.y / calculated_plot_height;\n }.bind(this));\n\n // Update dimensions on the plot to accommodate repositioned panels\n this.setDimensions();\n\n // Set dimensions on all panels using newly set plot-level dimensions and panel-level proportional dimensions\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].setDimensions(this.layout.width * this.panels[panel_id].layout.proportional_width,\n this.layout.height * this.panels[panel_id].layout.proportional_height);\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Prepare the first rendering of the plot. This includes initializing the individual panels, but also creates shared\n * elements such as mouse events, panel guides/boundaries, and loader/curtain.\n *\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.initialize = function() {\n\n // Ensure proper responsive class is present on the containing node if called for\n if (this.layout.responsive_resize) {\n d3.select(this.container).classed('lz-container-responsive', true);\n }\n\n // Create an element/layer for containing mouse guides\n if (this.layout.mouse_guide) {\n var mouse_guide_svg = this.svg.append('g')\n .attr('class', 'lz-mouse_guide').attr('id', this.id + '.mouse_guide');\n var mouse_guide_vertical_svg = mouse_guide_svg.append('rect')\n .attr('class', 'lz-mouse_guide-vertical').attr('x',-1);\n var mouse_guide_horizontal_svg = mouse_guide_svg.append('rect')\n .attr('class', 'lz-mouse_guide-horizontal').attr('y',-1);\n this.mouse_guide = {\n svg: mouse_guide_svg,\n vertical: mouse_guide_vertical_svg,\n horizontal: mouse_guide_horizontal_svg\n };\n }\n\n // Add curtain and loader prototpyes to the plot\n this.curtain = LocusZoom.generateCurtain.call(this);\n this.loader = LocusZoom.generateLoader.call(this);\n\n // Create the panel_boundaries object with show/position/hide methods\n this.panel_boundaries = {\n parent: this,\n hide_timeout: null,\n showing: false,\n dragging: false,\n selectors: [],\n corner_selector: null,\n show: function() {\n // Generate panel boundaries\n if (!this.showing && !this.parent.curtain.showing) {\n this.showing = true;\n // Loop through all panels to create a horizontal boundary for each\n this.parent.panel_ids_by_y_index.forEach(function(panel_id, panel_idx) {\n var selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip')\n .attr('class', 'lz-panel-boundary')\n .attr('title', 'Resize panel');\n selector.append('span');\n var panel_resize_drag = d3.behavior.drag();\n panel_resize_drag.on('dragstart', function() { this.dragging = true; }.bind(this));\n panel_resize_drag.on('dragend', function() { this.dragging = false; }.bind(this));\n panel_resize_drag.on('drag', function() {\n // First set the dimensions on the panel we're resizing\n var this_panel = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]];\n var original_panel_height = this_panel.layout.height;\n this_panel.setDimensions(this_panel.layout.width, this_panel.layout.height + d3.event.dy);\n var panel_height_change = this_panel.layout.height - original_panel_height;\n var new_calculated_plot_height = this.parent.layout.height + panel_height_change;\n // Next loop through all panels.\n // Update proportional dimensions for all panels including the one we've resized using discrete heights.\n // Reposition panels with a greater y-index than this panel to their appropriate new origin.\n this.parent.panel_ids_by_y_index.forEach(function(loop_panel_id, loop_panel_idx) {\n var loop_panel = this.parent.panels[this.parent.panel_ids_by_y_index[loop_panel_idx]];\n loop_panel.layout.proportional_height = loop_panel.layout.height / new_calculated_plot_height;\n if (loop_panel_idx > panel_idx) {\n loop_panel.setOrigin(loop_panel.layout.origin.x, loop_panel.layout.origin.y + panel_height_change);\n loop_panel.dashboard.position();\n }\n }.bind(this));\n // Reset dimensions on the entire plot and reposition panel boundaries\n this.parent.positionPanels();\n this.position();\n }.bind(this));\n selector.call(panel_resize_drag);\n this.parent.panel_boundaries.selectors.push(selector);\n }.bind(this));\n // Create a corner boundary / resize element on the bottom-most panel that resizes the entire plot\n var corner_selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip')\n .attr('class', 'lz-panel-corner-boundary')\n .attr('title', 'Resize plot');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-outer');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-inner');\n var corner_drag = d3.behavior.drag();\n corner_drag.on('dragstart', function() { this.dragging = true; }.bind(this));\n corner_drag.on('dragend', function() { this.dragging = false; }.bind(this));\n corner_drag.on('drag', function() {\n this.setDimensions(this.layout.width + d3.event.dx, this.layout.height + d3.event.dy);\n }.bind(this.parent));\n corner_selector.call(corner_drag);\n this.parent.panel_boundaries.corner_selector = corner_selector;\n }\n return this.position();\n },\n position: function() {\n if (!this.showing) { return this; }\n // Position panel boundaries\n var plot_page_origin = this.parent.getPageOrigin();\n this.selectors.forEach(function(selector, panel_idx) {\n var panel_page_origin = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].getPageOrigin();\n var left = plot_page_origin.x;\n var top = panel_page_origin.y + this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].layout.height - 12;\n var width = this.parent.layout.width - 1;\n selector.style({\n top: top + 'px',\n left: left + 'px',\n width: width + 'px'\n });\n selector.select('span').style({\n width: width + 'px'\n });\n }.bind(this));\n // Position corner selector\n var corner_padding = 10;\n var corner_size = 16;\n this.corner_selector.style({\n top: (plot_page_origin.y + this.parent.layout.height - corner_padding - corner_size) + 'px',\n left: (plot_page_origin.x + this.parent.layout.width - corner_padding - corner_size) + 'px'\n });\n return this;\n },\n hide: function() {\n if (!this.showing) { return this; }\n this.showing = false;\n // Remove panel boundaries\n this.selectors.forEach(function(selector) { selector.remove(); });\n this.selectors = [];\n // Remove corner boundary\n this.corner_selector.remove();\n this.corner_selector = null;\n return this;\n }\n };\n\n // Show panel boundaries stipulated by the layout (basic toggle, only show on mouse over plot)\n if (this.layout.panel_boundaries) {\n d3.select(this.svg.node().parentNode).on('mouseover.' + this.id + '.panel_boundaries', function() {\n clearTimeout(this.panel_boundaries.hide_timeout);\n this.panel_boundaries.show();\n }.bind(this));\n d3.select(this.svg.node().parentNode).on('mouseout.' + this.id + '.panel_boundaries', function() {\n this.panel_boundaries.hide_timeout = setTimeout(function() {\n this.panel_boundaries.hide();\n }.bind(this), 300);\n }.bind(this));\n }\n\n // Create the dashboard object and immediately show it\n this.dashboard = new LocusZoom.Dashboard(this).show();\n\n // Initialize all panels\n for (var id in this.panels) {\n this.panels[id].initialize();\n }\n\n // Define plot-level mouse events\n var namespace = '.' + this.id;\n if (this.layout.mouse_guide) {\n var mouseout_mouse_guide = function() {\n this.mouse_guide.vertical.attr('x', -1);\n this.mouse_guide.horizontal.attr('y', -1);\n }.bind(this);\n var mousemove_mouse_guide = function() {\n var coords = d3.mouse(this.svg.node());\n this.mouse_guide.vertical.attr('x', coords[0]);\n this.mouse_guide.horizontal.attr('y', coords[1]);\n }.bind(this);\n this.svg\n .on('mouseout' + namespace + '-mouse_guide', mouseout_mouse_guide)\n .on('touchleave' + namespace + '-mouse_guide', mouseout_mouse_guide)\n .on('mousemove' + namespace + '-mouse_guide', mousemove_mouse_guide);\n }\n var mouseup = function() {\n this.stopDrag();\n }.bind(this);\n var mousemove = function() {\n if (this.interaction.dragging) {\n var coords = d3.mouse(this.svg.node());\n if (d3.event) { d3.event.preventDefault(); }\n this.interaction.dragging.dragged_x = coords[0] - this.interaction.dragging.start_x;\n this.interaction.dragging.dragged_y = coords[1] - this.interaction.dragging.start_y;\n this.panels[this.interaction.panel_id].render();\n this.interaction.linked_panel_ids.forEach(function(panel_id) {\n this.panels[panel_id].render();\n }.bind(this));\n }\n }.bind(this);\n this.svg\n .on('mouseup' + namespace, mouseup)\n .on('touchend' + namespace, mouseup)\n .on('mousemove' + namespace, mousemove)\n .on('touchmove' + namespace, mousemove);\n\n // Add an extra namespaced mouseup handler to the containing body, if there is one\n // This helps to stop interaction events gracefully when dragging outside of the plot element\n if (!d3.select('body').empty()) {\n d3.select('body')\n .on('mouseup' + namespace, mouseup)\n .on('touchend' + namespace, mouseup);\n }\n\n this.on('match_requested', function(eventData) {\n // Layers can broadcast that a specific point has been selected, and the plot will tell every other layer\n // to look for that value. Whenever a point is de-selected, it clears the match.\n var data = eventData.data;\n var to_send = (data.active ? data.value : null);\n this.applyState({ lz_match_value: to_send });\n }.bind(this));\n\n this.initialized = true;\n\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n var client_rect = this.svg.node().getBoundingClientRect();\n var width = client_rect.width ? client_rect.width : this.layout.width;\n var height = client_rect.height ? client_rect.height : this.layout.height;\n this.setDimensions(width, height);\n\n return this;\n\n};\n\n/**\n * Refresh (or fetch) a plot's data from sources, regardless of whether position or state has changed\n * @returns {Promise}\n */\nLocusZoom.Plot.prototype.refresh = function() {\n return this.applyState();\n};\n\n\n/**\n * A user-defined callback function that can receive (and potentially act on) new plot data.\n * @callback externalDataCallback\n * @param {Object} new_data The body resulting from a data request. This represents the same information that would be passed to\n * a data layer making an equivalent request.\n */\n\n/**\n * A user-defined callback function that can respond to errors received during a previous operation\n * @callback externalErrorCallback\n * @param err A representation of the error that occurred\n */\n\n/**\n * Allow newly fetched data to be made available outside the LocusZoom plot. For example, a callback could be\n * registered to draw an HTML table of top GWAS hits, and update that table whenever the plot region changes.\n *\n * This is a convenience method for external hooks. It registers an event listener and returns parsed data,\n * using the same fields syntax and underlying methods as data layers.\n *\n * @param {String[]} fields An array of field names and transforms, in the same syntax used by a data layer.\n * Different data sources should be prefixed by the source name.\n * @param {externalDataCallback} success_callback Used defined function that is automatically called any time that\n * new data is received by the plot.\n * @param {Object} [opts] Options\n * @param {externalErrorCallback} [opts.onerror] User defined function that is automatically called if a problem\n * occurs during the data request or subsequent callback operations\n * @param {boolean} [opts.discrete=false] Normally the callback will subscribe to the combined body from the chain,\n * which may not be in a format that matches what the external callback wants to do. If discrete=true, returns the\n * uncombined record info\n * @return {function} The newly created event listener, to allow for later cleanup/removal\n */\nLocusZoom.Plot.prototype.subscribeToData = function(fields, success_callback, opts) {\n opts = opts || {};\n\n // Register an event listener that is notified whenever new data has been rendered\n var error_callback = opts.onerror || function(err) {\n console.log('An error occurred while acting on an external callback', err);\n };\n var self = this;\n\n var listener = function() {\n try {\n self.lzd.getData(self.state, fields)\n .then(function (new_data) {\n success_callback(opts.discrete ? new_data.discrete : new_data.body);\n }).catch(error_callback);\n } catch (error) {\n // In certain cases, errors are thrown before a promise can be generated, and LZ error display seems to rely on these errors bubbling up\n error_callback(error);\n }\n };\n this.on('data_rendered', listener);\n return listener;\n};\n\n/**\n * Update state values and trigger a pull for fresh data on all data sources for all data layers\n * @param state_changes\n * @returns {Promise} A promise that resolves when all data fetch and update operations are complete\n */\nLocusZoom.Plot.prototype.applyState = function(state_changes) {\n state_changes = state_changes || {};\n if (typeof state_changes != 'object') {\n throw new Error('LocusZoom.applyState only accepts an object; ' + (typeof state_changes) + ' given');\n }\n\n // First make a copy of the current (old) state to work with\n var new_state = JSON.parse(JSON.stringify(this.state));\n\n // Apply changes by top-level property to the new state\n for (var property in state_changes) {\n new_state[property] = state_changes[property];\n }\n\n // Validate the new state (may do nothing, may do a lot, depends on how the user has things set up)\n new_state = LocusZoom.validateState(new_state, this.layout);\n\n // Apply new state to the actual state\n for (property in new_state) {\n this.state[property] = new_state[property];\n }\n\n // Generate requests for all panels given new state\n this.emit('data_requested');\n this.remap_promises = [];\n this.loading_data = true;\n for (var id in this.panels) {\n this.remap_promises.push(this.panels[id].reMap());\n }\n\n return Promise.all(this.remap_promises)\n .catch(function(error) {\n console.error(error);\n this.curtain.show(error.message || error);\n this.loading_data = false;\n }.bind(this))\n .then(function() {\n // Update dashboard / components\n this.dashboard.update();\n\n // Apply panel-level state values\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n var panel = this.panels[panel_id];\n panel.dashboard.update();\n // Apply data-layer-level state values\n panel.data_layer_ids_by_z_index.forEach(function(data_layer_id) {\n var data_layer = this.data_layers[data_layer_id];\n var state_id = panel_id + '.' + data_layer_id;\n for (var property in this.state[state_id]) {\n if (!this.state[state_id].hasOwnProperty(property)) { continue; }\n if (Array.isArray(this.state[state_id][property])) {\n this.state[state_id][property].forEach(function(element_id) {\n try {\n this.setElementStatus(property, this.getElementById(element_id), true);\n } catch (e) {\n console.warn('Unable to apply state: ' + state_id + ', ' + property);\n console.error(e);\n }\n }.bind(data_layer));\n }\n }\n }.bind(panel));\n }.bind(this));\n\n // Emit events\n this.emit('layout_changed');\n this.emit('data_rendered');\n this.emit('state_changed', state_changes);\n\n this.loading_data = false;\n\n }.bind(this));\n};\n\n/**\n * Register interactions along the specified axis, provided that the target panel allows interaction.\n *\n * @param {LocusZoom.Panel} panel\n * @param {('x_tick'|'y1_tick'|'y2_tick')} method The direction (axis) along which dragging is being performed.\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.startDrag = function(panel, method) {\n\n panel = panel || null;\n method = method || null;\n\n var axis = null;\n switch (method) {\n case 'background':\n case 'x_tick':\n axis = 'x';\n break;\n case 'y1_tick':\n axis = 'y1';\n break;\n case 'y2_tick':\n axis = 'y2';\n break;\n }\n\n if (!(panel instanceof LocusZoom.Panel) || !axis || !this.canInteract()) { return this.stopDrag(); }\n\n var coords = d3.mouse(this.svg.node());\n this.interaction = {\n panel_id: panel.id,\n linked_panel_ids: panel.getLinkedPanelIds(axis),\n dragging: {\n method: method,\n start_x: coords[0],\n start_y: coords[1],\n dragged_x: 0,\n dragged_y: 0,\n axis: axis\n }\n };\n\n this.svg.style('cursor', 'all-scroll');\n\n return this;\n\n};\n\n/**\n * Process drag interactions across the target panel and synchronize plot state across other panels in sync;\n * clear the event when complete\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.stopDrag = function() {\n\n if (!this.interaction.dragging) { return this; }\n\n if (typeof this.panels[this.interaction.panel_id] != 'object') {\n this.interaction = {};\n return this;\n }\n var panel = this.panels[this.interaction.panel_id];\n\n // Helper function to find the appropriate axis layouts on child data layers\n // Once found, apply the extent as floor/ceiling and remove all other directives\n // This forces all associated axes to conform to the extent generated by a drag action\n var overrideAxisLayout = function(axis, axis_number, extent) {\n panel.data_layer_ids_by_z_index.forEach(function(id) {\n if (panel.data_layers[id].layout[axis + '_axis'].axis === axis_number) {\n panel.data_layers[id].layout[axis + '_axis'].floor = extent[0];\n panel.data_layers[id].layout[axis + '_axis'].ceiling = extent[1];\n delete panel.data_layers[id].layout[axis + '_axis'].lower_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].upper_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].min_extent;\n delete panel.data_layers[id].layout[axis + '_axis'].ticks;\n }\n });\n };\n\n switch(this.interaction.dragging.method) {\n case 'background':\n case 'x_tick':\n if (this.interaction.dragging.dragged_x !== 0) {\n overrideAxisLayout('x', 1, panel.x_extent);\n this.applyState({ start: panel.x_extent[0], end: panel.x_extent[1] });\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n if (this.interaction.dragging.dragged_y !== 0) {\n // TODO: Hardcoded assumption of only two possible axes with single-digit #s (switch/case)\n var y_axis_number = parseInt(this.interaction.dragging.method[1]);\n overrideAxisLayout('y', y_axis_number, panel['y' + y_axis_number + '_extent']);\n }\n break;\n }\n\n this.interaction = {};\n this.svg.style('cursor', null);\n\n return this;\n\n};\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A panel is an abstract class representing a subdivision of the LocusZoom stage\n * to display a distinct data representation as a collection of data layers.\n * @class\n * @param {Object} layout\n * @param {LocusZoom.Plot|null} parent\n*/\nLocusZoom.Panel = function(layout, parent) {\n\n if (typeof layout !== 'object') {\n throw new Error('Unable to create panel, invalid layout');\n }\n\n /** @member {LocusZoom.Plot|null} */\n this.parent = parent || null;\n /** @member {LocusZoom.Plot|null} */\n this.parent_plot = parent;\n\n // Ensure a valid ID is present. If there is no valid ID then generate one\n if (typeof layout.id !== 'string' || !layout.id.length) {\n if (!this.parent) {\n layout.id = 'p' + Math.floor(Math.random() * Math.pow(10,8));\n } else {\n var id = null;\n var generateID = function() {\n id = 'p' + Math.floor(Math.random() * Math.pow(10,8));\n if (id == null || typeof this.parent.panels[id] != 'undefined') {\n id = generateID();\n }\n }.bind(this);\n layout.id = id;\n }\n } else if (this.parent) {\n if (typeof this.parent.panels[layout.id] !== 'undefined') {\n throw new Error('Cannot create panel with id [' + layout.id + ']; panel with that id already exists');\n }\n }\n /** @member {String} */\n this.id = layout.id;\n\n /** @member {Boolean} */\n this.initialized = false;\n /**\n * The index of this panel in the parent plot's `layout.panels`\n * @member {number}\n * */\n this.layout_idx = null;\n /** @member {Object} */\n this.svg = {};\n\n /**\n * A JSON-serializable object used to describe the composition of the Panel\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.Panel.DefaultLayout);\n\n // Define state parameters specific to this panel\n if (this.parent) {\n /** @member {Object} */\n this.state = this.parent.state;\n\n /** @member {String} */\n this.state_id = this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n } else {\n this.state = null;\n this.state_id = null;\n }\n\n /** @member {Object} */\n this.data_layers = {};\n /** @member {String[]} */\n this.data_layer_ids_by_z_index = [];\n\n /** @protected */\n this.applyDataLayerZIndexesToDataLayerLayouts = function() {\n this.data_layer_ids_by_z_index.forEach(function(dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n }.bind(this);\n\n /**\n * Track data requests in progress\n * @member {Promise[]}\n * @protected\n */\n this.data_promises = [];\n\n /** @member {d3.scale} */\n this.x_scale = null;\n /** @member {d3.scale} */\n this.y1_scale = null;\n /** @member {d3.scale} */\n this.y2_scale = null;\n\n /** @member {d3.extent} */\n this.x_extent = null;\n /** @member {d3.extent} */\n this.y1_extent = null;\n /** @member {d3.extent} */\n this.y2_extent = null;\n\n /** @member {Number[]} */\n this.x_ticks = [];\n /** @member {Number[]} */\n this.y1_ticks = [];\n /** @member {Number[]} */\n this.y2_ticks = [];\n\n /**\n * A timeout ID as returned by setTimeout\n * @protected\n * @member {number}\n */\n this.zoom_timeout = null;\n\n /** @returns {string} */\n this.getBaseId = function() {\n return this.parent.id + '.' + this.id;\n };\n\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [],\n 'element_selection': [],\n 'match_requested': [] // A data layer is attempting to highlight matching points (internal use only)\n };\n\n /**\n * There are several events that a LocusZoom panel can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following panel-level events are currently supported:\n * - `layout_changed` - context: panel - Any aspect of the panel's layout (including dimensions or state) has changed.\n * - `data_requested` - context: panel - A request for new data from any data source used in the panel has been made.\n * - `data_rendered` - context: panel - Data from a request has been received and rendered in the panel.\n * - `element_clicked` - context: panel - A data element in any of the panel's data layers has been clicked.\n * - `element_selection` - context: panel - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `panel.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * panel itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of the event (as defined in `event_hooks`)\n * @param {function} hook\n * @returns {function} The registered event listener\n */\n this.on = function(event, hook) {\n // TODO: Dry plot and panel event code into a shared mixin\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Panel}\n */\n this.off = function(event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n *\n * There is a shorter overloaded form of this method: if the event does not have any data, the second\n * argument can be a boolean to control bubbling\n *\n * @param {string} event A known event name\n * @param {*} [eventData] Data or event description that will be passed to the event listener\n * @param {boolean} [bubble=false] Whether to bubble the event to the parent\n * @returns {LocusZoom.Panel}\n */\n this.emit = function(event, eventData, bubble) {\n bubble = bubble || false;\n\n // TODO: DRY this with the parent plot implementation. Ensure interfaces remain compatible.\n // TODO: Improve documentation for overloaded method signature (JSDoc may have trouble here)\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n if (typeof eventData === 'boolean' && arguments.length === 2) {\n // Overloaded method signature: emit(event, bubble)\n bubble = eventData;\n eventData = null;\n }\n var sourceID = this.getBaseId();\n var self = this;\n var eventContext = {sourceID: sourceID, data: eventData || null};\n this.event_hooks[event].forEach(function(hookToRun) {\n // By default, any handlers fired here will see the panel as the value of `this`. If a bound function is\n // registered as a handler, the previously bound `this` will override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n if (bubble && this.parent) {\n this.parent.emit(event, eventContext);\n }\n return this;\n };\n\n /**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\n this.getPageOrigin = function() {\n var plot_origin = this.parent.getPageOrigin();\n return {\n x: plot_origin.x + this.layout.origin.x,\n y: plot_origin.y + this.layout.origin.y\n };\n };\n\n // Initialize the layout\n this.initializeLayout();\n\n return this;\n\n};\n\n/**\n * Default panel layout\n * @static\n * @type {Object}\n */\nLocusZoom.Panel.DefaultLayout = {\n title: { text: '', style: {}, x: 10, y: 22 },\n y_index: null,\n width: 0,\n height: 0,\n origin: { x: 0, y: null },\n min_width: 1,\n min_height: 1,\n proportional_width: null,\n proportional_height: null,\n proportional_origin: { x: 0, y: null },\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n background_click: 'clear_selections',\n dashboard: {\n components: []\n },\n cliparea: {\n height: 0,\n width: 0,\n origin: { x: 0, y: 0 }\n },\n axes: { // These are the only axes supported!!\n x: {},\n y1: {},\n y2: {}\n },\n legend: null,\n interaction: {\n drag_background_to_pan: false,\n drag_x_ticks_to_scale: false,\n drag_y1_ticks_to_scale: false,\n drag_y2_ticks_to_scale: false,\n scroll_to_zoom: false,\n x_linked: false,\n y1_linked: false,\n y2_linked: false\n },\n data_layers: []\n};\n\n/**\n * Prepare the panel for first use by performing parameter validation, creating axes, setting default dimensions,\n * and preparing / positioning data layers as appropriate.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.initializeLayout = function() {\n\n // If the layout is missing BOTH width and proportional width then set the proportional width to 1.\n // This will default the panel to taking up the full width of the plot.\n if (this.layout.width === 0 && this.layout.proportional_width === null) {\n this.layout.proportional_width = 1;\n }\n\n // If the layout is missing BOTH height and proportional height then set the proportional height to\n // an equal share of the plot's current height.\n if (this.layout.height === 0 && this.layout.proportional_height === null) {\n var panel_count = Object.keys(this.parent.panels).length;\n if (panel_count > 0) {\n this.layout.proportional_height = (1 / panel_count);\n } else {\n this.layout.proportional_height = 1;\n }\n }\n\n // Set panel dimensions, origin, and margin\n this.setDimensions();\n this.setOrigin();\n this.setMargin();\n\n // Set ranges\n // TODO: Define stub values in constructor\n this.x_range = [0, this.layout.cliparea.width];\n this.y1_range = [this.layout.cliparea.height, 0];\n this.y2_range = [this.layout.cliparea.height, 0];\n\n // Initialize panel axes\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (!Object.keys(this.layout.axes[axis]).length || this.layout.axes[axis].render === false) {\n // The default layout sets the axis to an empty object, so set its render boolean here\n this.layout.axes[axis].render = false;\n } else {\n this.layout.axes[axis].render = true;\n this.layout.axes[axis].label = this.layout.axes[axis].label || null;\n this.layout.axes[axis].label_function = this.layout.axes[axis].label_function || null;\n }\n }.bind(this));\n\n // Add data layers (which define x and y extents)\n this.layout.data_layers.forEach(function(data_layer_layout) {\n this.addDataLayer(data_layer_layout);\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Set the dimensions for the panel. If passed with no arguments will calculate optimal size based on layout\n * directives and the available area within the plot. If passed discrete width (number) and height (number) will\n * attempt to resize the panel to them, but may be limited by minimum dimensions defined on the plot or panel.\n *\n * @public\n * @param {number} [width]\n * @param {number} [height]\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setDimensions = function(width, height) {\n if (typeof width != 'undefined' && typeof height != 'undefined') {\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n }\n } else {\n if (this.layout.proportional_width !== null) {\n this.layout.width = Math.max(this.layout.proportional_width * this.parent.layout.width, this.layout.min_width);\n }\n if (this.layout.proportional_height !== null) {\n this.layout.height = Math.max(this.layout.proportional_height * this.parent.layout.height, this.layout.min_height);\n }\n }\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n if (this.svg.clipRect) {\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n if (this.initialized) {\n this.render();\n this.curtain.update();\n this.loader.update();\n this.dashboard.update();\n if (this.legend) { this.legend.position(); }\n }\n return this;\n};\n\n/**\n * Set panel origin on the plot, and re-render as appropriate\n *\n * @public\n * @param {number} x\n * @param {number} y\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setOrigin = function(x, y) {\n if (!isNaN(x) && x >= 0) { this.layout.origin.x = Math.max(Math.round(+x), 0); }\n if (!isNaN(y) && y >= 0) { this.layout.origin.y = Math.max(Math.round(+y), 0); }\n if (this.initialized) { this.render(); }\n return this;\n};\n\n/**\n * Set margins around this panel\n * @public\n * @param {number} top\n * @param {number} right\n * @param {number} bottom\n * @param {number} left\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setMargin = function(top, right, bottom, left) {\n var extra;\n if (!isNaN(top) && top >= 0) { this.layout.margin.top = Math.max(Math.round(+top), 0); }\n if (!isNaN(right) && right >= 0) { this.layout.margin.right = Math.max(Math.round(+right), 0); }\n if (!isNaN(bottom) && bottom >= 0) { this.layout.margin.bottom = Math.max(Math.round(+bottom), 0); }\n if (!isNaN(left) && left >= 0) { this.layout.margin.left = Math.max(Math.round(+left), 0); }\n if (this.layout.margin.top + this.layout.margin.bottom > this.layout.height) {\n extra = Math.floor(((this.layout.margin.top + this.layout.margin.bottom) - this.layout.height) / 2);\n this.layout.margin.top -= extra;\n this.layout.margin.bottom -= extra;\n }\n if (this.layout.margin.left + this.layout.margin.right > this.layout.width) {\n extra = Math.floor(((this.layout.margin.left + this.layout.margin.right) - this.layout.width) / 2);\n this.layout.margin.left -= extra;\n this.layout.margin.right -= extra;\n }\n ['top', 'right', 'bottom', 'left'].forEach(function(m) {\n this.layout.margin[m] = Math.max(this.layout.margin[m], 0);\n }.bind(this));\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n this.layout.cliparea.origin.x = this.layout.margin.left;\n this.layout.cliparea.origin.y = this.layout.margin.top;\n\n if (this.initialized) { this.render(); }\n return this;\n};\n\n/**\n * Set the title for the panel. If passed an object, will merge the object with the existing layout configuration, so\n * that all or only some of the title layout object's parameters can be customized. If passed null, false, or an empty\n * string, the title DOM element will be set to display: none.\n *\n * @param {string|object|null} title The title text, or an object with additional configuration\n * @param {string} title.text Text to display. Since titles are rendered as SVG text, HTML and newlines will not be rendered.\n * @param {number} title.x X-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n * @param {number} title.y Y-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n NOTE: SVG y values go from the top down, so the SVG origin of (0,0) is in the top left corner.\n * @param {object} title.style CSS styles object to be applied to the title's DOM element.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setTitle = function(title) {\n if (typeof this.layout.title == 'string') {\n var text = this.layout.title;\n this.layout.title = { text: text, x: 0, y: 0, style: {} };\n }\n if (typeof title == 'string') {\n this.layout.title.text = title;\n } else if (typeof title == 'object' && title !== null) {\n this.layout.title = LocusZoom.Layouts.merge(title, this.layout.title);\n }\n if (this.layout.title.text.length) {\n this.title.attr('display', null)\n .attr('x', parseFloat(this.layout.title.x))\n .attr('y', parseFloat(this.layout.title.y))\n .style(this.layout.title.style)\n .text(this.layout.title.text);\n } else {\n this.title.attr('display', 'none');\n }\n return this;\n};\n\n\n/**\n * Prepare the first rendering of the panel. This includes drawing the individual data layers, but also creates shared\n * elements such as axes, title, and loader/curtain.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.initialize = function() {\n\n // Append a container group element to house the main panel group element and the clip path\n // Position with initial layout parameters\n this.svg.container = this.parent.svg.append('g')\n .attr('id', this.getBaseId() + '.panel_container')\n .attr('transform', 'translate(' + (this.layout.origin.x || 0) + ',' + (this.layout.origin.y || 0) + ')');\n\n // Append clip path to the parent svg element, size with initial layout parameters\n var clipPath = this.svg.container.append('clipPath')\n .attr('id', this.getBaseId() + '.clip');\n this.svg.clipRect = clipPath.append('rect')\n .attr('width', this.layout.width).attr('height', this.layout.height);\n\n // Append svg group for rendering all panel child elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g')\n .attr('id', this.getBaseId() + '.panel')\n .attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n\n // Add curtain and loader prototypes to the panel\n /** @member {Object} */\n this.curtain = LocusZoom.generateCurtain.call(this);\n /** @member {Object} */\n this.loader = LocusZoom.generateLoader.call(this);\n\n /**\n * Create the dashboard object and hang components on it as defined by panel layout\n * @member {LocusZoom.Dashboard}\n */\n this.dashboard = new LocusZoom.Dashboard(this);\n\n // Inner border\n this.inner_border = this.svg.group.append('rect')\n .attr('class', 'lz-panel-background')\n .on('click', function() {\n if (this.layout.background_click === 'clear_selections') { this.clearSelections(); }\n }.bind(this));\n\n // Add the title\n /** @member {Element} */\n this.title = this.svg.group.append('text').attr('class', 'lz-panel-title');\n if (typeof this.layout.title != 'undefined') { this.setTitle(); }\n\n // Initialize Axes\n this.svg.x_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.x_axis').attr('class', 'lz-x lz-axis');\n if (this.layout.axes.x.render) {\n this.svg.x_axis_label = this.svg.x_axis.append('text')\n .attr('class', 'lz-x lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n this.svg.y1_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.y1_axis').attr('class', 'lz-y lz-y1 lz-axis');\n if (this.layout.axes.y1.render) {\n this.svg.y1_axis_label = this.svg.y1_axis.append('text')\n .attr('class', 'lz-y1 lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n this.svg.y2_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.y2_axis').attr('class', 'lz-y lz-y2 lz-axis');\n if (this.layout.axes.y2.render) {\n this.svg.y2_axis_label = this.svg.y2_axis.append('text')\n .attr('class', 'lz-y2 lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n\n // Initialize child Data Layers\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].initialize();\n }.bind(this));\n\n /**\n * Legend object, as defined by panel layout and child data layer layouts\n * @member {LocusZoom.Legend}\n * */\n this.legend = null;\n if (this.layout.legend) {\n this.legend = new LocusZoom.Legend(this);\n }\n\n // Establish panel background drag interaction mousedown event handler (on the panel background)\n if (this.layout.interaction.drag_background_to_pan) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var mousedown = function() {\n this.parent.startDrag(this, 'background');\n }.bind(this);\n this.svg.container.select('.lz-panel-background')\n .on('mousedown' + namespace + '.background', mousedown)\n .on('touchstart' + namespace + '.background', mousedown);\n }\n\n return this;\n\n};\n\n/**\n * Refresh the sort order of all data layers (called by data layer moveUp and moveDown methods)\n */\nLocusZoom.Panel.prototype.resortDataLayers = function() {\n var sort = [];\n this.data_layer_ids_by_z_index.forEach(function(id) {\n sort.push(this.data_layers[id].layout.z_index);\n }.bind(this));\n this.svg.group.selectAll('g.lz-data_layer-container').data(sort).sort(d3.ascending);\n this.applyDataLayerZIndexesToDataLayerLayouts();\n};\n\n/**\n * Get an array of panel IDs that are axis-linked to this panel\n * @param {('x'|'y1'|'y2')} axis\n * @returns {Array}\n */\nLocusZoom.Panel.prototype.getLinkedPanelIds = function(axis) {\n axis = axis || null;\n var linked_panel_ids = [];\n if (['x','y1','y2'].indexOf(axis) === -1) { return linked_panel_ids; }\n if (!this.layout.interaction[axis + '_linked']) { return linked_panel_ids; }\n this.parent.panel_ids_by_y_index.forEach(function(panel_id) {\n if (panel_id !== this.id && this.parent.panels[panel_id].layout.interaction[axis + '_linked']) {\n linked_panel_ids.push(panel_id);\n }\n }.bind(this));\n return linked_panel_ids;\n};\n\n/**\n * Move a panel up relative to others by y-index\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.moveUp = function() {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index - 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index - 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index - 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n};\n\n/**\n * Move a panel down (y-axis) relative to others in the plot\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.moveDown = function() {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index + 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index + 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index + 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n};\n\n/**\n * Create a new data layer from a provided layout object. Should have the keys specified in `DefaultLayout`\n * Will automatically add at the top (depth/z-index) of the panel unless explicitly directed differently\n * in the layout provided.\n * @param {object} layout\n * @returns {*}\n */\nLocusZoom.Panel.prototype.addDataLayer = function(layout) {\n\n // Sanity checks\n if (typeof layout !== 'object' || typeof layout.id !== 'string' || !layout.id.length) {\n throw new Error('Invalid data layer layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n if (typeof this.data_layers[layout.id] !== 'undefined') {\n throw new Error('Cannot create data_layer with id [' + layout.id + ']; data layer with that id already exists in the panel');\n }\n if (typeof layout.type !== 'string') {\n throw new Error('Invalid data layer type in layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n\n // If the layout defines a y axis make sure the axis number is set and is 1 or 2 (default to 1)\n if (typeof layout.y_axis == 'object' && (typeof layout.y_axis.axis == 'undefined' || [1,2].indexOf(layout.y_axis.axis) === -1)) {\n layout.y_axis.axis = 1;\n }\n\n // Create the Data Layer\n var data_layer = LocusZoom.DataLayers.get(layout.type, layout, this);\n\n // Store the Data Layer on the Panel\n this.data_layers[data_layer.id] = data_layer;\n\n // If a discrete z_index was set in the layout then adjust other data layer z_index values to accommodate this one\n if (data_layer.layout.z_index !== null && !isNaN(data_layer.layout.z_index)\n && this.data_layer_ids_by_z_index.length > 0) {\n // Negative z_index values should count backwards from the end, so convert negatives to appropriate values here\n if (data_layer.layout.z_index < 0) {\n data_layer.layout.z_index = Math.max(this.data_layer_ids_by_z_index.length + data_layer.layout.z_index, 0);\n }\n this.data_layer_ids_by_z_index.splice(data_layer.layout.z_index, 0, data_layer.id);\n this.data_layer_ids_by_z_index.forEach(function(dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n } else {\n var length = this.data_layer_ids_by_z_index.push(data_layer.id);\n this.data_layers[data_layer.id].layout.z_index = length - 1;\n }\n\n // Determine if this data layer was already in the layout.data_layers array.\n // If it wasn't, add it. Either way store the layout.data_layers array index on the data_layer.\n var layout_idx = null;\n this.layout.data_layers.forEach(function(data_layer_layout, idx) {\n if (data_layer_layout.id === data_layer.id) { layout_idx = idx; }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.data_layers.push(this.data_layers[data_layer.id].layout) - 1;\n }\n this.data_layers[data_layer.id].layout_idx = layout_idx;\n\n return this.data_layers[data_layer.id];\n};\n\n/**\n * Remove a data layer by id\n * @param {string} id\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.removeDataLayer = function(id) {\n if (!this.data_layers[id]) {\n throw new Error('Unable to remove data layer, ID not found: ' + id);\n }\n\n // Destroy all tooltips for the data layer\n this.data_layers[id].destroyAllTooltips();\n\n // Remove the svg container for the data layer if it exists\n if (this.data_layers[id].svg.container) {\n this.data_layers[id].svg.container.remove();\n }\n\n // Delete the data layer and its presence in the panel layout and state\n this.layout.data_layers.splice(this.data_layers[id].layout_idx, 1);\n delete this.state[this.data_layers[id].state_id];\n delete this.data_layers[id];\n\n // Remove the data_layer id from the z_index array\n this.data_layer_ids_by_z_index.splice(this.data_layer_ids_by_z_index.indexOf(id), 1);\n\n // Update layout_idx and layout.z_index values for all remaining data_layers\n this.applyDataLayerZIndexesToDataLayerLayouts();\n this.layout.data_layers.forEach(function(data_layer_layout, idx) {\n this.data_layers[data_layer_layout.id].layout_idx = idx;\n }.bind(this));\n\n return this;\n};\n\n/**\n * Clear all selections on all data layers\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.clearSelections = function() {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setAllElementStatus('selected', false);\n }.bind(this));\n return this;\n};\n\n/**\n * When the parent plot changes state, adjust the panel accordingly. For example, this may include fetching new data\n * from the API as the viewing region changes\n * @returns {Promise}\n */\nLocusZoom.Panel.prototype.reMap = function() {\n this.emit('data_requested');\n this.data_promises = [];\n\n // Remove any previous error messages before attempting to load new data\n this.curtain.hide();\n // Trigger reMap on each Data Layer\n for (var id in this.data_layers) {\n try {\n this.data_promises.push(this.data_layers[id].reMap());\n } catch (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }\n }\n // When all finished trigger a render\n return Promise.all(this.data_promises)\n .then(function() {\n this.initialized = true;\n this.render();\n this.emit('layout_changed', true);\n this.emit('data_rendered');\n }.bind(this))\n .catch(function(error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }.bind(this));\n};\n\n/**\n * Iterate over data layers to generate panel axis extents\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.generateExtents = function() {\n\n // Reset extents\n ['x', 'y1', 'y2'].forEach(function(axis) {\n this[axis + '_extent'] = null;\n }.bind(this));\n\n // Loop through the data layers\n for (var id in this.data_layers) {\n\n var data_layer = this.data_layers[id];\n\n // If defined and not decoupled, merge the x extent of the data layer with the panel's x extent\n if (data_layer.layout.x_axis && !data_layer.layout.x_axis.decoupled) {\n this.x_extent = d3.extent((this.x_extent || []).concat(data_layer.getAxisExtent('x')));\n }\n\n // If defined and not decoupled, merge the y extent of the data layer with the panel's appropriate y extent\n if (data_layer.layout.y_axis && !data_layer.layout.y_axis.decoupled) {\n var y_axis = 'y' + data_layer.layout.y_axis.axis;\n this[y_axis + '_extent'] = d3.extent((this[y_axis + '_extent'] || []).concat(data_layer.getAxisExtent('y')));\n }\n\n }\n\n // Override x_extent from state if explicitly defined to do so\n if (this.layout.axes.x && this.layout.axes.x.extent === 'state') {\n this.x_extent = [ this.state.start, this.state.end ];\n }\n\n return this;\n\n};\n\n/**\n * Generate an array of ticks for an axis. These ticks are generated in one of three ways (highest wins):\n * 1. An array of specific tick marks\n * 2. Query each data layer for what ticks are appropriate, and allow a panel-level tick configuration parameter\n * object to override the layer's default presentation settings\n * 3. Generate generic tick marks based on the extent of the data\n * @param {('x'|'y1'|'y2')} axis The string identifier of the axis\n * @returns {Number[]|Object[]} TODO: number format?\n * An array of numbers: interpreted as an array of axis value offsets for positioning.\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\nLocusZoom.Panel.prototype.generateTicks = function(axis) {\n\n // Parse an explicit 'ticks' attribute in the axis layout\n if (this.layout.axes[axis].ticks) {\n var layout = this.layout.axes[axis];\n\n var baseTickConfig = layout.ticks;\n if (Array.isArray(baseTickConfig)) {\n // Array of specific ticks hard-coded into a panel will override any ticks that an individual layer might specify\n return baseTickConfig;\n }\n\n if (typeof baseTickConfig === 'object') {\n // If the layout specifies base configuration for ticks- but without specific positions- then ask each\n // data layer to report the tick marks that it thinks it needs\n // TODO: Few layers currently need to specify custom ticks (which is ok!). But if it becomes common, consider adding mechanisms to deduplicate ticks across layers\n var self = this;\n\n // Pass any layer-specific customizations for how ticks are calculated. (styles are overridden separately)\n var config = { position: baseTickConfig.position };\n\n var combinedTicks = this.data_layer_ids_by_z_index.reduce(function(acc, data_layer_id) {\n var nextLayer = self.data_layers[data_layer_id];\n return acc.concat(nextLayer.getTicks(axis, config));\n }, []);\n\n return combinedTicks.map(function(item) {\n // The layer makes suggestions, but tick configuration params specified on the panel take precedence\n var itemConfig = {};\n itemConfig = LocusZoom.Layouts.merge(itemConfig, baseTickConfig);\n return LocusZoom.Layouts.merge(itemConfig, item);\n });\n }\n }\n\n // If no other configuration is provided, attempt to generate ticks from the extent\n if (this[axis + '_extent']) {\n return LocusZoom.prettyTicks(this[axis + '_extent'], 'both');\n }\n return [];\n};\n\n/**\n * Update rendering of this panel whenever an event triggers a redraw. Assumes that the panel has already been\n * prepared the first time via `initialize`\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.render = function() {\n\n // Position the panel container\n this.svg.container.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n\n // Set size on the clip rect\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n\n // Set and position the inner border, style if necessary\n this.inner_border\n .attr('x', this.layout.margin.left).attr('y', this.layout.margin.top)\n .attr('width', this.layout.width - (this.layout.margin.left + this.layout.margin.right))\n .attr('height', this.layout.height - (this.layout.margin.top + this.layout.margin.bottom));\n if (this.layout.inner_border) {\n this.inner_border.style({ 'stroke-width': 1, 'stroke': this.layout.inner_border });\n }\n\n // Set/update panel title if necessary\n this.setTitle();\n\n // Regenerate all extents\n this.generateExtents();\n\n // Helper function to constrain any procedurally generated vectors (e.g. ranges, extents)\n // Constraints applied here keep vectors from going to infinity or beyond a definable power of ten\n var constrain = function(value, limit_exponent) {\n var neg_min = Math.pow(-10, limit_exponent);\n var neg_max = Math.pow(-10, -limit_exponent);\n var pos_min = Math.pow(10, -limit_exponent);\n var pos_max = Math.pow(10, limit_exponent);\n if (value === Infinity) { value = pos_max; }\n if (value === -Infinity) { value = neg_min; }\n if (value === 0) { value = pos_min; }\n if (value > 0) { value = Math.max(Math.min(value, pos_max), pos_min); }\n if (value < 0) { value = Math.max(Math.min(value, neg_max), neg_min); }\n return value;\n };\n\n // Define default and shifted ranges for all axes\n var ranges = {};\n if (this.x_extent) {\n var base_x_range = { start: 0, end: this.layout.cliparea.width };\n if (this.layout.axes.x.range) {\n base_x_range.start = this.layout.axes.x.range.start || base_x_range.start;\n base_x_range.end = this.layout.axes.x.range.end || base_x_range.end;\n }\n ranges.x = [base_x_range.start, base_x_range.end];\n ranges.x_shifted = [base_x_range.start, base_x_range.end];\n }\n if (this.y1_extent) {\n var base_y1_range = { start: this.layout.cliparea.height, end: 0 };\n if (this.layout.axes.y1.range) {\n base_y1_range.start = this.layout.axes.y1.range.start || base_y1_range.start;\n base_y1_range.end = this.layout.axes.y1.range.end || base_y1_range.end;\n }\n ranges.y1 = [base_y1_range.start, base_y1_range.end];\n ranges.y1_shifted = [base_y1_range.start, base_y1_range.end];\n }\n if (this.y2_extent) {\n var base_y2_range = { start: this.layout.cliparea.height, end: 0 };\n if (this.layout.axes.y2.range) {\n base_y2_range.start = this.layout.axes.y2.range.start || base_y2_range.start;\n base_y2_range.end = this.layout.axes.y2.range.end || base_y2_range.end;\n }\n ranges.y2 = [base_y2_range.start, base_y2_range.end];\n ranges.y2_shifted = [base_y2_range.start, base_y2_range.end];\n }\n\n // Shift ranges based on any drag or zoom interactions currently underway\n if (this.parent.interaction.panel_id && (this.parent.interaction.panel_id === this.id || this.parent.interaction.linked_panel_ids.indexOf(this.id) !== -1)) {\n var anchor, scalar = null;\n if (this.parent.interaction.zooming && typeof this.x_scale == 'function') {\n var current_extent_size = Math.abs(this.x_extent[1] - this.x_extent[0]);\n var current_scaled_extent_size = Math.round(this.x_scale.invert(ranges.x_shifted[1])) - Math.round(this.x_scale.invert(ranges.x_shifted[0]));\n var zoom_factor = this.parent.interaction.zooming.scale;\n var potential_extent_size = Math.floor(current_scaled_extent_size * (1 / zoom_factor));\n if (zoom_factor < 1 && !isNaN(this.parent.layout.max_region_scale)) {\n zoom_factor = 1 / (Math.min(potential_extent_size, this.parent.layout.max_region_scale) / current_scaled_extent_size);\n } else if (zoom_factor > 1 && !isNaN(this.parent.layout.min_region_scale)) {\n zoom_factor = 1 / (Math.max(potential_extent_size, this.parent.layout.min_region_scale) / current_scaled_extent_size);\n }\n var new_extent_size = Math.floor(current_extent_size * zoom_factor);\n anchor = this.parent.interaction.zooming.center - this.layout.margin.left - this.layout.origin.x;\n var offset_ratio = anchor / this.layout.cliparea.width;\n var new_x_extent_start = Math.max(Math.floor(this.x_scale.invert(ranges.x_shifted[0]) - ((new_extent_size - current_scaled_extent_size) * offset_ratio)), 1);\n ranges.x_shifted = [ this.x_scale(new_x_extent_start), this.x_scale(new_x_extent_start + new_extent_size) ];\n } else if (this.parent.interaction.dragging) {\n switch (this.parent.interaction.dragging.method) {\n case 'background':\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n break;\n case 'x_tick':\n if (d3.event && d3.event.shiftKey) {\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n } else {\n anchor = this.parent.interaction.dragging.start_x - this.layout.margin.left - this.layout.origin.x;\n scalar = constrain(anchor / (anchor + this.parent.interaction.dragging.dragged_x), 3);\n ranges.x_shifted[0] = 0;\n ranges.x_shifted[1] = Math.max(this.layout.cliparea.width * (1 / scalar), 1);\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n var y_shifted = 'y' + this.parent.interaction.dragging.method[1] + '_shifted';\n if (d3.event && d3.event.shiftKey) {\n ranges[y_shifted][0] = this.layout.cliparea.height + this.parent.interaction.dragging.dragged_y;\n ranges[y_shifted][1] = +this.parent.interaction.dragging.dragged_y;\n } else {\n anchor = this.layout.cliparea.height - (this.parent.interaction.dragging.start_y - this.layout.margin.top - this.layout.origin.y);\n scalar = constrain(anchor / (anchor - this.parent.interaction.dragging.dragged_y), 3);\n ranges[y_shifted][0] = this.layout.cliparea.height;\n ranges[y_shifted][1] = this.layout.cliparea.height - (this.layout.cliparea.height * (1 / scalar));\n }\n }\n }\n }\n\n // Generate scales and ticks for all axes, then render them\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (!this[axis + '_extent']) { return; }\n\n // Base Scale\n this[axis + '_scale'] = d3.scale.linear()\n .domain(this[axis + '_extent'])\n .range(ranges[axis + '_shifted']);\n\n // Shift the extent\n this[axis + '_extent'] = [\n this[axis + '_scale'].invert(ranges[axis][0]),\n this[axis + '_scale'].invert(ranges[axis][1])\n ];\n\n // Finalize Scale\n this[axis + '_scale'] = d3.scale.linear()\n .domain(this[axis + '_extent']).range(ranges[axis]);\n\n // Render axis (and generate ticks as needed)\n this.renderAxis(axis);\n }.bind(this));\n\n // Establish mousewheel zoom event handers on the panel (namespacing not passed through by d3, so not used here)\n if (this.layout.interaction.scroll_to_zoom) {\n var zoom_handler = function() {\n // Look for a shift key press while scrolling to execute.\n // If not present, gracefully raise a notification and allow conventional scrolling\n if (!d3.event.shiftKey) {\n if (this.parent.canInteract(this.id)) {\n this.loader.show('Press [SHIFT] while scrolling to zoom').hide(1000);\n }\n return;\n }\n d3.event.preventDefault();\n if (!this.parent.canInteract(this.id)) { return; }\n var coords = d3.mouse(this.svg.container.node());\n var delta = Math.max(-1, Math.min(1, (d3.event.wheelDelta || -d3.event.detail || -d3.event.deltaY)));\n if (delta === 0) { return; }\n this.parent.interaction = {\n panel_id: this.id,\n linked_panel_ids: this.getLinkedPanelIds('x'),\n zooming: {\n scale: (delta < 1) ? 0.9 : 1.1,\n center: coords[0]\n }\n };\n this.render();\n this.parent.interaction.linked_panel_ids.forEach(function(panel_id) {\n this.parent.panels[panel_id].render();\n }.bind(this));\n if (this.zoom_timeout !== null) { clearTimeout(this.zoom_timeout); }\n this.zoom_timeout = setTimeout(function() {\n this.parent.interaction = {};\n this.parent.applyState({ start: this.x_extent[0], end: this.x_extent[1] });\n }.bind(this), 500);\n }.bind(this);\n this.zoom_listener = d3.behavior.zoom();\n this.svg.container.call(this.zoom_listener)\n .on('wheel.zoom', zoom_handler)\n .on('mousewheel.zoom', zoom_handler)\n .on('DOMMouseScroll.zoom', zoom_handler);\n }\n\n // Render data layers in order by z-index\n this.data_layer_ids_by_z_index.forEach(function(data_layer_id) {\n this.data_layers[data_layer_id].draw().render();\n }.bind(this));\n\n return this;\n};\n\n\n/**\n * Render ticks for a particular axis\n * @param {('x'|'y1'|'y2')} axis The identifier of the axes\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.renderAxis = function(axis) {\n\n if (['x', 'y1', 'y2'].indexOf(axis) === -1) {\n throw new Error('Unable to render axis; invalid axis identifier: ' + axis);\n }\n\n var canRender = this.layout.axes[axis].render\n && typeof this[axis + '_scale'] == 'function'\n && !isNaN(this[axis + '_scale'](0));\n\n // If the axis has already been rendered then check if we can/can't render it\n // Make sure the axis element is shown/hidden to suit\n if (this[axis + '_axis']) {\n this.svg.container.select('g.lz-axis.lz-' + axis).style('display', canRender ? null : 'none');\n }\n\n if (!canRender) { return this; }\n\n // Axis-specific values to plug in where needed\n var axis_params = {\n x: {\n position: 'translate(' + this.layout.margin.left + ',' + (this.layout.height - this.layout.margin.bottom) + ')',\n orientation: 'bottom',\n label_x: this.layout.cliparea.width / 2,\n label_y: (this.layout.axes[axis].label_offset || 0),\n label_rotate: null\n },\n y1: {\n position: 'translate(' + this.layout.margin.left + ',' + this.layout.margin.top + ')',\n orientation: 'left',\n label_x: -1 * (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n },\n y2: {\n position: 'translate(' + (this.layout.width - this.layout.margin.right) + ',' + this.layout.margin.top + ')',\n orientation: 'right',\n label_x: (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n }\n };\n\n // Generate Ticks\n this[axis + '_ticks'] = this.generateTicks(axis);\n\n // Determine if the ticks are all numbers (d3-automated tick rendering) or not (manual tick rendering)\n var ticksAreAllNumbers = (function(ticks) {\n for (var i = 0; i < ticks.length; i++) {\n if (isNaN(ticks[i])) {\n return false;\n }\n }\n return true;\n })(this[axis + '_ticks']);\n\n // Initialize the axis; set scale and orientation\n this[axis + '_axis'] = d3.svg.axis().scale(this[axis + '_scale']).orient(axis_params[axis].orientation).tickPadding(3);\n\n // Set tick values and format\n if (ticksAreAllNumbers) {\n this[axis + '_axis'].tickValues(this[axis + '_ticks']);\n if (this.layout.axes[axis].tick_format === 'region') {\n this[axis + '_axis'].tickFormat(function(d) { return LocusZoom.positionIntToString(d, 6); });\n }\n } else {\n var ticks = this[axis + '_ticks'].map(function(t) {\n return(t[axis.substr(0,1)]);\n });\n this[axis + '_axis'].tickValues(ticks)\n .tickFormat(function(t, i) { return this[axis + '_ticks'][i].text; }.bind(this));\n }\n\n // Position the axis in the SVG and apply the axis construct\n this.svg[axis + '_axis']\n .attr('transform', axis_params[axis].position)\n .call(this[axis + '_axis']);\n\n // If necessary manually apply styles and transforms to ticks as specified by the layout\n if (!ticksAreAllNumbers) {\n var tick_selector = d3.selectAll('g#' + this.getBaseId().replace('.','\\\\.') + '\\\\.' + axis + '_axis g.tick');\n var panel = this;\n tick_selector.each(function(d, i) {\n var selector = d3.select(this).select('text');\n if (panel[axis + '_ticks'][i].style) {\n selector.style(panel[axis + '_ticks'][i].style);\n }\n if (panel[axis + '_ticks'][i].transform) {\n selector.attr('transform', panel[axis + '_ticks'][i].transform);\n }\n });\n }\n\n // Render the axis label if necessary\n var label = this.layout.axes[axis].label || null;\n if (label !== null) {\n this.svg[axis + '_axis_label']\n .attr('x', axis_params[axis].label_x).attr('y', axis_params[axis].label_y)\n .text(LocusZoom.parseFields(this.state, label));\n if (axis_params[axis].label_rotate !== null) {\n this.svg[axis + '_axis_label']\n .attr('transform', 'rotate(' + axis_params[axis].label_rotate + ' ' + axis_params[axis].label_x + ',' + axis_params[axis].label_y + ')');\n }\n }\n\n // Attach interactive handlers to ticks as needed\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (this.layout.interaction['drag_' + axis + '_ticks_to_scale']) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var tick_mouseover = function() {\n if (typeof d3.select(this).node().focus == 'function') { d3.select(this).node().focus(); }\n var cursor = (axis === 'x') ? 'ew-resize' : 'ns-resize';\n if (d3.event && d3.event.shiftKey) { cursor = 'move'; }\n d3.select(this)\n .style({'font-weight': 'bold', 'cursor': cursor})\n .on('keydown' + namespace, tick_mouseover)\n .on('keyup' + namespace, tick_mouseover);\n };\n this.svg.container.selectAll('.lz-axis.lz-' + axis + ' .tick text')\n .attr('tabindex', 0) // necessary to make the tick focusable so keypress events can be captured\n .on('mouseover' + namespace, tick_mouseover)\n .on('mouseout' + namespace, function() {\n d3.select(this).style({'font-weight': 'normal'});\n d3.select(this).on('keydown' + namespace, null).on('keyup' + namespace, null);\n })\n .on('mousedown' + namespace, function() {\n this.parent.startDrag(this, axis + '_tick');\n }.bind(this));\n }\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Force the height of this panel to the largest absolute height of the data in\n * all child data layers (if not null for any child data layers)\n * @param {number|null} [target_height] A target height, which will be used in situations when the expected height can be\n * pre-calculated (eg when the layers are transitioning)\n */\nLocusZoom.Panel.prototype.scaleHeightToData = function(target_height) {\n target_height = +target_height || null;\n if (target_height === null) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n var dh = this.data_layers[id].getAbsoluteDataHeight();\n if (+dh) {\n if (target_height === null) {\n target_height = +dh;\n }\n else {\n target_height = Math.max(target_height, +dh);\n }\n }\n }.bind(this));\n }\n if (+target_height) {\n target_height += +this.layout.margin.top + +this.layout.margin.bottom;\n this.setDimensions(this.layout.width, target_height);\n this.parent.setDimensions();\n this.parent.panel_ids_by_y_index.forEach(function(id) {\n this.parent.panels[id].layout.proportional_height = null;\n }.bind(this));\n this.parent.positionPanels();\n }\n};\n\n/**\n * Methods to set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n */\nLocusZoom.Panel.prototype.setElementStatusByFilters = function(status, toggle, filters, exclusive) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setElementStatusByFilters(status, toggle, filters, exclusive);\n }.bind(this));\n};\n/**\n * Set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n */\nLocusZoom.Panel.prototype.setAllElementStatus = function(status, toggle) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setAllElementStatus(status, toggle);\n }.bind(this));\n};\n// TODO: Capture documentation for dynamically generated methods\nLocusZoom.DataLayer.Statuses.verbs.forEach(function(verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.Panel.prototype[verb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.Panel.prototype[antiverb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.Panel.prototype[verb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.Panel.prototype[antiverb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n});\n\n\n/**\n * Add a \"basic\" loader to a panel\n * This method is just a shortcut for adding the most commonly used type of loading indicator, which appears when\n * data is requested, animates (e.g. shows an infinitely cycling progress bar as opposed to one that loads from\n * 0-100% based on actual load progress), and disappears when new data is loaded and rendered.\n *\n *\n * @param {Boolean} show_immediately\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.addBasicLoader = function(show_immediately) {\n if (typeof show_immediately != 'undefined') { show_immediately = true; }\n if (show_immediately) {\n this.loader.show('Loading...').animate();\n }\n this.on('data_requested', function() {\n this.loader.show('Loading...').animate();\n }.bind(this));\n this.on('data_rendered', function() {\n this.loader.hide();\n }.bind(this));\n return this;\n};\n"]} \ No newline at end of file diff --git a/dist/locuszoom.app.min.js b/dist/locuszoom.app.min.js index ccac3fe0..5cda89f4 100644 --- a/dist/locuszoom.app.min.js +++ b/dist/locuszoom.app.min.js @@ -1,2 +1,2 @@ -!function(e,a){"function"==typeof define&&define.amd?define(["d3"],function(t){return e.LocusZoom=a(t)}):"object"==typeof module&&module.exports?module.exports=e.LocusZoom=a(require("d3")):e.LocusZoom=a(e.d3)}(this,function(t){var e,a;try{var i="3.5.6";if("object"!=typeof t)throw new Error("d3 dependency not met. Library missing.");if(!function(t,e){if(e==t)return!0;var a=t.split("."),i=e.split("."),s=!1;return a.forEach(function(t,e){!s&&+i[e]>+a[e]&&(s=!0)}),s}(i,t.version))throw new Error("d3 dependency not met. Outdated version detected.\nRequired d3 version: 3.5.6 or higher (found: "+t.version+").");e=this,a=function(f){var a,i,s,n,o,r,l,e,h,d,u,c,t,p,y,g,_,m,b,v,x,w;try{var D="3.5.6";if("object"!=typeof f)throw new Error("d3 dependency not met. Library missing.");if(!function(t,e){if(e==t)return!0;var a=t.split("."),i=e.split("."),s=!1;return a.forEach(function(t,e){!s&&+i[e]>+a[e]&&(s=!0)}),s}(D,f.version))throw new Error("d3 dependency not met. Outdated version detected.\nRequired d3 version: 3.5.6 or higher (found: "+f.version+").");var k={version:"0.10.0",populate:function(t,a,i){if(void 0===t)throw new Error("LocusZoom.populate selector not defined");var s;return f.select(t).html(""),f.select(t).call(function(){if(void 0===this.node().id){for(var t=0;!f.select("#lz-"+t).empty();)t++;this.attr("id","#lz-"+t)}if((s=new k.Plot(this.node().id,a,i)).container=this.node(),void 0!==this.node().dataset&&void 0!==this.node().dataset.region){var e=k.parsePositionQuery(this.node().dataset.region);Object.keys(e).forEach(function(t){s.state[t]=e[t]})}s.svg=f.select("div#"+s.id).append("svg").attr("version","1.1").attr("xmlns","http://www.w3.org/2000/svg").attr("id",s.id+"_svg").attr("class","lz-locuszoom").style(s.layout.style),s.setDimensions(),s.positionPanels(),s.initialize(),"object"==typeof a&&Object.keys(a).length&&s.refresh()}),s},populateAll:function(t,a,i){var s=[];return f.selectAll(t).each(function(t,e){s[e]=k.populate(this,a,i)}),s},positionIntToString:function(t,e,a){var i={0:"",3:"K",6:"M",9:"G"};if(a=a||!1,isNaN(e)||null===e){var s=Math.log(t)/Math.LN10;e=Math.min(Math.max(s-s%3,0),9)}var n=e-Math.floor((Math.log(t)/Math.LN10).toFixed(e+3)),o=Math.min(Math.max(e,0),2),r=Math.min(Math.max(n,o),12),l=""+(t/Math.pow(10,e)).toFixed(r);return a&&void 0!==i[e]&&(l+=" "+i[e]+"b"),l},positionStringToInt:function(t){var e=t.toUpperCase();e=e.replace(/,/g,"");var a=/([KMG])[B]*$/,i=a.exec(e),s=1;return i&&(s="M"===i[1]?1e6:"G"===i[1]?1e9:1e3,e=e.replace(a,"")),e=Number(e)*s},parsePositionQuery:function(t){var e=/^(\w+):([\d,.]+[kmgbKMGB]*)([-+])([\d,.]+[kmgbKMGB]*)$/.exec(t);if(e){if("+"===e[3]){var a=k.positionStringToInt(e[2]),i=k.positionStringToInt(e[4]);return{chr:e[1],start:a-i,end:a+i}}return{chr:e[1],start:k.positionStringToInt(e[2]),end:k.positionStringToInt(e[4])}}return(e=/^(\w+):([\d,.]+[kmgbKMGB]*)$/.exec(t))?{chr:e[1],position:k.positionStringToInt(e[2])}:null},prettyTicks:function(t,e,a){(void 0===a||isNaN(parseInt(a)))&&(a=5);var i=(a=parseInt(a))/3,s=Math.abs(t[0]-t[1]),n=s/a;Math.log(s)/Math.LN10<-2&&(n=.75*Math.max(Math.abs(s))/i);var o=Math.pow(10,Math.floor(Math.log(n)/Math.LN10)),r=0;o<1&&0!==o&&(r=Math.abs(Math.round(Math.log(o)/Math.LN10)));var l=o;2*o-n<1.5*(n-l)&&5*o-n<2.75*(n-(l=2*o))&&10*o-n<1.5*(n-(l=5*o))&&(l=10*o);for(var h=[],d=parseFloat((Math.floor(t[0]/l)*l).toFixed(r));dt[1]&&h.pop(),h},createCORSPromise:function(s,n,o,r,l){return new Promise(function(t,e){var a=new XMLHttpRequest;if("withCredentials"in a?a.open(s,n,!0):"undefined"!=typeof XDomainRequest?(a=new XDomainRequest).open(s,n):a=null,a){if(a.onreadystatechange=function(){4===a.readyState&&(200===a.status||0===a.status?t(a.response):e("HTTP "+a.status+" for "+n))},l&&setTimeout(e,l),o=void 0!==o?o:"",void 0!==r)for(var i in r)a.setRequestHeader(i,r[i]);a.send(o)}})},validateState:function(t,e){e=e||{};var a=!1;if(void 0!==(t=t||{}).chr&&void 0!==t.start&&void 0!==t.end){var i,s=null;if(t.start=Math.max(parseInt(t.start),1),t.end=Math.max(parseInt(t.end),1),isNaN(t.start)&&isNaN(t.end))t.start=1,t.end=1,s=.5,i=0;else if(isNaN(t.start)||isNaN(t.end))s=t.start||t.end,i=0,t.start=isNaN(t.start)?t.end:t.start,t.end=isNaN(t.end)?t.start:t.end;else{if(s=Math.round((t.start+t.end)/2),(i=t.end-t.start)<0){var n=t.start;t.end=t.start,t.start=n,i=t.end-t.start}s<0&&(t.start=1,t.end=1,i=0)}a=!0}return!isNaN(e.min_region_scale)&&a&&ie.max_region_scale&&(t.start=Math.max(s-Math.floor(e.max_region_scale/2),1),t.end=t.start+e.max_region_scale),t},parseFields:function(e,t){if("object"!=typeof e)throw new Error("LocusZoom.parseFields invalid arguments: data is not an object");if("string"!=typeof t)throw new Error("LocusZoom.parseFields invalid arguments: html is not a string");for(var a=[],i=/\{\{(?:(#if )?([A-Za-z0-9_:|]+)|(\/if))\}\}/;0{{{{namespace[assoc]}}variant|htmlescape}}
P Value: {{{{namespace[assoc]}}log_pvalue|logtoscinotation|htmlescape}}
Ref. Allele: {{{{namespace[assoc]}}ref_allele|htmlescape}}
Make LD Reference
'}),k.Layouts.add("tooltip","covariates_model_association",((v=k.Layouts.get("tooltip","standard_association",{unnamespaced:!0})).html+='Condition on Variant
',v)),k.Layouts.add("tooltip","standard_genes",{closable:!0,show:{or:["highlighted","selected"]},hide:{and:["unhighlighted","unselected"]},html:'

{{gene_name|htmlescape}}

Gene ID: {{gene_id|htmlescape}}
Transcript ID: {{transcript_id|htmlescape}}
More data on gnomAD'}),k.Layouts.add("tooltip","standard_intervals",{namespace:{intervals:"intervals"},closable:!1,show:{or:["highlighted","selected"]},hide:{and:["unhighlighted","unselected"]},html:"{{{{namespace[intervals]}}state_name|htmlescape}}
{{{{namespace[intervals]}}start|htmlescape}}-{{{{namespace[intervals]}}end|htmlescape}}"}),k.Layouts.add("tooltip","catalog_variant",{namespace:{assoc:"assoc",catalog:"catalog"},closable:!0,show:{or:["highlighted","selected"]},hide:{and:["unhighlighted","unselected"]},html:'{{{{namespace[catalog]}}variant|htmlescape}}
Catalog entries: {{n_catalog_matches|htmlescape}}
Top Trait: {{{{namespace[catalog]}}trait|htmlescape}}
Top P Value: {{{{namespace[catalog]}}log_pvalue|logtoscinotation}}
More: GWAS catalog / dbSNP'}),k.Layouts.add("data_layer","significance",{id:"significance",type:"orthogonal_line",orientation:"horizontal",offset:z}),k.Layouts.add("data_layer","recomb_rate",{namespace:{recomb:"recomb"},id:"recombrate",type:"line",fields:["{{namespace[recomb]}}position","{{namespace[recomb]}}recomb_rate"],z_index:1,style:{stroke:"#0000FF","stroke-width":"1.5px"},x_axis:{field:"{{namespace[recomb]}}position"},y_axis:{axis:2,field:"{{namespace[recomb]}}recomb_rate",floor:0,ceiling:100}}),k.Layouts.add("data_layer","association_pvalues",{namespace:{assoc:"assoc",ld:"ld"},id:"associationpvalues",type:"scatter",point_shape:{scale_function:"if",field:"{{namespace[ld]}}isrefvar",parameters:{field_value:1,then:"diamond",else:"circle"}},point_size:{scale_function:"if",field:"{{namespace[ld]}}isrefvar",parameters:{field_value:1,then:80,else:40}},color:[{scale_function:"if",field:"{{namespace[ld]}}isrefvar",parameters:{field_value:1,then:"#9632b8"}},{scale_function:"numerical_bin",field:"{{namespace[ld]}}state",parameters:{breaks:[0,.2,.4,.6,.8],values:["#357ebd","#46b8da","#5cb85c","#eea236","#d43f3a"]}},"#B8B8B8"],legend:[{shape:"diamond",color:"#9632b8",size:40,label:"LD Ref Var",class:"lz-data_layer-scatter"},{shape:"circle",color:"#d43f3a",size:40,label:"1.0 > r² ≥ 0.8",class:"lz-data_layer-scatter"},{shape:"circle",color:"#eea236",size:40,label:"0.8 > r² ≥ 0.6",class:"lz-data_layer-scatter"},{shape:"circle",color:"#5cb85c",size:40,label:"0.6 > r² ≥ 0.4",class:"lz-data_layer-scatter"},{shape:"circle",color:"#46b8da",size:40,label:"0.4 > r² ≥ 0.2",class:"lz-data_layer-scatter"},{shape:"circle",color:"#357ebd",size:40,label:"0.2 > r² ≥ 0.0",class:"lz-data_layer-scatter"},{shape:"circle",color:"#B8B8B8",size:40,label:"no r² data",class:"lz-data_layer-scatter"}],label:null,fields:["{{namespace[assoc]}}variant","{{namespace[assoc]}}position","{{namespace[assoc]}}log_pvalue","{{namespace[assoc]}}log_pvalue|logtoscinotation","{{namespace[assoc]}}ref_allele","{{namespace[ld]}}state","{{namespace[ld]}}isrefvar"],id_field:"{{namespace[assoc]}}variant",z_index:2,x_axis:{field:"{{namespace[assoc]}}position"},y_axis:{axis:1,field:"{{namespace[assoc]}}log_pvalue",floor:0,upper_buffer:.1,min_extent:[0,10]},behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},tooltip:k.Layouts.get("tooltip","standard_association",{unnamespaced:!0})}),k.Layouts.add("data_layer","association_pvalues_catalog",((b=k.Layouts.get("data_layer","association_pvalues",{unnamespaced:!0,id:"associationpvaluescatalog",fill_opacity:.7})).tooltip.html+='{{#if {{namespace[catalog]}}rsid}}
See hits in GWAS catalog{{/if}}',b.namespace.catalog="catalog",b.fields.push("{{namespace[catalog]}}rsid","{{namespace[catalog]}}trait","{{namespace[catalog]}}log_pvalue"),b)),k.Layouts.add("data_layer","phewas_pvalues",{namespace:{phewas:"phewas"},id:"phewaspvalues",type:"category_scatter",point_shape:"circle",point_size:70,tooltip_positioning:"vertical",id_field:"{{namespace[phewas]}}id",fields:["{{namespace[phewas]}}id","{{namespace[phewas]}}log_pvalue","{{namespace[phewas]}}trait_group","{{namespace[phewas]}}trait_label"],x_axis:{field:"{{namespace[phewas]}}x",category_field:"{{namespace[phewas]}}trait_group",lower_buffer:.025,upper_buffer:.025},y_axis:{axis:1,field:"{{namespace[phewas]}}log_pvalue",floor:0,upper_buffer:.15},color:[{field:"{{namespace[phewas]}}trait_group",scale_function:"categorical_bin",parameters:{categories:[],values:[],null_value:"#B8B8B8"}}],fill_opacity:.7,tooltip:{closable:!0,show:{or:["highlighted","selected"]},hide:{and:["unhighlighted","unselected"]},html:["Trait: {{{{namespace[phewas]}}trait_label|htmlescape}}
","Trait Category: {{{{namespace[phewas]}}trait_group|htmlescape}}
","P-value: {{{{namespace[phewas]}}log_pvalue|logtoscinotation|htmlescape}}
"].join("")},behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},label:{text:"{{{{namespace[phewas]}}trait_label|htmlescape}}",spacing:6,lines:{style:{"stroke-width":"2px",stroke:"#333333","stroke-dasharray":"2px 2px"}},filters:[{field:"{{namespace[phewas]}}log_pvalue",operator:">=",value:20}],style:{"font-size":"14px","font-weight":"bold",fill:"#333333"}}}),k.Layouts.add("data_layer","genes",{namespace:{gene:"gene"},id:"genes",type:"genes",fields:["{{namespace[gene]}}all"],id_field:"gene_id",behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},tooltip:k.Layouts.get("tooltip","standard_genes",{unnamespaced:!0})}),k.Layouts.add("data_layer","genome_legend",{namespace:{genome:"genome"},id:"genome_legend",type:"genome_legend",fields:["{{namespace[genome]}}chr","{{namespace[genome]}}base_pairs"],x_axis:{floor:0,ceiling:2881033286}}),k.Layouts.add("data_layer","intervals",{namespace:{intervals:"intervals"},id:"intervals",type:"intervals",fields:["{{namespace[intervals]}}start","{{namespace[intervals]}}end","{{namespace[intervals]}}state_id","{{namespace[intervals]}}state_name"],id_field:"{{namespace[intervals]}}start",start_field:"{{namespace[intervals]}}start",end_field:"{{namespace[intervals]}}end",track_split_field:"{{namespace[intervals]}}state_id",split_tracks:!0,always_hide_legend:!1,color:{field:"{{namespace[intervals]}}state_id",scale_function:"categorical_bin",parameters:{categories:[1,2,3,4,5,6,7,8,9,10,11,12,13],values:["rgb(212,63,58)","rgb(250,120,105)","rgb(252,168,139)","rgb(240,189,66)","rgb(250,224,105)","rgb(240,238,84)","rgb(244,252,23)","rgb(23,232,252)","rgb(32,191,17)","rgb(23,166,77)","rgb(32,191,17)","rgb(162,133,166)","rgb(212,212,212)"],null_value:"#B8B8B8"}},legend:[{shape:"rect",color:"rgb(212,63,58)",width:9,label:"Active Promoter","{{namespace[intervals]}}state_id":1},{shape:"rect",color:"rgb(250,120,105)",width:9,label:"Weak Promoter","{{namespace[intervals]}}state_id":2},{shape:"rect",color:"rgb(252,168,139)",width:9,label:"Poised Promoter","{{namespace[intervals]}}state_id":3},{shape:"rect",color:"rgb(240,189,66)",width:9,label:"Strong enhancer","{{namespace[intervals]}}state_id":4},{shape:"rect",color:"rgb(250,224,105)",width:9,label:"Strong enhancer","{{namespace[intervals]}}state_id":5},{shape:"rect",color:"rgb(240,238,84)",width:9,label:"Weak enhancer","{{namespace[intervals]}}state_id":6},{shape:"rect",color:"rgb(244,252,23)",width:9,label:"Weak enhancer","{{namespace[intervals]}}state_id":7},{shape:"rect",color:"rgb(23,232,252)",width:9,label:"Insulator","{{namespace[intervals]}}state_id":8},{shape:"rect",color:"rgb(32,191,17)",width:9,label:"Transcriptional transition","{{namespace[intervals]}}state_id":9},{shape:"rect",color:"rgb(23,166,77)",width:9,label:"Transcriptional elongation","{{namespace[intervals]}}state_id":10},{shape:"rect",color:"rgb(136,240,129)",width:9,label:"Weak transcribed","{{namespace[intervals]}}state_id":11},{shape:"rect",color:"rgb(162,133,166)",width:9,label:"Polycomb-repressed","{{namespace[intervals]}}state_id":12},{shape:"rect",color:"rgb(212,212,212)",width:9,label:"Heterochromatin / low signal","{{namespace[intervals]}}state_id":13}],behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},tooltip:k.Layouts.get("tooltip","standard_intervals",{unnamespaced:!0})}),k.Layouts.add("data_layer","annotation_catalog",{namespace:{assoc:"assoc",catalog:"catalog"},id:"annotation_catalog",type:"annotation_track",id_field:"{{namespace[catalog]}}variant",x_axis:{field:"{{namespace[assoc]}}position"},color:"#0000CC",fields:["{{namespace[assoc]}}variant","{{namespace[assoc]}}chromosome","{{namespace[assoc]}}position","{{namespace[catalog]}}variant","{{namespace[catalog]}}rsid","{{namespace[catalog]}}trait","{{namespace[catalog]}}log_pvalue","{{namespace[catalog]}}pos"],filters:[["{{namespace[catalog]}}rsid","!=",null],["{{namespace[catalog]}}log_pvalue",">",z]],behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},tooltip:k.Layouts.get("tooltip","catalog_variant",{unnamespaced:!0}),tooltip_positioning:"top"}),k.Layouts.add("dashboard_components","ldlz2_pop_selector",{type:"set_state",position:"right",color:"blue",button_html:"LD Population: ",show_selected:!0,button_title:"Select LD Population: ",state_field:"ld_pop",options:[{display_name:"ALL (default)",value:"ALL"},{display_name:"AFR",value:"AFR"},{display_name:"AMR",value:"AMR"},{display_name:"EAS",value:"EAS"},{display_name:"EUR",value:"EUR"},{display_name:"SAS",value:"SAS"}]}),k.Layouts.add("dashboard","standard_panel",{components:[{type:"remove_panel",position:"right",color:"red",group_position:"end"},{type:"move_panel_up",position:"right",group_position:"middle"},{type:"move_panel_down",position:"right",group_position:"start",style:{"margin-left":"0.75em"}}]}),k.Layouts.add("dashboard","standard_plot",{components:[{type:"title",title:"LocusZoom",subtitle:'v'+k.version+"",position:"left"},{type:"download",position:"right"}]}),k.Layouts.add("dashboard","covariates_model_plot",((m=k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0})).components.push({type:"covariates_model",button_html:"Model",button_title:"Show and edit covariates currently in model",position:"left"}),m)),k.Layouts.add("dashboard","region_nav_plot",((_=k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0})).components.push({type:"shift_region",step:5e5,button_html:">>",position:"right",group_position:"end"},{type:"shift_region",step:5e4,button_html:">",position:"right",group_position:"middle"},{type:"zoom_region",step:.2,position:"right",group_position:"middle"},{type:"zoom_region",step:-.2,position:"right",group_position:"middle"},{type:"shift_region",step:-5e4,button_html:"<",position:"right",group_position:"middle"},{type:"shift_region",step:-5e5,button_html:"<<",position:"right",group_position:"start"}),_)),k.Layouts.add("panel","association",{id:"association",width:800,height:225,min_width:400,min_height:200,proportional_width:1,margin:{top:35,right:50,bottom:40,left:50},inner_border:"rgb(210, 210, 210)",dashboard:(g=k.Layouts.get("dashboard","standard_panel",{unnamespaced:!0}),g.components.push({type:"toggle_legend",position:"right"}),g),axes:{x:{label:"Chromosome {{chr}} (Mb)",label_offset:32,tick_format:"region",extent:"state"},y1:{label:"-log10 p-value",label_offset:28},y2:{label:"Recombination Rate (cM/Mb)",label_offset:40}},legend:{orientation:"vertical",origin:{x:55,y:40},hidden:!0},interaction:{drag_background_to_pan:!0,drag_x_ticks_to_scale:!0,drag_y1_ticks_to_scale:!0,drag_y2_ticks_to_scale:!0,scroll_to_zoom:!0,x_linked:!0},data_layers:[k.Layouts.get("data_layer","significance",{unnamespaced:!0}),k.Layouts.get("data_layer","recomb_rate",{unnamespaced:!0}),k.Layouts.get("data_layer","association_pvalues",{unnamespaced:!0})]}),k.Layouts.add("panel","association_catalog",((y=k.Layouts.get("panel","association",{unnamespaced:!0,id:"associationcatalog",namespace:{assoc:"assoc",ld:"ld",catalog:"catalog"}})).dashboard.components.push({type:"display_options",position:"right",color:"blue",button_html:"Display options...",button_title:"Control how plot items are displayed",layer_name:"associationpvaluescatalog",default_config_display_name:"No catalog labels (default)",options:[{display_name:"Label catalog traits",display:{label:{text:"{{{{namespace[catalog]}}trait|htmlescape}}",spacing:6,lines:{style:{"stroke-width":"2px",stroke:"#333333","stroke-dasharray":"2px 2px"}},filters:[{field:"{{namespace[catalog]}}trait",operator:"!=",value:null},{field:"{{namespace[catalog]}}log_pvalue",operator:">",value:z},{field:"{{namespace[ld]}}state",operator:">",value:.4}],style:{"font-size":"10px","font-weight":"bold",fill:"#333333"}}}}]}),y.data_layers=[k.Layouts.get("data_layer","significance",{unnamespaced:!0}),k.Layouts.get("data_layer","recomb_rate",{unnamespaced:!0}),k.Layouts.get("data_layer","association_pvalues_catalog",{unnamespaced:!0})],y)),k.Layouts.add("panel","genes",{id:"genes",width:800,height:225,min_width:400,min_height:112.5,proportional_width:1,margin:{top:20,right:50,bottom:20,left:50},axes:{},interaction:{drag_background_to_pan:!0,scroll_to_zoom:!0,x_linked:!0},dashboard:(p=k.Layouts.get("dashboard","standard_panel",{unnamespaced:!0}),p.components.push({type:"resize_to_data",position:"right",button_html:"Show all genes"}),p),data_layers:[k.Layouts.get("data_layer","genes",{unnamespaced:!0})]}),k.Layouts.add("panel","phewas",{id:"phewas",width:800,height:300,min_width:800,min_height:300,proportional_width:1,margin:{top:20,right:50,bottom:120,left:50},inner_border:"rgb(210, 210, 210)",axes:{x:{ticks:{style:{"font-weight":"bold","font-size":"11px","text-anchor":"start"},transform:"rotate(50)",position:"left"}},y1:{label:"-log10 p-value",label_offset:28}},data_layers:[k.Layouts.get("data_layer","significance",{unnamespaced:!0}),k.Layouts.get("data_layer","phewas_pvalues",{unnamespaced:!0})]}),k.Layouts.add("panel","genome_legend",{id:"genome_legend",width:800,height:50,origin:{x:0,y:300},min_width:800,min_height:50,proportional_width:1,margin:{top:0,right:50,bottom:35,left:50},axes:{x:{label:"Genomic Position (number denotes chromosome)",label_offset:35,ticks:[{x:124625310,text:"1",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:370850307,text:"2",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:591461209,text:"3",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:786049562,text:"4",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:972084330,text:"5",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1148099493,text:"6",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1313226358,text:"7",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1465977701,text:"8",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1609766427,text:"9",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1748140516,text:"10",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1883411148,text:"11",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2017840353,text:"12",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2142351240,text:"13",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2253610949,text:"14",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2358551415,text:"15",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2454994487,text:"16",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2540769469,text:"17",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2620405698,text:"18",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2689008813,text:"19",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2750086065,text:"20",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2805663772,text:"21",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2855381003,text:"22",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"}]}},data_layers:[k.Layouts.get("data_layer","genome_legend",{unnamespaced:!0})]}),k.Layouts.add("panel","intervals",{id:"intervals",width:1e3,height:50,min_width:500,min_height:50,margin:{top:25,right:150,bottom:5,left:50},dashboard:(t=k.Layouts.get("dashboard","standard_panel",{unnamespaced:!0}),t.components.push({type:"toggle_split_tracks",data_layer_id:"intervals",position:"right"}),t),axes:{},interaction:{drag_background_to_pan:!0,scroll_to_zoom:!0,x_linked:!0},legend:{hidden:!0,orientation:"horizontal",origin:{x:50,y:0},pad_from_bottom:5},data_layers:[k.Layouts.get("data_layer","intervals",{unnamespaced:!0})]}),k.Layouts.add("panel","annotation_catalog",{id:"annotationcatalog",width:800,height:50,min_height:50,proportional_width:1,margin:{top:25,right:50,bottom:0,left:50},inner_border:"rgb(210, 210, 210)",dashboard:k.Layouts.get("dashboard","standard_panel",{unnamespaced:!0}),interaction:{drag_background_to_pan:!0,scroll_to_zoom:!0,x_linked:!0},data_layers:[k.Layouts.get("data_layer","annotation_catalog",{unnamespaced:!0})]}),k.Layouts.add("plot","standard_association",{state:{},width:800,height:450,responsive_resize:"both",min_region_scale:2e4,max_region_scale:1e6,dashboard:k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0}),panels:[k.Layouts.get("panel","association",{unnamespaced:!0,proportional_height:.5}),k.Layouts.get("panel","genes",{unnamespaced:!0,proportional_height:.5})]}),k.Layouts.add("plot","association_catalog",{state:{},width:800,height:500,responsive_resize:"width_only",min_region_scale:2e4,max_region_scale:1e6,dashboard:k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0}),panels:[k.Layouts.get("panel","annotation_catalog",{unnamespaced:!0}),k.Layouts.get("panel","association_catalog",{unnamespaced:!0}),k.Layouts.get("panel","genes",{unnamespaced:!0})]}),k.StandardLayout=k.Layouts.get("plot","standard_association"),k.Layouts.add("plot","standard_phewas",{width:800,height:600,min_width:800,min_height:600,responsive_resize:"both",dashboard:k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0}),panels:[k.Layouts.get("panel","phewas",{unnamespaced:!0,proportional_height:.45}),k.Layouts.get("panel","genome_legend",{unnamespaced:!0,proportional_height:.1}),k.Layouts.get("panel","genes",{unnamespaced:!0,proportional_height:.45,margin:{bottom:40},axes:{x:{label:"Chromosome {{chr}} (Mb)",label_offset:32,tick_format:"region",extent:"state"}}})],mouse_guide:!1}),k.Layouts.add("plot","interval_association",{state:{},width:800,height:550,responsive_resize:"both",min_region_scale:2e4,max_region_scale:1e6,dashboard:k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0}),panels:[k.Layouts.get("panel","association",{unnamespaced:!0,width:800,proportional_height:225/570}),k.Layouts.get("panel","intervals",{unnamespaced:!0,proportional_height:120/570}),k.Layouts.get("panel","genes",{unnamespaced:!0,width:800,proportional_height:225/570})]}),k.DataLayer=function(t,e){return this.initialized=!1,this.layout_idx=null,this.id=null,this.parent=e||null,this.svg={},this.parent_plot=null,void 0!==e&&e instanceof k.Panel&&(this.parent_plot=e.parent),this.layout=k.Layouts.merge(t||{},k.DataLayer.DefaultLayout),this.layout.id&&(this.id=this.layout.id),this.layout.x_axis!=={}&&"number"!=typeof this.layout.x_axis.axis&&(this.layout.x_axis.axis=1),this.layout.y_axis!=={}&&"number"!=typeof this.layout.y_axis.axis&&(this.layout.y_axis.axis=1),this._base_layout=JSON.parse(JSON.stringify(this.layout)),this.state={},this.state_id=null,this.setDefaultState(),this.data=[],this.layout.tooltip&&(this.tooltips={}),this.global_statuses={highlighted:!1,selected:!1,faded:!1,hidden:!1},this},k.DataLayer.prototype.addField=function(t,e,a){if(!t||!e)throw new Error("Must specify field name and namespace to use when adding field");var i=e+":"+t;if(a)if(i+="|","string"==typeof a)i+=a;else{if(!Array.isArray(a))throw new Error("Must provide transformations as either a string or array of strings");i+=a.join("|")}var s=this.layout.fields;return-1===s.indexOf(i)&&s.push(i),i},k.DataLayer.prototype.setDefaultState=function(){if(this.parent){this.state=this.parent.state,this.state_id=this.parent.id+"."+this.id,this.state[this.state_id]=this.state[this.state_id]||{};var e=this.state[this.state_id];k.DataLayer.Statuses.adjectives.forEach(function(t){e[t]=e[t]||[]}),e.has_tooltip=e.has_tooltip||[]}},k.DataLayer.DefaultLayout={type:"",fields:[],x_axis:{},y_axis:{}},k.DataLayer.Statuses={verbs:["highlight","select","fade","hide"],adjectives:["highlighted","selected","faded","hidden"],menu_antiverbs:["unhighlight","deselect","unfade","show"]},k.DataLayer.prototype.getBaseId=function(){return this.parent_plot.id+"."+this.parent.id+"."+this.id},k.DataLayer.prototype.getAbsoluteDataHeight=function(){return this.svg.group.node().getBoundingClientRect().height},k.DataLayer.prototype.canTransition=function(){return!!this.layout.transition&&!(this.parent_plot.panel_boundaries.dragging||this.parent_plot.interaction.panel_id)},k.DataLayer.prototype.getElementId=function(t){var e="element";if("string"==typeof t)e=t;else if("object"==typeof t){var a=this.layout.id_field||"id";if(void 0===t[a])throw new Error("Unable to generate element ID");e=t[a].toString().replace(/\W/g,"")}return(this.getBaseId()+"-"+e).replace(/([:.[\],])/g,"_")},k.DataLayer.prototype.getElementStatusNodeId=function(t){return null},k.DataLayer.prototype.getElementById=function(t){var e=f.select("#"+t.replace(/([:.[\],])/g,"\\$1"));return!e.empty()&&e.data()&&e.data().length?e.data()[0]:null},k.DataLayer.prototype.applyDataMethods=function(){var e=this.layout.match&&this.layout.match.receive,i=this.parent_plot.state.lz_match_value;return this.data.forEach(function(t,a){e&&null!=i&&(t.lz_highlight_match=t[e]===i),this.data[a].toHTML=function(){var t=this.layout.id_field||"id",e="";return this.data[a][t]&&(e=this.data[a][t].toString()),e}.bind(this),this.data[a].getDataLayer=function(){return this}.bind(this),this.data[a].deselect=function(){this.getDataLayer().unselectElement(this)}}.bind(this)),this.applyCustomDataMethods(),this},k.DataLayer.prototype.applyCustomDataMethods=function(){return this},k.DataLayer.prototype.initialize=function(){return this.svg.container=this.parent.svg.group.append("g").attr("class","lz-data_layer-container").attr("id",this.getBaseId()+".data_layer_container"),this.svg.clipRect=this.svg.container.append("clipPath").attr("id",this.getBaseId()+".clip").append("rect"),this.svg.group=this.svg.container.append("g").attr("id",this.getBaseId()+".data_layer").attr("clip-path","url(#"+this.getBaseId()+".clip)"),this},k.DataLayer.prototype.moveUp=function(){return this.parent.data_layer_ids_by_z_index[this.layout.z_index+1]&&(this.parent.data_layer_ids_by_z_index[this.layout.z_index]=this.parent.data_layer_ids_by_z_index[this.layout.z_index+1],this.parent.data_layer_ids_by_z_index[this.layout.z_index+1]=this.id,this.parent.resortDataLayers()),this},k.DataLayer.prototype.moveDown=function(){return this.parent.data_layer_ids_by_z_index[this.layout.z_index-1]&&(this.parent.data_layer_ids_by_z_index[this.layout.z_index]=this.parent.data_layer_ids_by_z_index[this.layout.z_index-1],this.parent.data_layer_ids_by_z_index[this.layout.z_index-1]=this.id,this.parent.resortDataLayers()),this},k.DataLayer.prototype.resolveScalableParameter=function(t,e){var a=null;if(Array.isArray(t))for(var i=0;null===a&&i":function(t,e){return e=":function(t,e){return e<=t},"%":function(t,e){return t%e}},Array.isArray(a)&&(2===a.length?e[a[0]]===a[1]:3===a.length&&i[a[1]]&&i[a[1]](e[a[0]],a[2]))||(n=!1)}),n&&i.push("indexes"===a?t:s)}),i},k.DataLayer.prototype.filterIndexes=function(t){return this.filter(t,"indexes")},k.DataLayer.prototype.filterElements=function(t){return this.filter(t,"elements")},k.DataLayer.Statuses.verbs.forEach(function(t,e){var a=k.DataLayer.Statuses.adjectives[e],i="un"+t;k.DataLayer.prototype[t+"Element"]=function(t,e){return e=void 0!==e&&!!e,this.setElementStatus(a,t,!0,e),this},k.DataLayer.prototype[i+"Element"]=function(t,e){return e=void 0!==e&&!!e,this.setElementStatus(a,t,!1,e),this},k.DataLayer.prototype[t+"ElementsByFilters"]=function(t,e){return e=void 0!==e&&!!e,this.setElementStatusByFilters(a,!0,t,e)},k.DataLayer.prototype[i+"ElementsByFilters"]=function(t,e){return e=void 0!==e&&!!e,this.setElementStatusByFilters(a,!1,t,e)},k.DataLayer.prototype[t+"AllElements"]=function(){return this.setAllElementStatus(a,!0),this},k.DataLayer.prototype[i+"AllElements"]=function(){return this.setAllElementStatus(a,!1),this}}),k.DataLayer.prototype.setElementStatus=function(t,e,a,i){if("has_tooltip"===t)return this;if(void 0===t||-1===k.DataLayer.Statuses.adjectives.indexOf(t))throw new Error("Invalid status passed to DataLayer.setElementStatus()");if(void 0===e)throw new Error("Invalid element passed to DataLayer.setElementStatus()");void 0===a&&(a=!0);try{var s=this.getElementId(e)}catch(t){return this}i&&this.setAllElementStatus(t,!a),f.select("#"+s).classed("lz-data_layer-"+this.layout.type+"-"+t,a);var n=this.getElementStatusNodeId(e);null!==n&&f.select("#"+n).classed("lz-data_layer-"+this.layout.type+"-statusnode-"+t,a);var o=this.state[this.state_id][t].indexOf(s),r=-1===o;a&&r&&this.state[this.state_id][t].push(s),a||r||this.state[this.state_id][t].splice(o,1),this.showOrHideTooltip(e,r),r&&this.parent.emit("layout_changed",!0);var l="selected"===t;!l||!r&&a||this.parent.emit("element_selection",{element:e,active:a},!0);var h=this.layout.match&&this.layout.match.send;return l&&h&&(r||!a)&&this.parent.emit("match_requested",{value:e[h],active:a},!0),this},k.DataLayer.prototype.setElementStatusByFilters=function(e,a,t,i){if(void 0===e||-1===k.DataLayer.Statuses.adjectives.indexOf(e))throw new Error("Invalid status passed to DataLayer.setElementStatusByFilters()");return void 0===this.state[this.state_id][e]||(a=void 0===a||!!a,i=void 0!==i&&!!i,Array.isArray(t)||(t=[]),i&&this.setAllElementStatus(e,!a),this.filterElements(t).forEach(function(t){this.setElementStatus(e,t,a)}.bind(this))),this},k.DataLayer.prototype.setAllElementStatus=function(a,t){if(void 0===a||-1===k.DataLayer.Statuses.adjectives.indexOf(a))throw new Error("Invalid status passed to DataLayer.setAllElementStatus()");if(void 0===this.state[this.state_id][a])return this;(void 0===t&&(t=!0),t)?this.data.forEach(function(t){this.setElementStatus(a,t,!0)}.bind(this)):(this.state[this.state_id][a].slice().forEach(function(t){var e=this.getElementById(t);"object"==typeof e&&null!==e&&this.setElementStatus(a,e,!1)}.bind(this)),this.state[this.state_id][a]=[]);return this.global_statuses[a]=t,this},k.DataLayer.prototype.applyBehaviors=function(a){"object"==typeof this.layout.behaviors&&Object.keys(this.layout.behaviors).forEach(function(t){var e=/(click|mouseover|mouseout)/.exec(t);e&&a.on(e[0]+"."+t,this.executeBehaviors(t,this.layout.behaviors[t]))}.bind(this))},k.DataLayer.prototype.executeBehaviors=function(t,e){var a=-1!==t.indexOf("ctrl"),i=-1!==t.indexOf("shift");return function(s){a===!!f.event.ctrlKey&&i===!!f.event.shiftKey&&e.forEach(function(t){if("object"==typeof t&&null!==t)switch(t.action){case"set":this.setElementStatus(t.status,s,!0,t.exclusive);break;case"unset":this.setElementStatus(t.status,s,!1,t.exclusive);break;case"toggle":var e=-1!==this.state[this.state_id][t.status].indexOf(this.getElementId(s)),a=t.exclusive&&!e;this.setElementStatus(t.status,s,!e,a);break;case"link":if("string"==typeof t.href){var i=k.parseFields(s,t.href);"string"==typeof t.target?window.open(i,t.target):window.location.href=i}}}.bind(this))}.bind(this)},k.DataLayer.prototype.getPageOrigin=function(){var t=this.parent.getPageOrigin();return{x:t.x+this.parent.layout.margin.left,y:t.y+this.parent.layout.margin.top}},k.DataLayer.prototype.exportData=function(t){var e,a="json";switch(t="string"==typeof(t=t||a)?t.toLowerCase():a,-1===["json","csv","tsv"].indexOf(t)&&(t=a),t){case"json":try{e=JSON.stringify(this.data)}catch(t){e=null,console.warn("Unable to export JSON data from data layer: "+this.getBaseId()),console.error(t)}break;case"tsv":case"csv":try{var i=JSON.parse(JSON.stringify(this.data));if("object"!=typeof i)e=i.toString();else if(Array.isArray(i)){var s="tsv"===t?"\t":",";e=this.layout.fields.map(function(t){return JSON.stringify(t)}).join(s)+"\n"+i.map(function(e){return this.layout.fields.map(function(t){return void 0===e[t]?JSON.stringify(null):"object"==typeof e[t]&&null!==e[t]?Array.isArray(e[t])?'"[Array('+e[t].length+')]"':'"[Object]"':JSON.stringify(e[t])}).join(s)}.bind(this)).join("\n")}else e="Object"}catch(t){e=null,console.error("Unable to export CSV data from data layer: "+this.getBaseId()+";",t)}}return e},k.DataLayer.prototype.draw=function(){return this.svg.container.attr("transform","translate("+this.parent.layout.cliparea.origin.x+","+this.parent.layout.cliparea.origin.y+")"),this.svg.clipRect.attr("width",this.parent.layout.cliparea.width).attr("height",this.parent.layout.cliparea.height),this.positionAllTooltips(),this},k.DataLayer.prototype.reMap=function(){this.destroyAllTooltips();var t=this.parent_plot.lzd.getData(this.state,this.layout.fields);return t.then(function(t){this.data=t.body,this.applyDataMethods(),this.initialized=!0}.bind(this)),t},k.DataLayers=(c={},(u={}).get=function(t,e,a){if(t){if(c[t]){if("object"!=typeof e)throw new Error("invalid layout argument for data layer ["+t+"]");return new c[t](e,a)}throw new Error("data layer ["+t+"] not found")}return null},u.set=function(t,e){if(e){if("function"!=typeof e)throw new Error("unable to set data layer ["+t+"], argument provided is not a function");c[t]=e,c[t].prototype=new k.DataLayer}else delete c[t]},u.add=function(t,e){if(c[t])throw new Error("data layer already exists with name: "+t);u.set(t,e)},u.extend=function(t,e,a){a=a||{};var i=c[t];if(!i)throw new Error("Attempted to subclass an unknown or unregistered datalayer type");if("object"!=typeof a)throw new Error("Must specify an object of properties and methods");var s=k.subclass(i,a);return c[e]=s},u.list=function(){return Object.keys(c)},u),k.DataLayers.add("annotation_track",function(t){if(this.DefaultLayout={color:"#000000",filters:[],tooltip_positioning:"middle",hit_area_width:8},t=k.Layouts.merge(t,this.DefaultLayout),!Array.isArray(t.filters))throw new Error("Annotation track must specify array of filters for selecting points to annotate");return k.DataLayer.apply(this,arguments),this.render=function(){var o=this,r=this.filter(this.layout.filters,"elements"),t=this.svg.group.select("g.lz-data_layer-"+o.layout.type+"-visible_lines");0===t.size()&&(t=this.svg.group.append("g").attr("class","lz-data_layer-"+o.layout.type+"-visible_lines"));var e=t.selectAll("rect.lz-data_layer-"+o.layout.type).data(r,function(t){return t[o.layout.id_field]});e.enter().append("rect").attr("class","lz-data_layer-"+this.layout.type).attr("id",function(t){return o.getElementId(t)});e.attr("x",function(t){return o.parent.x_scale(t[o.layout.x_axis.field])-.5}).attr("width",1).attr("height",o.parent.layout.height).attr("fill",function(t){return o.resolveScalableParameter(o.layout.color,t)}),e.exit().remove();var a=this.svg.group.select("g.lz-data_layer-"+o.layout.type+"-hit_areas");0===a.size()&&(a=this.svg.group.append("g").attr("class","lz-data_layer-"+o.layout.type+"-hit_areas"));var i=a.selectAll("rect.lz-data_layer-"+o.layout.type).data(r,function(t){return t[o.layout.id_field]});i.enter().append("rect").attr("class","lz-data_layer-"+this.layout.type).attr("id",function(t){return o.getElementId(t)});var s=function(t,e){var a=o.parent.x_scale(t[o.layout.x_axis.field]),i=a-o.layout.hit_area_width/2;if(1<=e){var s=r[e-1],n=o.parent.x_scale(s[o.layout.x_axis.field]);i=Math.max(i,(a+n)/2)}return[i,a]};i.attr("height",o.parent.layout.height).attr("opacity",0).attr("x",function(t,e){return s(t,e)[0]}).attr("width",function(t,e){var a=s(t,e);return a[1]-a[0]+o.layout.hit_area_width/2}),i.exit().remove(),this.applyBehaviors(i)},this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s,n,o=this.tooltips[t],r=this.getPageOrigin(),l=o.selector.node().getBoundingClientRect(),h=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),d=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right),u=this.parent.x_scale(o.data[this.layout.x_axis.field]),c=h/2,p=Math.max(l.width/2-u,0),y=Math.max(l.width/2+u-d,0);a=r.x+u-l.width/2-y+p,n=l.width/2-7+y-p-.5;var g=0;switch(this.layout.tooltip_positioning){case"top":i="down";break;case"bottom":g=h,i="up";break;case"middle":default:g=c,i=f.mouse(this.svg.container.node())[1]>h/2?"down":"up"}"up"===i?(e=r.y+g+1+7,s=-8):"down"===i&&(e=r.y+g-(l.height+1+7),s=l.height-1),o.selector.style("left",a+"px").style("top",e+"px"),o.arrow||(o.arrow=o.selector.append("div").style("position","absolute")),o.arrow.attr("class","lz-data_layer-tooltip-arrow_"+i).style("left",n+"px").style("top",s+"px")},this}),k.DataLayers.add("forest",function(t){return this.DefaultLayout={point_size:40,point_shape:"square",color:"#888888",fill_opacity:1,y_axis:{axis:2},id_field:"id",confidence_intervals:{start_field:"ci_start",end_field:"ci_end"},show_no_significance_line:!0},t=k.Layouts.merge(t,this.DefaultLayout),k.DataLayer.apply(this,arguments),this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s=this.tooltips[t],n=this.resolveScalableParameter(this.layout.point_size,s.data),o=this.getPageOrigin(),r=this.parent.x_scale(s.data[this.layout.x_axis.field]),l="y"+this.layout.y_axis.axis+"_scale",h=this.parent[l](s.data[this.layout.y_axis.field]),d=s.selector.node().getBoundingClientRect(),u=Math.sqrt(n/Math.PI);r<=this.parent.layout.width/2?(e=o.x+r+u+7+1,a="left",i=-8):(e=o.x+r-d.width-u-7-1,a="right",i=d.width-1);var c,p,y=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom);h-d.height/2<=0?(c=o.y+h-10.5-6,p=6):h+d.height/2>=y?(c=o.y+h+7+6-d.height,p=d.height-14-6):(c=o.y+h-d.height/2,p=d.height/2-7),s.selector.style("left",e+"px").style("top",c+"px"),s.arrow||(s.arrow=s.selector.append("div").style("position","absolute")),s.arrow.attr("class","lz-data_layer-tooltip-arrow_"+a).style("left",i+"px").style("top",p+"px")},this.render=function(){var i="x_scale",s="y"+this.layout.y_axis.axis+"_scale";if(this.layout.confidence_intervals&&-1!==this.layout.fields.indexOf(this.layout.confidence_intervals.start_field)&&-1!==this.layout.fields.indexOf(this.layout.confidence_intervals.end_field)){var t=this.svg.group.selectAll("rect.lz-data_layer-forest.lz-data_layer-forest-ci").data(this.data,function(t){return t[this.layout.id_field]}.bind(this));t.enter().append("rect").attr("class","lz-data_layer-forest lz-data_layer-forest-ci").attr("id",function(t){return this.getElementId(t)+"_ci"}.bind(this)).attr("transform","translate(0,"+(isNaN(this.parent.layout.height)?0:this.parent.layout.height)+")");var e=function(t){var e=this.parent[i](t[this.layout.confidence_intervals.start_field]),a=this.parent[s](t[this.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),isNaN(a)&&(a=-1e3),"translate("+e+","+a+")"}.bind(this),a=function(t){return this.parent[i](t[this.layout.confidence_intervals.end_field])-this.parent[i](t[this.layout.confidence_intervals.start_field])}.bind(this);this.canTransition()?t.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("transform",e).attr("width",a).attr("height",1):t.attr("transform",e).attr("width",a).attr("height",1),t.exit().remove()}var n=this.svg.group.selectAll("path.lz-data_layer-forest.lz-data_layer-forest-point").data(this.data,function(t){return t[this.layout.id_field]}.bind(this)),o=isNaN(this.parent.layout.height)?0:this.parent.layout.height;n.enter().append("path").attr("class","lz-data_layer-forest lz-data_layer-forest-point").attr("id",function(t){return this.getElementId(t)}.bind(this)).attr("transform","translate(0,"+o+")");var r=function(t){var e=this.parent[i](t[this.layout.x_axis.field]),a=this.parent[s](t[this.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),isNaN(a)&&(a=-1e3),"translate("+e+","+a+")"}.bind(this),l=function(t){return this.resolveScalableParameter(this.layout.color,t)}.bind(this),h=function(t){return this.resolveScalableParameter(this.layout.fill_opacity,t)}.bind(this),d=f.svg.symbol().size(function(t){return this.resolveScalableParameter(this.layout.point_size,t)}.bind(this)).type(function(t){return this.resolveScalableParameter(this.layout.point_shape,t)}.bind(this));this.canTransition()?n.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("transform",r).attr("fill",l).attr("fill-opacity",h).attr("d",d):n.attr("transform",r).attr("fill",l).attr("fill-opacity",h).attr("d",d),n.exit().remove(),n.on("click.event_emitter",function(t){this.parent.emit("element_clicked",t,!0)}.bind(this)),this.applyBehaviors(n)},this}),k.DataLayers.extend("forest","category_forest",{_getDataExtent:function(t,e){var a=this.layout.confidence_intervals;if(a&&-1!==this.layout.fields.indexOf(a.start_field)&&-1!==this.layout.fields.indexOf(a.end_field)){return[f.min(t,function(t){return+new k.Data.Field(a.start_field).resolve(t)}),f.max(t,function(t){return+new k.Data.Field(a.end_field).resolve(t)})]}return k.DataLayer.prototype._getDataExtent.call(this,t,e)},getTicks:function(t,e){if(-1===["x","y1","y2"].indexOf(t))throw new Error("Invalid dimension identifier"+t);if(t==="y"+this.layout.y_axis.axis){var a=this.layout.y_axis.category_field;if(!a)throw new Error("Layout for "+this.layout.id+" must specify category_field");return this.data.map(function(t,e){return{y:e+1,text:t[a]}})}return[]},applyCustomDataMethods:function(){var a=this.layout.y_axis.field;if(!a)throw new Error("Layout for "+this.layout.id+" must specify yaxis.field");return this.data=this.data.map(function(t,e){return t[a]=e+1,t}),this.layout.y_axis.floor=0,this.layout.y_axis.ceiling=this.data.length+1,this}}),k.DataLayers.add("genes",function(t){return this.DefaultLayout={stroke:"rgb(54, 54, 150)",color:"#363696",label_font_size:12,label_exon_spacing:4,exon_height:16,bounding_box_padding:6,track_vertical_spacing:10},t=k.Layouts.merge(t,this.DefaultLayout),k.DataLayer.apply(this,arguments),this.getElementStatusNodeId=function(t){return this.getElementId(t)+"-statusnode"},this.getTrackHeight=function(){return 2*this.layout.bounding_box_padding+this.layout.label_font_size+this.layout.label_exon_spacing+this.layout.exon_height+this.layout.track_vertical_spacing},this.transcript_idx=0,this.tracks=1,this.gene_track_index={1:[]},this.assignTracks=function(){return this.getLabelWidth=function(t,e){try{var a=this.svg.group.append("text").attr("x",0).attr("y",0).attr("class","lz-data_layer-genes lz-label").style("font-size",e).text(t+"→"),i=a.node().getBBox().width;return a.remove(),i}catch(t){return 0}},this.tracks=1,this.gene_track_index={1:[]},this.data.map(function(t,i){if(this.data[i].gene_id&&this.data[i].gene_id.indexOf(".")){var e=this.data[i].gene_id.split(".");this.data[i].gene_id=e[0],this.data[i].gene_version=e[1]}if(this.data[i].transcript_id=this.data[i].transcripts[this.transcript_idx].transcript_id,this.data[i].display_range={start:this.parent.x_scale(Math.max(t.start,this.state.start)),end:this.parent.x_scale(Math.min(t.end,this.state.end))},this.data[i].display_range.label_width=this.getLabelWidth(this.data[i].gene_name,this.layout.label_font_size),this.data[i].display_range.width=this.data[i].display_range.end-this.data[i].display_range.start,this.data[i].display_range.text_anchor="middle",this.data[i].display_range.widththis.state.end)this.data[i].display_range.start=this.data[i].display_range.end-this.data[i].display_range.label_width-this.layout.label_font_size,this.data[i].display_range.text_anchor="end";else{var a=(this.data[i].display_range.label_width-this.data[i].display_range.width)/2+this.layout.label_font_size;this.data[i].display_range.start-athis.parent.x_scale(this.state.end)?(this.data[i].display_range.end=this.parent.x_scale(this.state.end),this.data[i].display_range.start=this.data[i].display_range.end-this.data[i].display_range.label_width,this.data[i].display_range.text_anchor="end"):(this.data[i].display_range.start-=a,this.data[i].display_range.end+=a)}this.data[i].display_range.width=this.data[i].display_range.end-this.data[i].display_range.start}this.data[i].display_range.start-=this.layout.bounding_box_padding,this.data[i].display_range.end+=this.layout.bounding_box_padding,this.data[i].display_range.width+=2*this.layout.bounding_box_padding,this.data[i].display_domain={start:this.parent.x_scale.invert(this.data[i].display_range.start),end:this.parent.x_scale.invert(this.data[i].display_range.end)},this.data[i].display_domain.width=this.data[i].display_domain.end-this.data[i].display_domain.start,this.data[i].track=null;for(var s=1;null===this.data[i].track;){var n=!1;this.gene_track_index[s].map(function(t){if(!n){var e=Math.min(t.display_range.start,this.display_range.start);Math.max(t.display_range.end,this.display_range.end)-ethis.tracks&&(this.tracks=s,this.gene_track_index[s]=[]):(this.data[i].track=s,this.gene_track_index[s].push(this.data[i]))}(this.data[i].parent=this).data[i].transcripts.map(function(t,a){this.data[i].transcripts[a].parent=this.data[i],this.data[i].transcripts[a].exons.map(function(t,e){this.data[i].transcripts[a].exons[e].parent=this.data[i].transcripts[a]}.bind(this))}.bind(this))}.bind(this)),this},this.render=function(){var r,l,h,d,u=this;this.assignTracks();var t=this.svg.group.selectAll("g.lz-data_layer-genes").data(this.data,function(t){return t.gene_name});t.enter().append("g").attr("class","lz-data_layer-genes"),t.attr("id",function(t){return this.getElementId(t)}.bind(this)).each(function(t){var e=t.parent,a=f.select(this).selectAll("rect.lz-data_layer-genes.lz-data_layer-genes-statusnode").data([t],function(t){return e.getElementStatusNodeId(t)});a.enter().append("rect").attr("class","lz-data_layer-genes lz-data_layer-genes-statusnode"),a.attr("id",function(t){return e.getElementStatusNodeId(t)}).attr("rx",function(){return e.layout.bounding_box_padding}).attr("ry",function(){return e.layout.bounding_box_padding}),r=function(t){return t.display_range.width},l=function(){return e.getTrackHeight()-e.layout.track_vertical_spacing},h=function(t){return t.display_range.start},d=function(t){return(t.track-1)*e.getTrackHeight()},e.canTransition()?a.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",r).attr("height",l).attr("x",h).attr("y",d):a.attr("width",r).attr("height",l).attr("x",h).attr("y",d),a.exit().remove();var i=f.select(this).selectAll("rect.lz-data_layer-genes.lz-boundary").data([t],function(t){return t.gene_name+"_boundary"}).style({fill:function(t){return u.resolveScalableParameter(u.layout.color,t)},stroke:function(t){return u.resolveScalableParameter(u.layout.stroke,t)}});i.enter().append("rect").attr("class","lz-data_layer-genes lz-boundary"),r=function(t){return e.parent.x_scale(t.end)-e.parent.x_scale(t.start)},l=function(){return 1},h=function(t){return e.parent.x_scale(t.start)},d=function(t){return(t.track-1)*e.getTrackHeight()+e.layout.bounding_box_padding+e.layout.label_font_size+e.layout.label_exon_spacing+Math.max(e.layout.exon_height,3)/2},e.canTransition()?i.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",r).attr("height",l).attr("x",h).attr("y",d):i.attr("width",r).attr("height",l).attr("x",h).attr("y",d),i.exit().remove();var s=f.select(this).selectAll("text.lz-data_layer-genes.lz-label").data([t],function(t){return t.gene_name+"_label"});s.enter().append("text").attr("class","lz-data_layer-genes lz-label"),s.attr("text-anchor",function(t){return t.display_range.text_anchor}).text(function(t){return"+"===t.strand?t.gene_name+"→":"←"+t.gene_name}).style("font-size",t.parent.layout.label_font_size),h=function(t){return"middle"===t.display_range.text_anchor?t.display_range.start+t.display_range.width/2:"start"===t.display_range.text_anchor?t.display_range.start+e.layout.bounding_box_padding:"end"===t.display_range.text_anchor?t.display_range.end-e.layout.bounding_box_padding:void 0},d=function(t){return(t.track-1)*e.getTrackHeight()+e.layout.bounding_box_padding+e.layout.label_font_size},e.canTransition()?s.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("x",h).attr("y",d):s.attr("x",h).attr("y",d),s.exit().remove();var n=f.select(this).selectAll("rect.lz-data_layer-genes.lz-exon").data(t.transcripts[t.parent.transcript_idx].exons,function(t){return t.exon_id});n.enter().append("rect").attr("class","lz-data_layer-genes lz-exon"),n.style({fill:function(t){return u.resolveScalableParameter(u.layout.color,t.parent.parent)},stroke:function(t){return u.resolveScalableParameter(u.layout.stroke,t.parent.parent)}}),r=function(t){return e.parent.x_scale(t.end)-e.parent.x_scale(t.start)},l=function(){return e.layout.exon_height},h=function(t){return e.parent.x_scale(t.start)},d=function(){return(t.track-1)*e.getTrackHeight()+e.layout.bounding_box_padding+e.layout.label_font_size+e.layout.label_exon_spacing},e.canTransition()?n.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",r).attr("height",l).attr("x",h).attr("y",d):n.attr("width",r).attr("height",l).attr("x",h).attr("y",d),n.exit().remove();var o=f.select(this).selectAll("rect.lz-data_layer-genes.lz-clickarea").data([t],function(t){return t.gene_name+"_clickarea"});o.enter().append("rect").attr("class","lz-data_layer-genes lz-clickarea"),o.attr("id",function(t){return e.getElementId(t)+"_clickarea"}).attr("rx",function(){return e.layout.bounding_box_padding}).attr("ry",function(){return e.layout.bounding_box_padding}),r=function(t){return t.display_range.width},l=function(){return e.getTrackHeight()-e.layout.track_vertical_spacing},h=function(t){return t.display_range.start},d=function(t){return(t.track-1)*e.getTrackHeight()},e.canTransition()?o.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",r).attr("height",l).attr("x",h).attr("y",d):o.attr("width",r).attr("height",l).attr("x",h).attr("y",d),o.exit().remove(),o.on("click.event_emitter",function(t){t.parent.parent.emit("element_clicked",t,!0)}),e.applyBehaviors(o)}),t.exit().remove()},this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s=this.tooltips[t],n=this.getPageOrigin(),o=s.selector.node().getBoundingClientRect(),r=this.getElementStatusNodeId(s.data),l=f.select("#"+r).node().getBBox(),h=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),d=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right),u=(s.data.display_range.start+s.data.display_range.end)/2-this.layout.bounding_box_padding/2,c=Math.max(o.width/2-u,0),p=Math.max(o.width/2+u-d,0),y=n.x+u-o.width/2-p+c,g=o.width/2-3.5+p-c;o.height+1+7>h-(l.y+l.height)?(e=n.y+l.y-(o.height+1+7),a="down",i=o.height-1):(e=n.y+l.y+l.height+1+7,a="up",i=-8),s.selector.style("left",y+"px").style("top",e+"px"),s.arrow||(s.arrow=s.selector.append("div").style("position","absolute")),s.arrow.attr("class","lz-data_layer-tooltip-arrow_"+a).style("left",g+"px").style("top",i+"px")},this}),k.DataLayers.add("genome_legend",function(t){return this.DefaultLayout={chromosome_fill_colors:{light:"rgb(155, 155, 188)",dark:"rgb(95, 95, 128)"},chromosome_label_colors:{light:"rgb(120, 120, 186)",dark:"rgb(0, 0, 66)"}},t=k.Layouts.merge(t,this.DefaultLayout),k.DataLayer.apply(this,arguments),this.render=function(){var a=0;this.data.forEach(function(t,e){this.data[e].genome_start=a,this.data[e].genome_end=a+t["genome:base_pairs"],a+=t["genome:base_pairs"]}.bind(this));var t=this.svg.group.selectAll("rect.lz-data_layer-genome_legend").data(this.data,function(t){return t["genome:chr"]});t.enter().append("rect").attr("class","lz-data_layer-genome_legend");var e=this,i=this.parent;t.attr("fill",function(t){return t["genome:chr"]%2?e.layout.chromosome_fill_colors.light:e.layout.chromosome_fill_colors.dark}).attr("x",function(t){return i.x_scale(t.genome_start)}).attr("y",0).attr("width",function(t){return i.x_scale(t["genome:base_pairs"])}).attr("height",i.layout.cliparea.height),t.exit().remove();var s=/([^:]+):(\d+)(?:_.*)?/.exec(this.state.variant);if(!s)throw new Error("Genome legend cannot understand the specified variant position");var n=s[1],o=s[2];a=+this.data[n-1].genome_start+ +o;var r=this.svg.group.selectAll("rect.lz-data_layer-genome_legend-marker").data([{start:a,end:a+1}]);r.enter().append("rect").attr("class","lz-data_layer-genome_legend-marker"),r.transition().duration(500).style({fill:"rgba(255, 250, 50, 0.8)",stroke:"rgba(255, 250, 50, 0.8)","stroke-width":"3px"}).attr("x",function(t){return i.x_scale(t.start)}).attr("y",0).attr("width",function(t){return i.x_scale(t.end-t.start)}).attr("height",i.layout.cliparea.height),r.exit().remove()},this}),k.DataLayers.add("intervals",function(t){return this.DefaultLayout={start_field:"start",end_field:"end",track_split_field:"state_id",track_split_order:"DESC",track_split_legend_to_y_axis:2,split_tracks:!0,track_height:15,track_vertical_spacing:3,bounding_box_padding:2,always_hide_legend:!1,color:"#B8B8B8",fill_opacity:1},t=k.Layouts.merge(t,this.DefaultLayout),k.DataLayer.apply(this,arguments),this.getElementStatusNodeId=function(t){return this.layout.split_tracks?(this.getBaseId()+"-statusnode-"+t[this.layout.track_split_field]).replace(/[:.[\],]/g,"_"):this.getElementId(t)+"-statusnode"}.bind(this),this.getTrackHeight=function(){return this.layout.track_height+this.layout.track_vertical_spacing+2*this.layout.bounding_box_padding},this.tracks=1,this.previous_tracks=1,this.interval_track_index={1:[]},this.assignTracks=function(){if(this.previous_tracks=this.tracks,this.tracks=0,this.interval_track_index={1:[]},this.track_split_field_index={},this.layout.track_split_field&&this.layout.split_tracks){this.data.map(function(t){this.track_split_field_index[t[this.layout.track_split_field]]=null}.bind(this));var t=Object.keys(this.track_split_field_index);"DESC"===this.layout.track_split_order&&t.reverse(),t.forEach(function(t){this.track_split_field_index[t]=this.tracks+1,this.interval_track_index[this.tracks+1]=[],this.tracks++}.bind(this))}return this.data.map(function(t,e){if((this.data[e].parent=this).data[e].display_range={start:this.parent.x_scale(Math.max(t[this.layout.start_field],this.state.start)),end:this.parent.x_scale(Math.min(t[this.layout.end_field],this.state.end))},this.data[e].display_range.width=this.data[e].display_range.end-this.data[e].display_range.start,this.data[e].display_domain={start:this.parent.x_scale.invert(this.data[e].display_range.start),end:this.parent.x_scale.invert(this.data[e].display_range.end)},this.data[e].display_domain.width=this.data[e].display_domain.end-this.data[e].display_domain.start,this.layout.track_split_field&&this.layout.split_tracks){var a=this.data[e][this.layout.track_split_field];this.data[e].track=this.track_split_field_index[a],this.interval_track_index[this.data[e].track].push(e)}else{this.tracks=1,this.data[e].track=null;for(var i=1;null===this.data[e].track;){var s=!1;this.interval_track_index[i].map(function(t){if(!s){var e=Math.min(t.display_range.start,this.display_range.start);Math.max(t.display_range.end,this.display_range.end)-ethis.tracks&&(this.tracks=i,this.interval_track_index[i]=[]):(this.data[e].track=i,this.interval_track_index[i].push(this.data[e]))}}}.bind(this)),this},this.render=function(){var o,r,l,h,d,u;this.assignTracks(),this.svg.group.selectAll(".lz-data_layer-intervals-statusnode.lz-data_layer-intervals-shared").remove(),Object.keys(this.track_split_field_index).forEach(function(t){var e={};e[this.layout.track_split_field]=t;var a={display:this.layout.split_tracks?null:"none"};this.svg.group.insert("rect",":first-child").attr("id",this.getElementStatusNodeId(e)).attr("class","lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-shared").attr("rx",this.layout.bounding_box_padding).attr("ry",this.layout.bounding_box_padding).attr("width",this.parent.layout.cliparea.width).attr("height",this.getTrackHeight()-this.layout.track_vertical_spacing).attr("x",0).attr("y",(this.track_split_field_index[t]-1)*this.getTrackHeight()).style(a)}.bind(this));var t=this.svg.group.selectAll("g.lz-data_layer-intervals").data(this.data,function(t){return t[this.layout.id_field]}.bind(this));return t.enter().append("g").attr("class","lz-data_layer-intervals"),t.attr("id",function(t){return this.getElementId(t)}.bind(this)).each(function(t){var e=t.parent,a={display:e.layout.split_tracks?"none":null},i=f.select(this).selectAll("rect.lz-data_layer-intervals.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-statusnode-discrete").data([t],function(t){return e.getElementId(t)+"-statusnode"});i.enter().insert("rect",":first-child").attr("class","lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-statusnode-discrete"),i.attr("id",function(t){return e.getElementId(t)+"-statusnode"}).attr("rx",function(){return e.layout.bounding_box_padding}).attr("ry",function(){return e.layout.bounding_box_padding}).style(a),o=function(t){return t.display_range.width+2*e.layout.bounding_box_padding},r=function(){return e.getTrackHeight()-e.layout.track_vertical_spacing},l=function(t){return t.display_range.start-e.layout.bounding_box_padding},h=function(t){return(t.track-1)*e.getTrackHeight()},e.canTransition()?i.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",o).attr("height",r).attr("x",l).attr("y",h):i.attr("width",o).attr("height",r).attr("x",l).attr("y",h),i.exit().remove();var s=f.select(this).selectAll("rect.lz-data_layer-intervals.lz-interval_rect").data([t],function(t){return t[e.layout.id_field]+"_interval_rect"});s.enter().append("rect").attr("class","lz-data_layer-intervals lz-interval_rect"),r=e.layout.track_height,o=function(t){return t.display_range.width},l=function(t){return t.display_range.start},h=function(t){return(t.track-1)*e.getTrackHeight()+e.layout.bounding_box_padding},d=function(t){return e.resolveScalableParameter(e.layout.color,t)},u=function(t){return e.resolveScalableParameter(e.layout.fill_opacity,t)},e.canTransition()?s.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",o).attr("height",r).attr("x",l).attr("y",h).attr("fill",d).attr("fill-opacity",u):s.attr("width",o).attr("height",r).attr("x",l).attr("y",h).attr("fill",d).attr("fill-opacity",u),s.exit().remove();var n=f.select(this).selectAll("rect.lz-data_layer-intervals.lz-clickarea").data([t],function(t){return t.interval_name+"_clickarea"});n.enter().append("rect").attr("class","lz-data_layer-intervals lz-clickarea"),n.attr("id",function(t){return e.getElementId(t)+"_clickarea"}).attr("rx",function(){return e.layout.bounding_box_padding}).attr("ry",function(){return e.layout.bounding_box_padding}),o=function(t){return t.display_range.width},r=function(){return e.getTrackHeight()-e.layout.track_vertical_spacing},l=function(t){return t.display_range.start},h=function(t){return(t.track-1)*e.getTrackHeight()},e.canTransition()?n.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",o).attr("height",r).attr("x",l).attr("y",h):n.attr("width",o).attr("height",r).attr("x",l).attr("y",h),n.exit().remove(),n.on("click",function(t){t.parent.parent.emit("element_clicked",t,!0)}.bind(this)),e.applyBehaviors(n)}),t.exit().remove(),this.previous_tracks!==this.tracks&&this.updateSplitTrackAxis(),this},this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s=this.tooltips[t],n=this.getPageOrigin(),o=s.selector.node().getBoundingClientRect(),r=f.select("#"+this.getElementStatusNodeId(s.data)).node().getBBox(),l=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),h=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right),d=(s.data.display_range.start+s.data.display_range.end)/2-this.layout.bounding_box_padding/2,u=Math.max(o.width/2-d,0),c=Math.max(o.width/2+d-h,0),p=n.x+d-o.width/2-c+u,y=o.width/2-3.5+c-u;o.height+1+7>l-(r.y+r.height)?(e=n.y+r.y-(o.height+1+7),a="down",i=o.height-1):(e=n.y+r.y+r.height+1+7,a="up",i=-8),s.selector.style("left",p+"px").style("top",e+"px"),s.arrow||(s.arrow=s.selector.append("div").style("position","absolute")),s.arrow.attr("class","lz-data_layer-tooltip-arrow_"+a).style("left",y+"px").style("top",i+"px")},this.updateSplitTrackAxis=function(){var i=!!this.layout.track_split_legend_to_y_axis&&"y"+this.layout.track_split_legend_to_y_axis;if(this.layout.split_tracks){var s=+this.tracks||0,t=+this.layout.track_height||0,e=2*(+this.layout.bounding_box_padding||0)+(+this.layout.track_vertical_spacing||0),a=s*t+(s-1)*e;this.parent.scaleHeightToData(a),i&&this.parent.legend&&(this.parent.legend.hide(),this.parent.layout.axes[i]={render:!0,ticks:[],range:{start:a-this.layout.track_height/2,end:this.layout.track_height/2}},this.layout.legend.forEach(function(t){var e=t[this.layout.track_split_field],a=this.track_split_field_index[e];a&&("DESC"===this.layout.track_split_order&&(a=Math.abs(a-s-1)),this.parent.layout.axes[i].ticks.push({y:a,text:t.label}))}.bind(this)),this.layout.y_axis={axis:this.layout.track_split_legend_to_y_axis,floor:1,ceiling:s},this.parent.render()),this.parent_plot.positionPanels()}else i&&this.parent.legend&&(this.layout.always_hide_legend||this.parent.legend.show(),this.parent.layout.axes[i]={render:!1},this.parent.render());return this},this.toggleSplitTracks=function(){return this.layout.split_tracks=!this.layout.split_tracks,this.parent.legend&&!this.layout.always_hide_legend&&(this.parent.layout.margin.bottom=5+(this.layout.split_tracks?0:this.parent.legend.layout.height+5)),this.render(),this.updateSplitTrackAxis(),this},this}),k.DataLayers.add("line",function(t){return this.DefaultLayout={style:{fill:"none","stroke-width":"2px"},interpolate:"linear",x_axis:{field:"x"},y_axis:{field:"y",axis:1},hitarea_width:5},t=k.Layouts.merge(t,this.DefaultLayout),this.mouse_event=null,this.line=null,this.tooltip_timeout=null,k.DataLayer.apply(this,arguments),this.getMouseDisplayAndData=function(){var t={display:{x:f.mouse(this.mouse_event)[0],y:null},data:{},slope:null},e=this.layout.x_axis.field,a=this.layout.y_axis.field,i="x_scale",s="y"+this.layout.y_axis.axis+"_scale";t.data[e]=this.parent[i].invert(t.display.x);var n=(0,f.bisector(function(t){return+t[e]}).left)(this.data,t.data[e])-1,o=this.data[n],r=this.data[n+1],l=f.interpolateNumber(+o[a],+r[a]),h=+r[e]-+o[e];return t.data[a]=l(t.data[e]%h/h),t.display.y=this.parent[s](t.data[a]),this.layout.tooltip.x_precision&&(t.data[e]=t.data[e].toPrecision(this.layout.tooltip.x_precision)),this.layout.tooltip.y_precision&&(t.data[a]=t.data[a].toPrecision(this.layout.tooltip.y_precision)),t.slope=(this.parent[s](r[a])-this.parent[s](o[a]))/(this.parent[i](r[e])-this.parent[i](o[e])),t},this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s,n,o=this.tooltips[t],r=o.selector.node().getBoundingClientRect(),l=parseFloat(this.layout.style["stroke-width"])||1,h=this.getPageOrigin(),d=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),u=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right),c=this.getMouseDisplayAndData();if(1=d?(e=h.y+c.display.y+7+6-r.height,i=r.height-14-6):(e=h.y+c.display.y-r.height/2,i=r.height/2-7);else{var p=Math.max(r.width/2-c.display.x,0),y=Math.max(r.width/2+c.display.x-u,0);a=h.x+c.display.x-r.width/2-y+p;var g=r.width-17.5;s=r.width/2-7+y-p,s=Math.min(Math.max(s,3.5),g),r.height+l+7>c.display.y?(e=h.y+c.display.y+l+7,n="up",i=0-l-7):(e=h.y+c.display.y-(r.height+l+7),n="down",i=r.height-l)}o.selector.style({left:a+"px",top:e+"px"}),o.arrow||(o.arrow=o.selector.append("div").style("position","absolute")),o.arrow.attr("class","lz-data_layer-tooltip-arrow_"+n).style({left:s+"px",top:i+"px"})},this.render=function(){var e=this,a=this.parent,i=this.layout.x_axis.field,s=this.layout.y_axis.field,n="x_scale",o="y"+this.layout.y_axis.axis+"_scale",t=this.svg.group.selectAll("path.lz-data_layer-line").data([this.data]);if(this.path=t.enter().append("path").attr("class","lz-data_layer-line"),this.layout.style.fill&&"none"!==this.layout.style.fill?this.line=f.svg.area().x(function(t){return parseFloat(a[n](t[i]))}).y0(function(t){return parseFloat(a[o](0))}).y1(function(t){return parseFloat(a[o](t[s]))}):this.line=f.svg.line().x(function(t){return parseFloat(a[n](t[i]))}).y(function(t){return parseFloat(a[o](t[s]))}).interpolate(this.layout.interpolate),this.canTransition()?t.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("d",this.line).style(this.layout.style):t.attr("d",this.line).style(this.layout.style),this.layout.tooltip){var r=parseFloat(this.layout.hitarea_width).toString()+"px",l=this.svg.group.selectAll("path.lz-data_layer-line-hitarea").data([this.data]);l.enter().append("path").attr("class","lz-data_layer-line-hitarea").style("stroke-width",r);var h=f.svg.line().x(function(t){return parseFloat(a[n](t[i]))}).y(function(t){return parseFloat(a[o](t[s]))}).interpolate(this.layout.interpolate);l.attr("d",h).on("mouseover",function(){clearTimeout(e.tooltip_timeout),e.mouse_event=this;var t=e.getMouseDisplayAndData();e.createTooltip(t.data)}).on("mousemove",function(){clearTimeout(e.tooltip_timeout),e.mouse_event=this;var t=e.getMouseDisplayAndData();e.updateTooltip(t.data),e.positionTooltip(e.getElementId())}).on("mouseout",function(){e.tooltip_timeout=setTimeout(function(){e.mouse_event=null,e.destroyTooltip(e.getElementId())},300)}),l.exit().remove()}t.exit().remove()},this.setElementStatus=function(t,e,a){return this.setAllElementStatus(t,a)},this.setElementStatusByFilters=function(t,e){return this.setAllElementStatus(t,e)},this.setAllElementStatus=function(t,e){if(void 0===t||-1===k.DataLayer.Statuses.adjectives.indexOf(t))throw new Error("Invalid status passed to DataLayer.setAllElementStatus()");if(void 0===this.state[this.state_id][t])return this;void 0===e&&(e=!0),this.global_statuses[t]=e;var a="lz-data_layer-line";return Object.keys(this.global_statuses).forEach(function(t){this.global_statuses[t]&&(a+=" lz-data_layer-line-"+t)}.bind(this)),this.path.attr("class",a),this.parent.emit("layout_changed",!0),this},this}),k.DataLayers.add("orthogonal_line",function(t){return this.DefaultLayout={style:{stroke:"#D3D3D3","stroke-width":"3px","stroke-dasharray":"10px 10px"},orientation:"horizontal",x_axis:{axis:1,decoupled:!0},y_axis:{axis:1,decoupled:!0},offset:0},t=k.Layouts.merge(t,this.DefaultLayout),-1===["horizontal","vertical"].indexOf(t.orientation)&&(t.orientation="horizontal"),this.data=[],this.line=null,k.DataLayer.apply(this,arguments),this.render=function(){var i=this.parent,s="y"+this.layout.y_axis.axis+"_scale",t="x_extent",e="y"+this.layout.y_axis.axis+"_extent";if("horizontal"===this.layout.orientation)this.data=[{x:i[t][0],y:this.layout.offset},{x:i[t][1],y:this.layout.offset}];else{if("vertical"!==this.layout.orientation)throw new Error('Unrecognized vertical line type. Must be "vertical" or "horizontal"');this.data=[{x:this.layout.offset,y:i[e][0]},{x:this.layout.offset,y:i[e][1]}]}var a=this.svg.group.selectAll("path.lz-data_layer-line").data([this.data]);this.path=a.enter().append("path").attr("class","lz-data_layer-line");var n=[i.layout.cliparea.height,0];this.line=f.svg.line().x(function(t,e){var a=parseFloat(i.x_scale(t.x));return isNaN(a)?i.x_range[e]:a}).y(function(t,e){var a=parseFloat(i[s](t.y));return isNaN(a)?n[e]:a}).interpolate("linear"),this.canTransition()?a.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("d",this.line).style(this.layout.style):a.attr("d",this.line).style(this.layout.style),a.exit().remove()},this}),k.DataLayers.add("scatter",function(t){return this.DefaultLayout={point_size:40,point_shape:"circle",tooltip_positioning:"horizontal",color:"#888888",fill_opacity:1,y_axis:{axis:1},id_field:"id"},(t=k.Layouts.merge(t,this.DefaultLayout)).label&&isNaN(t.label.spacing)&&(t.label.spacing=4),k.DataLayer.apply(this,arguments),this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s,n,o=this.tooltips[t],r=this.resolveScalableParameter(this.layout.point_size,o.data),l=Math.sqrt(r/Math.PI),h=this.getPageOrigin(),d=this.parent.x_scale(o.data[this.layout.x_axis.field]),u="y"+this.layout.y_axis.axis+"_scale",c=this.parent[u](o.data[this.layout.y_axis.field]),p=o.selector.node().getBoundingClientRect(),y=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),g=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right);if("vertical"===this.layout.tooltip_positioning){var _=Math.max(p.width/2-d,0),f=Math.max(p.width/2+d-g,0);a=h.x+d-p.width/2-f+_,n=p.width/2-3.5+f-_-l,p.height+1+7>y-(c+l)?(e=h.y+c-(l+p.height+1+7),i="down",s=p.height-1):(e=h.y+c+l+1+7,i="up",s=-8)}else d<=this.parent.layout.width/2?(a=h.x+d+l+7+1,i="left",n=-8):(a=h.x+d-p.width-l-7-1,i="right",n=p.width-1),y=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),c-p.height/2<=0?(e=h.y+c-10.5-6,s=6):c+p.height/2>=y?(e=h.y+c+7+6-p.height,s=p.height-14-6):(e=h.y+c-p.height/2,s=p.height/2-7);o.selector.style("left",a+"px").style("top",e+"px"),o.arrow||(o.arrow=o.selector.append("div").style("position","absolute")),o.arrow.attr("class","lz-data_layer-tooltip-arrow_"+i).style("left",n+"px").style("top",s+"px")},this.flip_labels=function(){var n=this,o=n.resolveScalableParameter(n.layout.point_size,{}),r=n.layout.label.spacing,l=Boolean(n.layout.label.lines),h=2*r,s=n.parent.layout.width-n.parent.layout.margin.left-n.parent.layout.margin.right-2*r,d=function(t,e){var a=+t.attr("x"),i=2*r+2*Math.sqrt(o);if(l)var s=+e.attr("x2"),n=r+2*Math.sqrt(o);"start"===t.style("text-anchor")?(t.style("text-anchor","end"),t.attr("x",a-i),l&&e.attr("x2",s-n)):(t.style("text-anchor","start"),t.attr("x",a+i),l&&e.attr("x2",s+n))};n.label_texts.each(function(t,e){var a=f.select(this);if(+a.attr("x")+a.node().getBoundingClientRect().width+r>s){var i=l?f.select(n.label_lines[0][e]):null;d(a,i)}}),n.label_texts.each(function(t,e){var a=f.select(this);if("end"!==a.style("text-anchor")){a.attr("x");var i=a.node().getBoundingClientRect(),s=l?f.select(n.label_lines[0][e]):null;n.label_texts.each(function(){var t=f.select(this).node().getBoundingClientRect();i.leftt.left&&i.topt.top&&(d(a,s),+a.attr("x")-i.width-ra.left&&e.topa.top){g=!0;var i,s=t.attr("y"),n=.5*(e.toph?(i=o-+c,o=+c,r-=i):r+a.height/2>h&&(i=r-+s,r=+s,o-=i),u.attr("y",o),t.attr("y",r)}}}})}),g){if(p.layout.label.lines){var a=p.label_texts[0];p.label_lines.attr("y2",function(t,e){return f.select(a[e]).attr("y")})}this.seperate_iterations<150&&setTimeout(function(){this.separate_labels()}.bind(this),1)}}},this.render=function(){var s=this,i="x_scale",n="y"+this.layout.y_axis.axis+"_scale";if(this.layout.label){var t=this.data.filter(function(a){if(s.layout.label.filters){var i=!0;return s.layout.label.filters.forEach(function(t){var e=new k.Data.Field(t.field).resolve(a);if(-1===["!=","="].indexOf(t.operator)&&isNaN(e))i=!1;else switch(t.operator){case"<":e":e>t.value||(i=!1);break;case">=":e>=t.value||(i=!1);break;case"=":e!==t.value&&(i=!1);break;case"!=":e==t.value&&(i=!1);break;default:i=!1}}),i}return!0}),e=this;this.label_groups=this.svg.group.selectAll("g.lz-data_layer-"+this.layout.type+"-label").data(t,function(t){return t[e.layout.id_field]+"_label"}),this.label_groups.enter().append("g").attr("class","lz-data_layer-"+this.layout.type+"-label"),this.label_texts&&this.label_texts.remove(),this.label_texts=this.label_groups.append("text").attr("class","lz-data_layer-"+this.layout.type+"-label"),this.label_texts.text(function(t){return k.parseFields(t,s.layout.label.text||"")}).style(s.layout.label.style||{}).attr({x:function(t){var e=s.parent[i](t[s.layout.x_axis.field])+Math.sqrt(s.resolveScalableParameter(s.layout.point_size,t))+s.layout.label.spacing;return isNaN(e)&&(e=-1e3),e},y:function(t){var e=s.parent[n](t[s.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),e},"text-anchor":function(){return"start"}}),s.layout.label.lines&&(this.label_lines&&this.label_lines.remove(),this.label_lines=this.label_groups.append("line").attr("class","lz-data_layer-"+this.layout.type+"-label"),this.label_lines.style(s.layout.label.lines.style||{}).attr({x1:function(t){var e=s.parent[i](t[s.layout.x_axis.field]);return isNaN(e)&&(e=-1e3),e},y1:function(t){var e=s.parent[n](t[s.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),e},x2:function(t){var e=s.parent[i](t[s.layout.x_axis.field])+Math.sqrt(s.resolveScalableParameter(s.layout.point_size,t))+s.layout.label.spacing/2;return isNaN(e)&&(e=-1e3),e},y2:function(t){var e=s.parent[n](t[s.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),e}})),this.label_groups.exit().remove()}else this.label_groups&&this.label_groups.remove(),this.label_lines&&this.label_lines.remove();var a=this.svg.group.selectAll("path.lz-data_layer-"+this.layout.type).data(this.data,function(t){return t[this.layout.id_field]}.bind(this)),o=isNaN(this.parent.layout.height)?0:this.parent.layout.height;a.enter().append("path").attr("class","lz-data_layer-"+this.layout.type).attr("id",function(t){return this.getElementId(t)}.bind(this)).attr("transform","translate(0,"+o+")");var r=function(t){var e=this.parent[i](t[this.layout.x_axis.field]),a=this.parent[n](t[this.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),isNaN(a)&&(a=-1e3),"translate("+e+","+a+")"}.bind(this),l=function(t){return this.resolveScalableParameter(this.layout.color,t)}.bind(this),h=function(t){return this.resolveScalableParameter(this.layout.fill_opacity,t)}.bind(this),d=f.svg.symbol().size(function(t){return this.resolveScalableParameter(this.layout.point_size,t)}.bind(this)).type(function(t){return this.resolveScalableParameter(this.layout.point_shape,t)}.bind(this));this.canTransition()?a.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("transform",r).attr("fill",l).attr("fill-opacity",h).attr("d",d):a.attr("transform",r).attr("fill",l).attr("fill-opacity",h).attr("d",d),a.exit().remove(),a.on("click.event_emitter",function(t){this.parent.emit("element_clicked",t,!0)}.bind(this)),this.applyBehaviors(a),this.layout.label&&(this.flip_labels(),this.seperate_iterations=0,this.separate_labels(),this.label_texts.on("click.event_emitter",function(t){this.parent.emit("element_clicked",t,!0)}.bind(this)),this.applyBehaviors(this.label_texts))},this.makeLDReference=function(t){var e=null;if(void 0===t)throw new Error("makeLDReference requires one argument of any type");e="object"==typeof t?this.layout.id_field&&void 0!==t[this.layout.id_field]?t[this.layout.id_field].toString():void 0!==t.id?t.id.toString():t.toString():t.toString(),this.parent_plot.applyState({ldrefvar:e})},this}),k.DataLayers.extend("scatter","category_scatter",{_prepareData:function(){var a=this.layout.x_axis.field||"x",o=this.layout.x_axis.category_field;if(!o)throw new Error("Layout for "+this.layout.id+" must specify category_field");var t=this.data.sort(function(t,e){var a=t[o],i=e[o],s="string"==typeof a?a.toLowerCase():a,n="string"==typeof i?i.toLowerCase():i;return s===n?0:s&`]/g,function(t){switch(t){case"'":return"'";case'"':return""";case"<":return"<";case">":return">";case"&":return"&";case"`":return"`"}}):""}),k.ScaleFunctions=(n={},(s={}).get=function(t,e,a){if(t){if(n[t])return void 0===e&&void 0===a?n[t]:n[t](e,a);throw new Error("scale function ["+t+"] not found")}return null},s.set=function(t,e){e?n[t]=e:delete n[t]},s.add=function(t,e){if(n[t])throw new Error("scale function already exists with name: "+t);s.set(t,e)},s.list=function(){return Object.keys(n)},s),k.ScaleFunctions.add("if",function(t,e){return void 0===e||t.field_value!==e?void 0!==t.else?t.else:null:t.then}),k.ScaleFunctions.add("numerical_bin",function(t,a){var e=t.breaks||[],i=t.values||[];if(null==a||isNaN(+a))return t.null_value?t.null_value:null;var s=e.reduce(function(t,e){return+a=t.breaks[t.breaks.length-1])return e[i.length-1];var n=null;if(i.forEach(function(t,e){e&&i[e-1]<=+a&&i[e]>=+a&&(n=e)}),null===n)return s;var o=(+a-i[n-1])/(i[n]-i[n-1]);return isFinite(o)?f.interpolate(e[n-1],e[n])(o):s}),k.Dashboard=function(t){if(!(t instanceof k.Plot||t instanceof k.Panel))throw new Error("Unable to create dashboard, parent must be a locuszoom plot or panel");return this.parent=t,this.id=this.parent.getBaseId()+".dashboard",this.type=this.parent instanceof k.Plot?"plot":"panel",this.parent_plot="plot"===this.type?this.parent:this.parent.parent,this.selector=null,this.components=[],this.hide_timeout=null,this.persist=!1,this.initialize()},k.Dashboard.prototype.initialize=function(){return Array.isArray(this.parent.layout.dashboard.components)&&this.parent.layout.dashboard.components.forEach(function(t){try{var e=k.Dashboard.Components.get(t.type,t,this);this.components.push(e)}catch(t){console.warn(t)}}.bind(this)),"panel"===this.type&&(f.select(this.parent.parent.svg.node().parentNode).on("mouseover."+this.id,function(){clearTimeout(this.hide_timeout),this.selector&&"hidden"!==this.selector.style("visibility")||this.show()}.bind(this)),f.select(this.parent.parent.svg.node().parentNode).on("mouseout."+this.id,function(){clearTimeout(this.hide_timeout),this.hide_timeout=setTimeout(function(){this.hide()}.bind(this),300)}.bind(this))),this},k.Dashboard.prototype.shouldPersist=function(){if(this.persist)return!0;var e=!1;return this.components.forEach(function(t){e=e||t.shouldPersist()}),!!(e=e||this.parent_plot.panel_boundaries.dragging||this.parent_plot.interaction.dragging)},k.Dashboard.prototype.show=function(){if(!this.selector){switch(this.type){case"plot":this.selector=f.select(this.parent.svg.node().parentNode).insert("div",":first-child");break;case"panel":this.selector=f.select(this.parent.parent.svg.node().parentNode).insert("div",".lz-data_layer-tooltip, .lz-dashboard-menu, .lz-curtain").classed("lz-panel-dashboard",!0)}this.selector.classed("lz-dashboard",!0).classed("lz-"+this.type+"-dashboard",!0).attr("id",this.id)}return this.components.forEach(function(t){t.show()}),this.selector.style({visibility:"visible"}),this.update()},k.Dashboard.prototype.update=function(){return this.selector?(this.components.forEach(function(t){t.update()}),this.position()):this},k.Dashboard.prototype.position=function(){if(!this.selector)return this;if("panel"===this.type){var t=this.parent.getPageOrigin(),e=(t.y+3.5).toString()+"px",a=t.x.toString()+"px",i=(this.parent.layout.width-4).toString()+"px";this.selector.style({position:"absolute",top:e,left:a,width:i})}return this.components.forEach(function(t){t.position()}),this},k.Dashboard.prototype.hide=function(){return!this.selector||this.shouldPersist()||(this.components.forEach(function(t){t.hide()}),this.selector.style({visibility:"hidden"})),this},k.Dashboard.prototype.destroy=function(t){return void 0===t&&(t=!1),this.selector&&(this.shouldPersist()&&!t||(this.components.forEach(function(t){t.destroy(!0)}),this.components=[],this.selector.remove(),this.selector=null)),this},k.Dashboard.Component=function(t,e){return this.layout=t||{},this.layout.color||(this.layout.color="gray"),this.parent=e||null,this.parent_panel=null,this.parent_plot=null,this.parent_svg=null,this.parent instanceof k.Dashboard&&("panel"===this.parent.type?(this.parent_panel=this.parent.parent,this.parent_plot=this.parent.parent.parent,this.parent_svg=this.parent_panel):(this.parent_plot=this.parent.parent,this.parent_svg=this.parent_plot)),this.selector=null,this.button=null,this.persist=!1,this.layout.position||(this.layout.position="left"),this},k.Dashboard.Component.prototype.show=function(){if(this.parent&&this.parent.selector){if(!this.selector){var t=-1!==["start","middle","end"].indexOf(this.layout.group_position)?" lz-dashboard-group-"+this.layout.group_position:"";this.selector=this.parent.selector.append("div").attr("class","lz-dashboard-"+this.layout.position+t),this.layout.style&&this.selector.style(this.layout.style),"function"==typeof this.initialize&&this.initialize()}return this.button&&"highlighted"===this.button.status&&this.button.menu.show(),this.selector.style({visibility:"visible"}),this.update(),this.position()}},k.Dashboard.Component.prototype.update=function(){},k.Dashboard.Component.prototype.position=function(){return this.button&&this.button.menu.position(),this},k.Dashboard.Component.prototype.shouldPersist=function(){return!!this.persist||!(!this.button||!this.button.persist)},k.Dashboard.Component.prototype.hide=function(){return!this.selector||this.shouldPersist()||(this.button&&this.button.menu.hide(),this.selector.style({visibility:"hidden"})),this},k.Dashboard.Component.prototype.destroy=function(t){return void 0===t&&(t=!1),this.selector&&(this.shouldPersist()&&!t||(this.button&&this.button.menu&&this.button.menu.destroy(),this.selector.remove(),this.selector=null,this.button=null)),this},k.Dashboard.Components=(i={},(a={}).get=function(t,e,a){if(t){if(i[t]){if("object"!=typeof e)throw new Error("invalid layout argument for dashboard component ["+t+"]");return new i[t](e,a)}throw new Error("dashboard component ["+t+"] not found")}return null},a.set=function(t,e){if(e){if("function"!=typeof e)throw new Error("unable to set dashboard component ["+t+"], argument provided is not a function");i[t]=e,i[t].prototype=new k.Dashboard.Component}else delete i[t]},a.add=function(t,e){if(i[t])throw new Error("dashboard component already exists with name: "+t);a.set(t,e)},a.list=function(){return Object.keys(i)},a),k.Dashboard.Component.Button=function(t){if(!(t instanceof k.Dashboard.Component))throw new Error("Unable to create dashboard component button, invalid parent");this.parent=t,this.parent_panel=this.parent.parent_panel,this.parent_plot=this.parent.parent_plot,this.parent_svg=this.parent.parent_svg,this.parent_dashboard=this.parent.parent,this.selector=null,this.tag="a",this.setTag=function(t){return void 0!==t&&(this.tag=t.toString()),this},this.html="",this.setHtml=function(t){return void 0!==t&&(this.html=t.toString()),this},this.setText=this.setHtml,this.title="",this.setTitle=function(t){return void 0!==t&&(this.title=t.toString()),this},this.color="gray",this.setColor=function(t){return void 0!==t&&(-1!==["gray","red","orange","yellow","green","blue","purple"].indexOf(t)?this.color=t:this.color="gray"),this},this.style={},this.setStyle=function(t){return void 0!==t&&(this.style=t),this},this.getClass=function(){var t=-1!==["start","middle","end"].indexOf(this.parent.layout.group_position)?" lz-dashboard-button-group-"+this.parent.layout.group_position:"";return"lz-dashboard-button lz-dashboard-button-"+this.color+(this.status?"-"+this.status:"")+t},this.persist=!1,this.permanent=!1,this.setPermanent=function(t){return t=void 0===t||Boolean(t),this.permanent=t,this.permanent&&(this.persist=!0),this},this.shouldPersist=function(){return this.permanent||this.persist},this.status="",this.setStatus=function(t){return void 0!==t&&-1!==["","highlighted","disabled"].indexOf(t)&&(this.status=t),this.update()},this.highlight=function(t){return(t=void 0===t||Boolean(t))?this.setStatus("highlighted"):"highlighted"===this.status?this.setStatus(""):this},this.disable=function(t){return(t=void 0===t||Boolean(t))?this.setStatus("disabled"):"disabled"===this.status?this.setStatus(""):this},this.onmouseover=function(){},this.setOnMouseover=function(t){return this.onmouseover="function"==typeof t?t:function(){},this},this.onmouseout=function(){},this.setOnMouseout=function(t){return this.onmouseout="function"==typeof t?t:function(){},this},this.onclick=function(){},this.setOnclick=function(t){return this.onclick="function"==typeof t?t:function(){},this},this.show=function(){if(this.parent)return this.selector||(this.selector=this.parent.selector.append(this.tag).attr("class",this.getClass())),this.update()},this.preUpdate=function(){return this},this.update=function(){return this.selector&&(this.preUpdate(),this.selector.attr("class",this.getClass()).attr("title",this.title).style(this.style).on("mouseover","disabled"===this.status?null:this.onmouseover).on("mouseout","disabled"===this.status?null:this.onmouseout).on("click","disabled"===this.status?null:this.onclick).html(this.html),this.menu.update(),this.postUpdate()),this},this.postUpdate=function(){return this},this.hide=function(){return this.selector&&!this.shouldPersist()&&(this.selector.remove(),this.selector=null),this},this.menu={outer_selector:null,inner_selector:null,scroll_position:0,hidden:!0,show:function(){return this.menu.outer_selector||(this.menu.outer_selector=f.select(this.parent_plot.svg.node().parentNode).append("div").attr("class","lz-dashboard-menu lz-dashboard-menu-"+this.color).attr("id",this.parent_svg.getBaseId()+".dashboard.menu"),this.menu.inner_selector=this.menu.outer_selector.append("div").attr("class","lz-dashboard-menu-content"),this.menu.inner_selector.on("scroll",function(){this.menu.scroll_position=this.menu.inner_selector.node().scrollTop}.bind(this))),this.menu.outer_selector.style({visibility:"visible"}),this.menu.hidden=!1,this.menu.update()}.bind(this),update:function(){return this.menu.outer_selector?(this.menu.populate(),this.menu.inner_selector&&(this.menu.inner_selector.node().scrollTop=this.menu.scroll_position),this.menu.position()):this.menu}.bind(this),position:function(){if(!this.menu.outer_selector)return this.menu;this.menu.outer_selector.style({height:null});var t=this.parent_svg.getPageOrigin(),e=document.documentElement.scrollTop||document.body.scrollTop,a=this.parent_plot.getContainerOffset(),i=this.parent_dashboard.selector.node().getBoundingClientRect(),s=this.selector.node().getBoundingClientRect(),n=this.menu.outer_selector.node().getBoundingClientRect(),o=this.menu.inner_selector.node().scrollHeight,r=0,l=0;"panel"===this.parent_dashboard.type?(r=t.y+i.height+6,l=Math.max(t.x+this.parent_svg.layout.width-n.width-3,t.x+3)):(r=s.bottom+e+3-a.top,l=Math.max(s.left+s.width-n.width-a.left,t.x+3));var h=Math.max(this.parent_svg.layout.width-6-20,20),d=h,u=h-12,c=Math.max(this.parent_svg.layout.height-30-14,14),p=Math.min(o,c),y=c;return this.menu.outer_selector.style({top:r.toString()+"px",left:l.toString()+"px","max-width":d.toString()+"px","max-height":y.toString()+"px",height:p.toString()+"px"}),this.menu.inner_selector.style({"max-width":u.toString()+"px"}),this.menu.inner_selector.node().scrollTop=this.menu.scroll_position,this.menu}.bind(this),hide:function(){return this.menu.outer_selector&&(this.menu.outer_selector.style({visibility:"hidden"}),this.menu.hidden=!0),this.menu}.bind(this),destroy:function(){return this.menu.outer_selector&&(this.menu.inner_selector.remove(),this.menu.outer_selector.remove(),this.menu.inner_selector=null,this.menu.outer_selector=null),this.menu}.bind(this),populate:function(){}.bind(this),setPopulate:function(t){return"function"==typeof t?(this.menu.populate=t,this.setOnclick(function(){this.menu.hidden?(this.menu.show(),this.highlight().update(),this.persist=!0):(this.menu.hide(),this.highlight(!1).update(),this.permanent||(this.persist=!1))}.bind(this))):this.setOnclick(),this}.bind(this)}},k.Dashboard.Components.add("title",function(e){k.Dashboard.Component.apply(this,arguments),this.show=function(){return this.div_selector=this.parent.selector.append("div").attr("class","lz-dashboard-title lz-dashboard-"+this.layout.position),this.title_selector=this.div_selector.append("h3"),this.update()},this.update=function(){var t=e.title.toString();return this.layout.subtitle&&(t+=" "+this.layout.subtitle+""),this.title_selector.html(t),this}}),k.Dashboard.Components.add("dimensions",function(a){k.Dashboard.Component.apply(this,arguments),this.update=function(){var t=-1===this.parent_plot.layout.width.toString().indexOf(".")?this.parent_plot.layout.width:this.parent_plot.layout.width.toFixed(2),e=-1===this.parent_plot.layout.height.toString().indexOf(".")?this.parent_plot.layout.height:this.parent_plot.layout.height.toFixed(2);return this.selector.html(t+"px × "+e+"px"),a.class&&this.selector.attr("class",a.class),a.style&&this.selector.style(a.style),this}}),k.Dashboard.Components.add("region_scale",function(t){k.Dashboard.Component.apply(this,arguments),this.update=function(){return isNaN(this.parent_plot.state.start)||isNaN(this.parent_plot.state.end)||null===this.parent_plot.state.start||null===this.parent_plot.state.end?this.selector.style("display","none"):(this.selector.style("display",null),this.selector.html(k.positionIntToString(this.parent_plot.state.end-this.parent_plot.state.start,null,!0))),t.class&&this.selector.attr("class",t.class),t.style&&this.selector.style(t.style),this}}),k.Dashboard.Components.add("download",function(a){for(var t in k.Dashboard.Component.apply(this,arguments),this.update=function(){return this.button||(this.button=new k.Dashboard.Component.Button(this).setColor(a.color).setHtml(a.button_html||"Download Image").setTitle(a.button_title||"Download image of the current plot as locuszoom.svg").setOnMouseover(function(){this.button.selector.classed("lz-dashboard-button-gray-disabled",!0).html("Preparing Image"),this.generateBase64SVG().then(function(t){var e=this.button.selector.attr("href");e&&URL.revokeObjectURL(e),this.button.selector.attr("href",t).classed("lz-dashboard-button-gray-disabled",!1).classed("lz-dashboard-button-gray-highlighted",!0).html(a.button_html||"Download Image")}.bind(this))}.bind(this)).setOnMouseout(function(){this.button.selector.classed("lz-dashboard-button-gray-highlighted",!1)}.bind(this)),this.button.show(),this.button.selector.attr("href-lang","image/svg+xml").attr("download",a.filename||"locuszoom.svg")),this},this.css_string="",Object.keys(document.styleSheets))if(null!==document.styleSheets[t].href&&-1!==document.styleSheets[t].href.indexOf("locuszoom.css")){k.createCORSPromise("GET",document.styleSheets[t].href).then(function(t){this.css_string=t.replace(/[\r\n]/g," ").replace(/\s+/g," "),this.css_string.indexOf("/* ! LocusZoom HTML Styles */")&&(this.css_string=this.css_string.substring(0,this.css_string.indexOf("/* ! LocusZoom HTML Styles */")))}.bind(this));break}this.generateBase64SVG=function(){return new Promise(function(t,e){var a=this.parent.selector.append("div").style("display","none").html(this.parent_plot.svg.node().outerHTML);a.selectAll("g.lz-curtain").remove(),a.selectAll("g.lz-mouse_guide").remove(),a.selectAll("g.tick text").each(function(){var t=10*+f.select(this).attr("dy").substring(-2).slice(0,-2);f.select(this).attr("dy",t)});var i=f.select(a.select("svg").node().parentNode).html(),s='",n=i.indexOf(">")+1;i=i.slice(0,n)+s+i.slice(n),a.remove();var o=new Blob([i],{type:"image/svg+xml"});t(URL.createObjectURL(o))}.bind(this))}}),k.Dashboard.Components.add("remove_panel",function(e){k.Dashboard.Component.apply(this,arguments),this.update=function(){return this.button||(this.button=new k.Dashboard.Component.Button(this).setColor(e.color).setHtml("×").setTitle("Remove panel").setOnclick(function(){if(!e.suppress_confirm&&!confirm("Are you sure you want to remove this panel? This cannot be undone!"))return!1;var t=this.parent_panel;return t.dashboard.hide(!0),f.select(t.parent.svg.node().parentNode).on("mouseover."+t.getBaseId()+".dashboard",null),f.select(t.parent.svg.node().parentNode).on("mouseout."+t.getBaseId()+".dashboard",null),t.parent.removePanel(t.id)}.bind(this)),this.button.show()),this}}),k.Dashboard.Components.add("move_panel_up",function(e){k.Dashboard.Component.apply(this,arguments),this.update=function(){if(this.button){var t=0===this.parent_panel.layout.y_index;return this.button.disable(t),this}return this.button=new k.Dashboard.Component.Button(this).setColor(e.color).setHtml("▴").setTitle("Move panel up").setOnclick(function(){this.parent_panel.moveUp(),this.update()}.bind(this)),this.button.show(),this.update()}}),k.Dashboard.Components.add("move_panel_down",function(e){k.Dashboard.Component.apply(this,arguments),this.update=function(){if(this.button){var t=this.parent_panel.layout.y_index===this.parent_plot.panel_ids_by_y_index.length-1;return this.button.disable(t),this}return this.button=new k.Dashboard.Component.Button(this).setColor(e.color).setHtml("▾").setTitle("Move panel down").setOnclick(function(){this.parent_panel.moveDown(),this.update()}.bind(this)),this.button.show(),this.update()}}),k.Dashboard.Components.add("shift_region",function(t){if(k.Dashboard.Component.apply(this,arguments),isNaN(this.parent_plot.state.start)||isNaN(this.parent_plot.state.end))return this.update=function(){},void console.warn("Unable to add shift_region dashboard component: plot state does not have region bounds");(isNaN(t.step)||0===t.step)&&(t.step=5e4),"string"!=typeof t.button_html&&(t.button_html=0":"<"),"string"!=typeof t.button_title&&(t.button_title="Shift region by "+(0=this.parent_plot.layout.max_region_scale&&(t=!1),i.step<0&&!isNaN(this.parent_plot.layout.min_region_scale)&&e<=this.parent_plot.layout.min_region_scale&&(t=!1),this.button.disable(!t),this}return this.button=new k.Dashboard.Component.Button(this).setColor(i.color).setHtml(i.button_html).setTitle(i.button_title).setOnclick(function(){var t=this.parent_plot.state.end-this.parent_plot.state.start,e=t*(1+i.step);isNaN(this.parent_plot.layout.max_region_scale)||(e=Math.min(e,this.parent_plot.layout.max_region_scale)),isNaN(this.parent_plot.layout.min_region_scale)||(e=Math.max(e,this.parent_plot.layout.min_region_scale));var a=Math.floor((e-t)/2);this.parent_plot.applyState({start:Math.max(this.parent_plot.state.start-a,1),end:this.parent_plot.state.end+a})}.bind(this)),this.button.show(),this}}),k.Dashboard.Components.add("menu",function(t){k.Dashboard.Component.apply(this,arguments),this.update=function(){return this.button||(this.button=new k.Dashboard.Component.Button(this).setColor(t.color).setHtml(t.button_html).setTitle(t.button_title),this.button.menu.setPopulate(function(){this.button.menu.inner_selector.html(t.menu_html)}.bind(this)),this.button.show()),this}}),k.Dashboard.Components.add("covariates_model",function(t){k.Dashboard.Component.apply(this,arguments),this.initialize=function(){this.parent_plot.state.model=this.parent_plot.state.model||{},this.parent_plot.state.model.covariates=this.parent_plot.state.model.covariates||[],this.parent_plot.CovariatesModel={button:this,add:function(t){var e=JSON.parse(JSON.stringify(t));"object"==typeof t&&"string"!=typeof e.html&&(e.html="function"==typeof t.toHTML?t.toHTML():t.toString());for(var a=0;athis.parent.layout.width&&(g+=_,y=p,e.attr("transform","translate("+y+","+g+")")),y+=u.width+3*p}this.elements.push(e)}.bind(this))}.bind(this));var t=this.elements_group.node().getBoundingClientRect();return this.layout.width=t.width+2*this.layout.padding,this.layout.height=t.height+2*this.layout.padding,this.background_rect.attr("width",this.layout.width).attr("height",this.layout.height),this.selector.style({visibility:this.layout.hidden?"hidden":"visible"}),this.position()},k.Legend.prototype.position=function(){if(!this.selector)return this;var t=this.selector.node().getBoundingClientRect();isNaN(+this.layout.pad_from_bottom)||(this.layout.origin.y=this.parent.layout.height-t.height-+this.layout.pad_from_bottom),isNaN(+this.layout.pad_from_right)||(this.layout.origin.x=this.parent.layout.width-t.width-+this.layout.pad_from_right),this.selector.attr("transform","translate("+this.layout.origin.x+","+this.layout.origin.y+")")},k.Legend.prototype.hide=function(){this.layout.hidden=!0,this.render()},k.Legend.prototype.show=function(){this.layout.hidden=!1,this.render()},k.Data=k.Data||{},k.DataSources=function(){this.sources={}},k.DataSources.prototype.addSource=function(t,e){return console.warn("Warning: .addSource() is deprecated. Use .add() instead"),this.add(t,e)},k.DataSources.prototype.add=function(t,e){return t.match(/[^A-Za-z0-9_]/)&&console.warn("Deprecation warning: source name '"+t+"' should contain only alphanumeric characters or underscores. Use of other characters may break layouts, and will be disallowed in the future."),this.set(t,e)},k.DataSources.prototype.set=function(t,e){if(Array.isArray(e)){var a=k.KnownDataSources.create.apply(null,e);a.source_id=t,this.sources[t]=a}else null!==e?(e.source_id=t,this.sources[t]=e):delete this.sources[t];return this},k.DataSources.prototype.getSource=function(t){return console.warn("Warning: .getSource() is deprecated. Use .get() instead"),this.get(t)},k.DataSources.prototype.get=function(t){return this.sources[t]},k.DataSources.prototype.removeSource=function(t){return console.warn("Warning: .removeSource() is deprecated. Use .remove() instead"),this.remove(t)},k.DataSources.prototype.remove=function(t){return this.set(t,null)},k.DataSources.prototype.fromJSON=function(e){"string"==typeof e&&(e=JSON.parse(e));var a=this;return Object.keys(e).forEach(function(t){a.set(t,e[t])}),a},k.DataSources.prototype.keys=function(){return Object.keys(this.sources)},k.DataSources.prototype.toJSON=function(){return this.sources},k.Data.Field=function(t){var e=/^(?:([^:]+):)?([^:|]*)(\|.+)*$/.exec(t);this.full_name=t,this.namespace=e[1]||null,this.name=e[2]||null,this.transformations=[],"string"==typeof e[3]&&1e[d]))for(var o=0;othis.layout.height&&(s=Math.floor((this.layout.margin.top+this.layout.margin.bottom-this.layout.height)/2),this.layout.margin.top-=s,this.layout.margin.bottom-=s),this.layout.margin.left+this.layout.margin.right>this.layout.width&&(s=Math.floor((this.layout.margin.left+this.layout.margin.right-this.layout.width)/2),this.layout.margin.left-=s,this.layout.margin.right-=s),["top","right","bottom","left"].forEach(function(t){this.layout.margin[t]=Math.max(this.layout.margin[t],0)}.bind(this)),this.layout.cliparea.width=Math.max(this.layout.width-(this.layout.margin.left+this.layout.margin.right),0),this.layout.cliparea.height=Math.max(this.layout.height-(this.layout.margin.top+this.layout.margin.bottom),0),this.layout.cliparea.origin.x=this.layout.margin.left,this.layout.cliparea.origin.y=this.layout.margin.top,this.initialized&&this.render(),this},k.Panel.prototype.setTitle=function(t){if("string"==typeof this.layout.title){var e=this.layout.title;this.layout.title={text:e,x:0,y:0,style:{}}}return"string"==typeof t?this.layout.title.text=t:"object"==typeof t&&null!==t&&(this.layout.title=k.Layouts.merge(t,this.layout.title)),this.layout.title.text.length?this.title.attr("display",null).attr("x",parseFloat(this.layout.title.x)).attr("y",parseFloat(this.layout.title.y)).style(this.layout.title.style).text(this.layout.title.text):this.title.attr("display","none"),this},k.Panel.prototype.initialize=function(){this.svg.container=this.parent.svg.append("g").attr("id",this.getBaseId()+".panel_container").attr("transform","translate("+(this.layout.origin.x||0)+","+(this.layout.origin.y||0)+")");var t=this.svg.container.append("clipPath").attr("id",this.getBaseId()+".clip");if(this.svg.clipRect=t.append("rect").attr("width",this.layout.width).attr("height",this.layout.height),this.svg.group=this.svg.container.append("g").attr("id",this.getBaseId()+".panel").attr("clip-path","url(#"+this.getBaseId()+".clip)"),this.curtain=k.generateCurtain.call(this),this.loader=k.generateLoader.call(this),this.dashboard=new k.Dashboard(this),this.inner_border=this.svg.group.append("rect").attr("class","lz-panel-background").on("click",function(){"clear_selections"===this.layout.background_click&&this.clearSelections()}.bind(this)),this.title=this.svg.group.append("text").attr("class","lz-panel-title"),void 0!==this.layout.title&&this.setTitle(),this.svg.x_axis=this.svg.group.append("g").attr("id",this.getBaseId()+".x_axis").attr("class","lz-x lz-axis"),this.layout.axes.x.render&&(this.svg.x_axis_label=this.svg.x_axis.append("text").attr("class","lz-x lz-axis lz-label").attr("text-anchor","middle")),this.svg.y1_axis=this.svg.group.append("g").attr("id",this.getBaseId()+".y1_axis").attr("class","lz-y lz-y1 lz-axis"),this.layout.axes.y1.render&&(this.svg.y1_axis_label=this.svg.y1_axis.append("text").attr("class","lz-y1 lz-axis lz-label").attr("text-anchor","middle")),this.svg.y2_axis=this.svg.group.append("g").attr("id",this.getBaseId()+".y2_axis").attr("class","lz-y lz-y2 lz-axis"),this.layout.axes.y2.render&&(this.svg.y2_axis_label=this.svg.y2_axis.append("text").attr("class","lz-y2 lz-axis lz-label").attr("text-anchor","middle")),this.data_layer_ids_by_z_index.forEach(function(t){this.data_layers[t].initialize()}.bind(this)),this.legend=null,this.layout.legend&&(this.legend=new k.Legend(this)),this.layout.interaction.drag_background_to_pan){var e="."+this.parent.id+"."+this.id+".interaction.drag",a=function(){this.parent.startDrag(this,"background")}.bind(this);this.svg.container.select(".lz-panel-background").on("mousedown"+e+".background",a).on("touchstart"+e+".background",a)}return this},k.Panel.prototype.resortDataLayers=function(){var e=[];this.data_layer_ids_by_z_index.forEach(function(t){e.push(this.data_layers[t].layout.z_index)}.bind(this)),this.svg.group.selectAll("g.lz-data_layer-container").data(e).sort(f.ascending),this.applyDataLayerZIndexesToDataLayerLayouts()},k.Panel.prototype.getLinkedPanelIds=function(e){var a=[];return-1===["x","y1","y2"].indexOf(e=e||null)||this.layout.interaction[e+"_linked"]&&this.parent.panel_ids_by_y_index.forEach(function(t){t!==this.id&&this.parent.panels[t].layout.interaction[e+"_linked"]&&a.push(t)}.bind(this)),a},k.Panel.prototype.moveUp=function(){return this.parent.panel_ids_by_y_index[this.layout.y_index-1]&&(this.parent.panel_ids_by_y_index[this.layout.y_index]=this.parent.panel_ids_by_y_index[this.layout.y_index-1],this.parent.panel_ids_by_y_index[this.layout.y_index-1]=this.id,this.parent.applyPanelYIndexesToPanelLayouts(),this.parent.positionPanels()),this},k.Panel.prototype.moveDown=function(){return this.parent.panel_ids_by_y_index[this.layout.y_index+1]&&(this.parent.panel_ids_by_y_index[this.layout.y_index]=this.parent.panel_ids_by_y_index[this.layout.y_index+1],this.parent.panel_ids_by_y_index[this.layout.y_index+1]=this.id,this.parent.applyPanelYIndexesToPanelLayouts(),this.parent.positionPanels()),this},k.Panel.prototype.addDataLayer=function(t){if("object"!=typeof t||"string"!=typeof t.id||!t.id.length)throw new Error("Invalid data layer layout passed to LocusZoom.Panel.prototype.addDataLayer()");if(void 0!==this.data_layers[t.id])throw new Error("Cannot create data_layer with id ["+t.id+"]; data layer with that id already exists in the panel");if("string"!=typeof t.type)throw new Error("Invalid data layer type in layout passed to LocusZoom.Panel.prototype.addDataLayer()");"object"!=typeof t.y_axis||void 0!==t.y_axis.axis&&-1!==[1,2].indexOf(t.y_axis.axis)||(t.y_axis.axis=1);var a=k.DataLayers.get(t.type,t,this);if(null!==(this.data_layers[a.id]=a).layout.z_index&&!isNaN(a.layout.z_index)&&0[SHIFT] while scrolling to zoom").hide(1e3)}.bind(this);this.zoom_listener=f.behavior.zoom(),this.svg.container.call(this.zoom_listener).on("wheel.zoom",g).on("mousewheel.zoom",g).on("DOMMouseScroll.zoom",g)}return this.data_layer_ids_by_z_index.forEach(function(t){this.data_layers[t].draw().render()}.bind(this)),this},k.Panel.prototype.renderAxis=function(i){if(-1===["x","y1","y2"].indexOf(i))throw new Error("Unable to render axis; invalid axis identifier: "+i);var t=this.layout.axes[i].render&&"function"==typeof this[i+"_scale"]&&!isNaN(this[i+"_scale"](0));if(this[i+"_axis"]&&this.svg.container.select("g.lz-axis.lz-"+i).style("display",t?null:"none"),!t)return this;var e={x:{position:"translate("+this.layout.margin.left+","+(this.layout.height-this.layout.margin.bottom)+")",orientation:"bottom",label_x:this.layout.cliparea.width/2,label_y:this.layout.axes[i].label_offset||0,label_rotate:null},y1:{position:"translate("+this.layout.margin.left+","+this.layout.margin.top+")",orientation:"left",label_x:-1*(this.layout.axes[i].label_offset||0),label_y:this.layout.cliparea.height/2,label_rotate:-90},y2:{position:"translate("+(this.layout.width-this.layout.margin.right)+","+this.layout.margin.top+")",orientation:"right",label_x:this.layout.axes[i].label_offset||0,label_y:this.layout.cliparea.height/2,label_rotate:-90}};this[i+"_ticks"]=this.generateTicks(i);var a=function(t){for(var e=0;e+a[e]&&(s=!0)}),s}(i,t.version))throw new Error("d3 dependency not met. Outdated version detected.\nRequired d3 version: 3.5.6 or higher (found: "+t.version+").");e=this,a=function(f){var a,i,s,n,o,r,l,e,h,d,u,p,t,c,y,g,_,m,b,v,x,w;try{var D="3.5.6";if("object"!=typeof f)throw new Error("d3 dependency not met. Library missing.");if(!function(t,e){if(e==t)return!0;var a=t.split("."),i=e.split("."),s=!1;return a.forEach(function(t,e){!s&&+i[e]>+a[e]&&(s=!0)}),s}(D,f.version))throw new Error("d3 dependency not met. Outdated version detected.\nRequired d3 version: 3.5.6 or higher (found: "+f.version+").");var k={version:"0.10.1",populate:function(t,a,i){if(void 0===t)throw new Error("LocusZoom.populate selector not defined");var s;return f.select(t).html(""),f.select(t).call(function(){if(void 0===this.node().id){for(var t=0;!f.select("#lz-"+t).empty();)t++;this.attr("id","#lz-"+t)}if((s=new k.Plot(this.node().id,a,i)).container=this.node(),void 0!==this.node().dataset&&void 0!==this.node().dataset.region){var e=k.parsePositionQuery(this.node().dataset.region);Object.keys(e).forEach(function(t){s.state[t]=e[t]})}s.svg=f.select("div#"+s.id).append("svg").attr("version","1.1").attr("xmlns","http://www.w3.org/2000/svg").attr("id",s.id+"_svg").attr("class","lz-locuszoom").style(s.layout.style),s.setDimensions(),s.positionPanels(),s.initialize(),"object"==typeof a&&Object.keys(a).length&&s.refresh()}),s},populateAll:function(t,a,i){var s=[];return f.selectAll(t).each(function(t,e){s[e]=k.populate(this,a,i)}),s},positionIntToString:function(t,e,a){var i={0:"",3:"K",6:"M",9:"G"};if(a=a||!1,isNaN(e)||null===e){var s=Math.log(t)/Math.LN10;e=Math.min(Math.max(s-s%3,0),9)}var n=e-Math.floor((Math.log(t)/Math.LN10).toFixed(e+3)),o=Math.min(Math.max(e,0),2),r=Math.min(Math.max(n,o),12),l=""+(t/Math.pow(10,e)).toFixed(r);return a&&void 0!==i[e]&&(l+=" "+i[e]+"b"),l},positionStringToInt:function(t){var e=t.toUpperCase();e=e.replace(/,/g,"");var a=/([KMG])[B]*$/,i=a.exec(e),s=1;return i&&(s="M"===i[1]?1e6:"G"===i[1]?1e9:1e3,e=e.replace(a,"")),e=Number(e)*s},parsePositionQuery:function(t){var e=/^(\w+):([\d,.]+[kmgbKMGB]*)([-+])([\d,.]+[kmgbKMGB]*)$/.exec(t);if(e){if("+"===e[3]){var a=k.positionStringToInt(e[2]),i=k.positionStringToInt(e[4]);return{chr:e[1],start:a-i,end:a+i}}return{chr:e[1],start:k.positionStringToInt(e[2]),end:k.positionStringToInt(e[4])}}return(e=/^(\w+):([\d,.]+[kmgbKMGB]*)$/.exec(t))?{chr:e[1],position:k.positionStringToInt(e[2])}:null},prettyTicks:function(t,e,a){(void 0===a||isNaN(parseInt(a)))&&(a=5);var i=(a=parseInt(a))/3,s=Math.abs(t[0]-t[1]),n=s/a;Math.log(s)/Math.LN10<-2&&(n=.75*Math.max(Math.abs(s))/i);var o=Math.pow(10,Math.floor(Math.log(n)/Math.LN10)),r=0;o<1&&0!==o&&(r=Math.abs(Math.round(Math.log(o)/Math.LN10)));var l=o;2*o-n<1.5*(n-l)&&5*o-n<2.75*(n-(l=2*o))&&10*o-n<1.5*(n-(l=5*o))&&(l=10*o);for(var h=[],d=parseFloat((Math.floor(t[0]/l)*l).toFixed(r));dt[1]&&h.pop(),h},createCORSPromise:function(s,n,o,r,l){return new Promise(function(t,e){var a=new XMLHttpRequest;if("withCredentials"in a?a.open(s,n,!0):"undefined"!=typeof XDomainRequest?(a=new XDomainRequest).open(s,n):a=null,a){if(a.onreadystatechange=function(){4===a.readyState&&(200===a.status||0===a.status?t(a.response):e("HTTP "+a.status+" for "+n))},l&&setTimeout(e,l),o=void 0!==o?o:"",void 0!==r)for(var i in r)a.setRequestHeader(i,r[i]);a.send(o)}})},validateState:function(t,e){e=e||{};var a=!1;if(void 0!==(t=t||{}).chr&&void 0!==t.start&&void 0!==t.end){var i,s=null;if(t.start=Math.max(parseInt(t.start),1),t.end=Math.max(parseInt(t.end),1),isNaN(t.start)&&isNaN(t.end))t.start=1,t.end=1,s=.5,i=0;else if(isNaN(t.start)||isNaN(t.end))s=t.start||t.end,i=0,t.start=isNaN(t.start)?t.end:t.start,t.end=isNaN(t.end)?t.start:t.end;else{if(s=Math.round((t.start+t.end)/2),(i=t.end-t.start)<0){var n=t.start;t.end=t.start,t.start=n,i=t.end-t.start}s<0&&(t.start=1,t.end=1,i=0)}a=!0}return!isNaN(e.min_region_scale)&&a&&ie.max_region_scale&&(t.start=Math.max(s-Math.floor(e.max_region_scale/2),1),t.end=t.start+e.max_region_scale),t},parseFields:function(e,t){if("object"!=typeof e)throw new Error("LocusZoom.parseFields invalid arguments: data is not an object");if("string"!=typeof t)throw new Error("LocusZoom.parseFields invalid arguments: html is not a string");for(var a=[],i=/\{\{(?:(#if )?([A-Za-z0-9_:|]+)|(\/if))\}\}/;0{{{{namespace[assoc]}}variant|htmlescape}}
P Value: {{{{namespace[assoc]}}log_pvalue|logtoscinotation|htmlescape}}
Ref. Allele: {{{{namespace[assoc]}}ref_allele|htmlescape}}
Make LD Reference
'}),k.Layouts.add("tooltip","covariates_model_association",((v=k.Layouts.get("tooltip","standard_association",{unnamespaced:!0})).html+='Condition on Variant
',v)),k.Layouts.add("tooltip","standard_genes",{closable:!0,show:{or:["highlighted","selected"]},hide:{and:["unhighlighted","unselected"]},html:'

{{gene_name|htmlescape}}

Gene ID: {{gene_id|htmlescape}}
Transcript ID: {{transcript_id|htmlescape}}
{{#if pLI}}
ConstraintExpected variantsObserved variantsConst. Metric
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
o/e = {{oe_syn}} ({{oe_syn_lower}} - {{oe_syn_upper}})
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
o/e = {{oe_mis}} ({{oe_mis_lower}} - {{oe_mis_upper}})
pLoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
o/e = {{oe_lof}} ({{oe_lof_lower}} - {{oe_lof_upper}})

{{/if}}More data on gnomAD'}),k.Layouts.add("tooltip","standard_intervals",{namespace:{intervals:"intervals"},closable:!1,show:{or:["highlighted","selected"]},hide:{and:["unhighlighted","unselected"]},html:"{{{{namespace[intervals]}}state_name|htmlescape}}
{{{{namespace[intervals]}}start|htmlescape}}-{{{{namespace[intervals]}}end|htmlescape}}"}),k.Layouts.add("tooltip","catalog_variant",{namespace:{assoc:"assoc",catalog:"catalog"},closable:!0,show:{or:["highlighted","selected"]},hide:{and:["unhighlighted","unselected"]},html:'{{{{namespace[catalog]}}variant|htmlescape}}
Catalog entries: {{n_catalog_matches|htmlescape}}
Top Trait: {{{{namespace[catalog]}}trait|htmlescape}}
Top P Value: {{{{namespace[catalog]}}log_pvalue|logtoscinotation}}
More: GWAS catalog / dbSNP'}),k.Layouts.add("data_layer","significance",{id:"significance",type:"orthogonal_line",orientation:"horizontal",offset:z}),k.Layouts.add("data_layer","recomb_rate",{namespace:{recomb:"recomb"},id:"recombrate",type:"line",fields:["{{namespace[recomb]}}position","{{namespace[recomb]}}recomb_rate"],z_index:1,style:{stroke:"#0000FF","stroke-width":"1.5px"},x_axis:{field:"{{namespace[recomb]}}position"},y_axis:{axis:2,field:"{{namespace[recomb]}}recomb_rate",floor:0,ceiling:100}}),k.Layouts.add("data_layer","association_pvalues",{namespace:{assoc:"assoc",ld:"ld"},id:"associationpvalues",type:"scatter",point_shape:{scale_function:"if",field:"{{namespace[ld]}}isrefvar",parameters:{field_value:1,then:"diamond",else:"circle"}},point_size:{scale_function:"if",field:"{{namespace[ld]}}isrefvar",parameters:{field_value:1,then:80,else:40}},color:[{scale_function:"if",field:"{{namespace[ld]}}isrefvar",parameters:{field_value:1,then:"#9632b8"}},{scale_function:"numerical_bin",field:"{{namespace[ld]}}state",parameters:{breaks:[0,.2,.4,.6,.8],values:["#357ebd","#46b8da","#5cb85c","#eea236","#d43f3a"]}},"#B8B8B8"],legend:[{shape:"diamond",color:"#9632b8",size:40,label:"LD Ref Var",class:"lz-data_layer-scatter"},{shape:"circle",color:"#d43f3a",size:40,label:"1.0 > r² ≥ 0.8",class:"lz-data_layer-scatter"},{shape:"circle",color:"#eea236",size:40,label:"0.8 > r² ≥ 0.6",class:"lz-data_layer-scatter"},{shape:"circle",color:"#5cb85c",size:40,label:"0.6 > r² ≥ 0.4",class:"lz-data_layer-scatter"},{shape:"circle",color:"#46b8da",size:40,label:"0.4 > r² ≥ 0.2",class:"lz-data_layer-scatter"},{shape:"circle",color:"#357ebd",size:40,label:"0.2 > r² ≥ 0.0",class:"lz-data_layer-scatter"},{shape:"circle",color:"#B8B8B8",size:40,label:"no r² data",class:"lz-data_layer-scatter"}],label:null,fields:["{{namespace[assoc]}}variant","{{namespace[assoc]}}position","{{namespace[assoc]}}log_pvalue","{{namespace[assoc]}}log_pvalue|logtoscinotation","{{namespace[assoc]}}ref_allele","{{namespace[ld]}}state","{{namespace[ld]}}isrefvar"],id_field:"{{namespace[assoc]}}variant",z_index:2,x_axis:{field:"{{namespace[assoc]}}position"},y_axis:{axis:1,field:"{{namespace[assoc]}}log_pvalue",floor:0,upper_buffer:.1,min_extent:[0,10]},behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},tooltip:k.Layouts.get("tooltip","standard_association",{unnamespaced:!0})}),k.Layouts.add("data_layer","association_pvalues_catalog",((b=k.Layouts.get("data_layer","association_pvalues",{unnamespaced:!0,id:"associationpvaluescatalog",fill_opacity:.7})).tooltip.html+='{{#if {{namespace[catalog]}}rsid}}
See hits in GWAS catalog{{/if}}',b.namespace.catalog="catalog",b.fields.push("{{namespace[catalog]}}rsid","{{namespace[catalog]}}trait","{{namespace[catalog]}}log_pvalue"),b)),k.Layouts.add("data_layer","phewas_pvalues",{namespace:{phewas:"phewas"},id:"phewaspvalues",type:"category_scatter",point_shape:"circle",point_size:70,tooltip_positioning:"vertical",id_field:"{{namespace[phewas]}}id",fields:["{{namespace[phewas]}}id","{{namespace[phewas]}}log_pvalue","{{namespace[phewas]}}trait_group","{{namespace[phewas]}}trait_label"],x_axis:{field:"{{namespace[phewas]}}x",category_field:"{{namespace[phewas]}}trait_group",lower_buffer:.025,upper_buffer:.025},y_axis:{axis:1,field:"{{namespace[phewas]}}log_pvalue",floor:0,upper_buffer:.15},color:[{field:"{{namespace[phewas]}}trait_group",scale_function:"categorical_bin",parameters:{categories:[],values:[],null_value:"#B8B8B8"}}],fill_opacity:.7,tooltip:{closable:!0,show:{or:["highlighted","selected"]},hide:{and:["unhighlighted","unselected"]},html:["Trait: {{{{namespace[phewas]}}trait_label|htmlescape}}
","Trait Category: {{{{namespace[phewas]}}trait_group|htmlescape}}
","P-value: {{{{namespace[phewas]}}log_pvalue|logtoscinotation|htmlescape}}
"].join("")},behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},label:{text:"{{{{namespace[phewas]}}trait_label|htmlescape}}",spacing:6,lines:{style:{"stroke-width":"2px",stroke:"#333333","stroke-dasharray":"2px 2px"}},filters:[{field:"{{namespace[phewas]}}log_pvalue",operator:">=",value:20}],style:{"font-size":"14px","font-weight":"bold",fill:"#333333"}}}),k.Layouts.add("data_layer","genes",{namespace:{gene:"gene",constraint:"constraint"},id:"genes",type:"genes",fields:["{{namespace[gene]}}all","{{namespace[constraint]}}all"],id_field:"gene_id",behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},tooltip:k.Layouts.get("tooltip","standard_genes",{unnamespaced:!0})}),k.Layouts.add("data_layer","genome_legend",{namespace:{genome:"genome"},id:"genome_legend",type:"genome_legend",fields:["{{namespace[genome]}}chr","{{namespace[genome]}}base_pairs"],x_axis:{floor:0,ceiling:2881033286}}),k.Layouts.add("data_layer","intervals",{namespace:{intervals:"intervals"},id:"intervals",type:"intervals",fields:["{{namespace[intervals]}}start","{{namespace[intervals]}}end","{{namespace[intervals]}}state_id","{{namespace[intervals]}}state_name"],id_field:"{{namespace[intervals]}}start",start_field:"{{namespace[intervals]}}start",end_field:"{{namespace[intervals]}}end",track_split_field:"{{namespace[intervals]}}state_id",split_tracks:!0,always_hide_legend:!1,color:{field:"{{namespace[intervals]}}state_id",scale_function:"categorical_bin",parameters:{categories:[1,2,3,4,5,6,7,8,9,10,11,12,13],values:["rgb(212,63,58)","rgb(250,120,105)","rgb(252,168,139)","rgb(240,189,66)","rgb(250,224,105)","rgb(240,238,84)","rgb(244,252,23)","rgb(23,232,252)","rgb(32,191,17)","rgb(23,166,77)","rgb(32,191,17)","rgb(162,133,166)","rgb(212,212,212)"],null_value:"#B8B8B8"}},legend:[{shape:"rect",color:"rgb(212,63,58)",width:9,label:"Active Promoter","{{namespace[intervals]}}state_id":1},{shape:"rect",color:"rgb(250,120,105)",width:9,label:"Weak Promoter","{{namespace[intervals]}}state_id":2},{shape:"rect",color:"rgb(252,168,139)",width:9,label:"Poised Promoter","{{namespace[intervals]}}state_id":3},{shape:"rect",color:"rgb(240,189,66)",width:9,label:"Strong enhancer","{{namespace[intervals]}}state_id":4},{shape:"rect",color:"rgb(250,224,105)",width:9,label:"Strong enhancer","{{namespace[intervals]}}state_id":5},{shape:"rect",color:"rgb(240,238,84)",width:9,label:"Weak enhancer","{{namespace[intervals]}}state_id":6},{shape:"rect",color:"rgb(244,252,23)",width:9,label:"Weak enhancer","{{namespace[intervals]}}state_id":7},{shape:"rect",color:"rgb(23,232,252)",width:9,label:"Insulator","{{namespace[intervals]}}state_id":8},{shape:"rect",color:"rgb(32,191,17)",width:9,label:"Transcriptional transition","{{namespace[intervals]}}state_id":9},{shape:"rect",color:"rgb(23,166,77)",width:9,label:"Transcriptional elongation","{{namespace[intervals]}}state_id":10},{shape:"rect",color:"rgb(136,240,129)",width:9,label:"Weak transcribed","{{namespace[intervals]}}state_id":11},{shape:"rect",color:"rgb(162,133,166)",width:9,label:"Polycomb-repressed","{{namespace[intervals]}}state_id":12},{shape:"rect",color:"rgb(212,212,212)",width:9,label:"Heterochromatin / low signal","{{namespace[intervals]}}state_id":13}],behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},tooltip:k.Layouts.get("tooltip","standard_intervals",{unnamespaced:!0})}),k.Layouts.add("data_layer","annotation_catalog",{namespace:{assoc:"assoc",catalog:"catalog"},id:"annotation_catalog",type:"annotation_track",id_field:"{{namespace[catalog]}}variant",x_axis:{field:"{{namespace[assoc]}}position"},color:"#0000CC",fields:["{{namespace[assoc]}}variant","{{namespace[assoc]}}chromosome","{{namespace[assoc]}}position","{{namespace[catalog]}}variant","{{namespace[catalog]}}rsid","{{namespace[catalog]}}trait","{{namespace[catalog]}}log_pvalue","{{namespace[catalog]}}pos"],filters:[["{{namespace[catalog]}}rsid","!=",null],["{{namespace[catalog]}}log_pvalue",">",z]],behaviors:{onmouseover:[{action:"set",status:"highlighted"}],onmouseout:[{action:"unset",status:"highlighted"}],onclick:[{action:"toggle",status:"selected",exclusive:!0}],onshiftclick:[{action:"toggle",status:"selected"}]},tooltip:k.Layouts.get("tooltip","catalog_variant",{unnamespaced:!0}),tooltip_positioning:"top"}),k.Layouts.add("dashboard_components","ldlz2_pop_selector",{type:"set_state",position:"right",color:"blue",button_html:"LD Population: ",show_selected:!0,button_title:"Select LD Population: ",state_field:"ld_pop",options:[{display_name:"ALL (default)",value:"ALL"},{display_name:"AFR",value:"AFR"},{display_name:"AMR",value:"AMR"},{display_name:"EAS",value:"EAS"},{display_name:"EUR",value:"EUR"},{display_name:"SAS",value:"SAS"}]}),k.Layouts.add("dashboard","standard_panel",{components:[{type:"remove_panel",position:"right",color:"red",group_position:"end"},{type:"move_panel_up",position:"right",group_position:"middle"},{type:"move_panel_down",position:"right",group_position:"start",style:{"margin-left":"0.75em"}}]}),k.Layouts.add("dashboard","standard_plot",{components:[{type:"title",title:"LocusZoom",subtitle:'v'+k.version+"",position:"left"},{type:"download",position:"right"}]}),k.Layouts.add("dashboard","covariates_model_plot",((m=k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0})).components.push({type:"covariates_model",button_html:"Model",button_title:"Show and edit covariates currently in model",position:"left"}),m)),k.Layouts.add("dashboard","region_nav_plot",((_=k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0})).components.push({type:"shift_region",step:5e5,button_html:">>",position:"right",group_position:"end"},{type:"shift_region",step:5e4,button_html:">",position:"right",group_position:"middle"},{type:"zoom_region",step:.2,position:"right",group_position:"middle"},{type:"zoom_region",step:-.2,position:"right",group_position:"middle"},{type:"shift_region",step:-5e4,button_html:"<",position:"right",group_position:"middle"},{type:"shift_region",step:-5e5,button_html:"<<",position:"right",group_position:"start"}),_)),k.Layouts.add("panel","association",{id:"association",width:800,height:225,min_width:400,min_height:200,proportional_width:1,margin:{top:35,right:50,bottom:40,left:50},inner_border:"rgb(210, 210, 210)",dashboard:(g=k.Layouts.get("dashboard","standard_panel",{unnamespaced:!0}),g.components.push({type:"toggle_legend",position:"right"}),g),axes:{x:{label:"Chromosome {{chr}} (Mb)",label_offset:32,tick_format:"region",extent:"state"},y1:{label:"-log10 p-value",label_offset:28},y2:{label:"Recombination Rate (cM/Mb)",label_offset:40}},legend:{orientation:"vertical",origin:{x:55,y:40},hidden:!0},interaction:{drag_background_to_pan:!0,drag_x_ticks_to_scale:!0,drag_y1_ticks_to_scale:!0,drag_y2_ticks_to_scale:!0,scroll_to_zoom:!0,x_linked:!0},data_layers:[k.Layouts.get("data_layer","significance",{unnamespaced:!0}),k.Layouts.get("data_layer","recomb_rate",{unnamespaced:!0}),k.Layouts.get("data_layer","association_pvalues",{unnamespaced:!0})]}),k.Layouts.add("panel","association_catalog",((y=k.Layouts.get("panel","association",{unnamespaced:!0,id:"associationcatalog",namespace:{assoc:"assoc",ld:"ld",catalog:"catalog"}})).dashboard.components.push({type:"display_options",position:"right",color:"blue",button_html:"Display options...",button_title:"Control how plot items are displayed",layer_name:"associationpvaluescatalog",default_config_display_name:"No catalog labels (default)",options:[{display_name:"Label catalog traits",display:{label:{text:"{{{{namespace[catalog]}}trait|htmlescape}}",spacing:6,lines:{style:{"stroke-width":"2px",stroke:"#333333","stroke-dasharray":"2px 2px"}},filters:[{field:"{{namespace[catalog]}}trait",operator:"!=",value:null},{field:"{{namespace[catalog]}}log_pvalue",operator:">",value:z},{field:"{{namespace[ld]}}state",operator:">",value:.4}],style:{"font-size":"10px","font-weight":"bold",fill:"#333333"}}}}]}),y.data_layers=[k.Layouts.get("data_layer","significance",{unnamespaced:!0}),k.Layouts.get("data_layer","recomb_rate",{unnamespaced:!0}),k.Layouts.get("data_layer","association_pvalues_catalog",{unnamespaced:!0})],y)),k.Layouts.add("panel","genes",{id:"genes",width:800,height:225,min_width:400,min_height:112.5,proportional_width:1,margin:{top:20,right:50,bottom:20,left:50},axes:{},interaction:{drag_background_to_pan:!0,scroll_to_zoom:!0,x_linked:!0},dashboard:(c=k.Layouts.get("dashboard","standard_panel",{unnamespaced:!0}),c.components.push({type:"resize_to_data",position:"right",button_html:"Show all genes"}),c),data_layers:[k.Layouts.get("data_layer","genes",{unnamespaced:!0})]}),k.Layouts.add("panel","phewas",{id:"phewas",width:800,height:300,min_width:800,min_height:300,proportional_width:1,margin:{top:20,right:50,bottom:120,left:50},inner_border:"rgb(210, 210, 210)",axes:{x:{ticks:{style:{"font-weight":"bold","font-size":"11px","text-anchor":"start"},transform:"rotate(50)",position:"left"}},y1:{label:"-log10 p-value",label_offset:28}},data_layers:[k.Layouts.get("data_layer","significance",{unnamespaced:!0}),k.Layouts.get("data_layer","phewas_pvalues",{unnamespaced:!0})]}),k.Layouts.add("panel","genome_legend",{id:"genome_legend",width:800,height:50,origin:{x:0,y:300},min_width:800,min_height:50,proportional_width:1,margin:{top:0,right:50,bottom:35,left:50},axes:{x:{label:"Genomic Position (number denotes chromosome)",label_offset:35,ticks:[{x:124625310,text:"1",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:370850307,text:"2",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:591461209,text:"3",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:786049562,text:"4",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:972084330,text:"5",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1148099493,text:"6",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1313226358,text:"7",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1465977701,text:"8",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1609766427,text:"9",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1748140516,text:"10",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:1883411148,text:"11",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2017840353,text:"12",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2142351240,text:"13",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2253610949,text:"14",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2358551415,text:"15",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2454994487,text:"16",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2540769469,text:"17",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2620405698,text:"18",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2689008813,text:"19",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2750086065,text:"20",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2805663772,text:"21",style:{fill:"rgb(120, 120, 186)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"},{x:2855381003,text:"22",style:{fill:"rgb(0, 0, 66)","text-anchor":"center","font-size":"13px","font-weight":"bold"},transform:"translate(0, 2)"}]}},data_layers:[k.Layouts.get("data_layer","genome_legend",{unnamespaced:!0})]}),k.Layouts.add("panel","intervals",{id:"intervals",width:1e3,height:50,min_width:500,min_height:50,margin:{top:25,right:150,bottom:5,left:50},dashboard:(t=k.Layouts.get("dashboard","standard_panel",{unnamespaced:!0}),t.components.push({type:"toggle_split_tracks",data_layer_id:"intervals",position:"right"}),t),axes:{},interaction:{drag_background_to_pan:!0,scroll_to_zoom:!0,x_linked:!0},legend:{hidden:!0,orientation:"horizontal",origin:{x:50,y:0},pad_from_bottom:5},data_layers:[k.Layouts.get("data_layer","intervals",{unnamespaced:!0})]}),k.Layouts.add("panel","annotation_catalog",{id:"annotationcatalog",width:800,height:50,min_height:50,proportional_width:1,margin:{top:25,right:50,bottom:0,left:50},inner_border:"rgb(210, 210, 210)",dashboard:k.Layouts.get("dashboard","standard_panel",{unnamespaced:!0}),interaction:{drag_background_to_pan:!0,scroll_to_zoom:!0,x_linked:!0},data_layers:[k.Layouts.get("data_layer","annotation_catalog",{unnamespaced:!0})]}),k.Layouts.add("plot","standard_association",{state:{},width:800,height:450,responsive_resize:"both",min_region_scale:2e4,max_region_scale:1e6,dashboard:k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0}),panels:[k.Layouts.get("panel","association",{unnamespaced:!0,proportional_height:.5}),k.Layouts.get("panel","genes",{unnamespaced:!0,proportional_height:.5})]}),k.Layouts.add("plot","association_catalog",{state:{},width:800,height:500,responsive_resize:"width_only",min_region_scale:2e4,max_region_scale:1e6,dashboard:k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0}),panels:[k.Layouts.get("panel","annotation_catalog",{unnamespaced:!0}),k.Layouts.get("panel","association_catalog",{unnamespaced:!0}),k.Layouts.get("panel","genes",{unnamespaced:!0})]}),k.StandardLayout=k.Layouts.get("plot","standard_association"),k.Layouts.add("plot","standard_phewas",{width:800,height:600,min_width:800,min_height:600,responsive_resize:"both",dashboard:k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0}),panels:[k.Layouts.get("panel","phewas",{unnamespaced:!0,proportional_height:.45}),k.Layouts.get("panel","genome_legend",{unnamespaced:!0,proportional_height:.1}),k.Layouts.get("panel","genes",{unnamespaced:!0,proportional_height:.45,margin:{bottom:40},axes:{x:{label:"Chromosome {{chr}} (Mb)",label_offset:32,tick_format:"region",extent:"state"}}})],mouse_guide:!1}),k.Layouts.add("plot","interval_association",{state:{},width:800,height:550,responsive_resize:"both",min_region_scale:2e4,max_region_scale:1e6,dashboard:k.Layouts.get("dashboard","standard_plot",{unnamespaced:!0}),panels:[k.Layouts.get("panel","association",{unnamespaced:!0,width:800,proportional_height:225/570}),k.Layouts.get("panel","intervals",{unnamespaced:!0,proportional_height:120/570}),k.Layouts.get("panel","genes",{unnamespaced:!0,width:800,proportional_height:225/570})]}),k.DataLayer=function(t,e){return this.initialized=!1,this.layout_idx=null,this.id=null,this.parent=e||null,this.svg={},this.parent_plot=null,void 0!==e&&e instanceof k.Panel&&(this.parent_plot=e.parent),this.layout=k.Layouts.merge(t||{},k.DataLayer.DefaultLayout),this.layout.id&&(this.id=this.layout.id),this.layout.x_axis!=={}&&"number"!=typeof this.layout.x_axis.axis&&(this.layout.x_axis.axis=1),this.layout.y_axis!=={}&&"number"!=typeof this.layout.y_axis.axis&&(this.layout.y_axis.axis=1),this._base_layout=JSON.parse(JSON.stringify(this.layout)),this.state={},this.state_id=null,this.setDefaultState(),this.data=[],this.layout.tooltip&&(this.tooltips={}),this.global_statuses={highlighted:!1,selected:!1,faded:!1,hidden:!1},this},k.DataLayer.prototype.addField=function(t,e,a){if(!t||!e)throw new Error("Must specify field name and namespace to use when adding field");var i=e+":"+t;if(a)if(i+="|","string"==typeof a)i+=a;else{if(!Array.isArray(a))throw new Error("Must provide transformations as either a string or array of strings");i+=a.join("|")}var s=this.layout.fields;return-1===s.indexOf(i)&&s.push(i),i},k.DataLayer.prototype.setDefaultState=function(){if(this.parent){this.state=this.parent.state,this.state_id=this.parent.id+"."+this.id,this.state[this.state_id]=this.state[this.state_id]||{};var e=this.state[this.state_id];k.DataLayer.Statuses.adjectives.forEach(function(t){e[t]=e[t]||[]}),e.has_tooltip=e.has_tooltip||[]}},k.DataLayer.DefaultLayout={type:"",fields:[],x_axis:{},y_axis:{}},k.DataLayer.Statuses={verbs:["highlight","select","fade","hide"],adjectives:["highlighted","selected","faded","hidden"],menu_antiverbs:["unhighlight","deselect","unfade","show"]},k.DataLayer.prototype.getBaseId=function(){return this.parent_plot.id+"."+this.parent.id+"."+this.id},k.DataLayer.prototype.getAbsoluteDataHeight=function(){return this.svg.group.node().getBoundingClientRect().height},k.DataLayer.prototype.canTransition=function(){return!!this.layout.transition&&!(this.parent_plot.panel_boundaries.dragging||this.parent_plot.interaction.panel_id)},k.DataLayer.prototype.getElementId=function(t){var e="element";if("string"==typeof t)e=t;else if("object"==typeof t){var a=this.layout.id_field||"id";if(void 0===t[a])throw new Error("Unable to generate element ID");e=t[a].toString().replace(/\W/g,"")}return(this.getBaseId()+"-"+e).replace(/([:.[\],])/g,"_")},k.DataLayer.prototype.getElementStatusNodeId=function(t){return null},k.DataLayer.prototype.getElementById=function(t){var e=f.select("#"+t.replace(/([:.[\],])/g,"\\$1"));return!e.empty()&&e.data()&&e.data().length?e.data()[0]:null},k.DataLayer.prototype.applyDataMethods=function(){var e=this.layout.match&&this.layout.match.receive,i=this.parent_plot.state.lz_match_value;return this.data.forEach(function(t,a){e&&null!=i&&(t.lz_highlight_match=t[e]===i),this.data[a].toHTML=function(){var t=this.layout.id_field||"id",e="";return this.data[a][t]&&(e=this.data[a][t].toString()),e}.bind(this),this.data[a].getDataLayer=function(){return this}.bind(this),this.data[a].deselect=function(){this.getDataLayer().unselectElement(this)}}.bind(this)),this.applyCustomDataMethods(),this},k.DataLayer.prototype.applyCustomDataMethods=function(){return this},k.DataLayer.prototype.initialize=function(){return this.svg.container=this.parent.svg.group.append("g").attr("class","lz-data_layer-container").attr("id",this.getBaseId()+".data_layer_container"),this.svg.clipRect=this.svg.container.append("clipPath").attr("id",this.getBaseId()+".clip").append("rect"),this.svg.group=this.svg.container.append("g").attr("id",this.getBaseId()+".data_layer").attr("clip-path","url(#"+this.getBaseId()+".clip)"),this},k.DataLayer.prototype.moveUp=function(){return this.parent.data_layer_ids_by_z_index[this.layout.z_index+1]&&(this.parent.data_layer_ids_by_z_index[this.layout.z_index]=this.parent.data_layer_ids_by_z_index[this.layout.z_index+1],this.parent.data_layer_ids_by_z_index[this.layout.z_index+1]=this.id,this.parent.resortDataLayers()),this},k.DataLayer.prototype.moveDown=function(){return this.parent.data_layer_ids_by_z_index[this.layout.z_index-1]&&(this.parent.data_layer_ids_by_z_index[this.layout.z_index]=this.parent.data_layer_ids_by_z_index[this.layout.z_index-1],this.parent.data_layer_ids_by_z_index[this.layout.z_index-1]=this.id,this.parent.resortDataLayers()),this},k.DataLayer.prototype.resolveScalableParameter=function(t,e){var a=null;if(Array.isArray(t))for(var i=0;null===a&&i":function(t,e){return e=":function(t,e){return e<=t},"%":function(t,e){return t%e}},Array.isArray(a)&&(2===a.length?e[a[0]]===a[1]:3===a.length&&i[a[1]]&&i[a[1]](e[a[0]],a[2]))||(n=!1)}),n&&i.push("indexes"===a?t:s)}),i},k.DataLayer.prototype.filterIndexes=function(t){return this.filter(t,"indexes")},k.DataLayer.prototype.filterElements=function(t){return this.filter(t,"elements")},k.DataLayer.Statuses.verbs.forEach(function(t,e){var a=k.DataLayer.Statuses.adjectives[e],i="un"+t;k.DataLayer.prototype[t+"Element"]=function(t,e){return e=void 0!==e&&!!e,this.setElementStatus(a,t,!0,e),this},k.DataLayer.prototype[i+"Element"]=function(t,e){return e=void 0!==e&&!!e,this.setElementStatus(a,t,!1,e),this},k.DataLayer.prototype[t+"ElementsByFilters"]=function(t,e){return e=void 0!==e&&!!e,this.setElementStatusByFilters(a,!0,t,e)},k.DataLayer.prototype[i+"ElementsByFilters"]=function(t,e){return e=void 0!==e&&!!e,this.setElementStatusByFilters(a,!1,t,e)},k.DataLayer.prototype[t+"AllElements"]=function(){return this.setAllElementStatus(a,!0),this},k.DataLayer.prototype[i+"AllElements"]=function(){return this.setAllElementStatus(a,!1),this}}),k.DataLayer.prototype.setElementStatus=function(t,e,a,i){if("has_tooltip"===t)return this;if(void 0===t||-1===k.DataLayer.Statuses.adjectives.indexOf(t))throw new Error("Invalid status passed to DataLayer.setElementStatus()");if(void 0===e)throw new Error("Invalid element passed to DataLayer.setElementStatus()");void 0===a&&(a=!0);try{var s=this.getElementId(e)}catch(t){return this}i&&this.setAllElementStatus(t,!a),f.select("#"+s).classed("lz-data_layer-"+this.layout.type+"-"+t,a);var n=this.getElementStatusNodeId(e);null!==n&&f.select("#"+n).classed("lz-data_layer-"+this.layout.type+"-statusnode-"+t,a);var o=this.state[this.state_id][t].indexOf(s),r=-1===o;a&&r&&this.state[this.state_id][t].push(s),a||r||this.state[this.state_id][t].splice(o,1),this.showOrHideTooltip(e,r),r&&this.parent.emit("layout_changed",!0);var l="selected"===t;!l||!r&&a||this.parent.emit("element_selection",{element:e,active:a},!0);var h=this.layout.match&&this.layout.match.send;return l&&h&&(r||!a)&&this.parent.emit("match_requested",{value:e[h],active:a},!0),this},k.DataLayer.prototype.setElementStatusByFilters=function(e,a,t,i){if(void 0===e||-1===k.DataLayer.Statuses.adjectives.indexOf(e))throw new Error("Invalid status passed to DataLayer.setElementStatusByFilters()");return void 0===this.state[this.state_id][e]||(a=void 0===a||!!a,i=void 0!==i&&!!i,Array.isArray(t)||(t=[]),i&&this.setAllElementStatus(e,!a),this.filterElements(t).forEach(function(t){this.setElementStatus(e,t,a)}.bind(this))),this},k.DataLayer.prototype.setAllElementStatus=function(a,t){if(void 0===a||-1===k.DataLayer.Statuses.adjectives.indexOf(a))throw new Error("Invalid status passed to DataLayer.setAllElementStatus()");if(void 0===this.state[this.state_id][a])return this;(void 0===t&&(t=!0),t)?this.data.forEach(function(t){this.setElementStatus(a,t,!0)}.bind(this)):(this.state[this.state_id][a].slice().forEach(function(t){var e=this.getElementById(t);"object"==typeof e&&null!==e&&this.setElementStatus(a,e,!1)}.bind(this)),this.state[this.state_id][a]=[]);return this.global_statuses[a]=t,this},k.DataLayer.prototype.applyBehaviors=function(a){"object"==typeof this.layout.behaviors&&Object.keys(this.layout.behaviors).forEach(function(t){var e=/(click|mouseover|mouseout)/.exec(t);e&&a.on(e[0]+"."+t,this.executeBehaviors(t,this.layout.behaviors[t]))}.bind(this))},k.DataLayer.prototype.executeBehaviors=function(t,e){var a=-1!==t.indexOf("ctrl"),i=-1!==t.indexOf("shift");return function(s){a===!!f.event.ctrlKey&&i===!!f.event.shiftKey&&e.forEach(function(t){if("object"==typeof t&&null!==t)switch(t.action){case"set":this.setElementStatus(t.status,s,!0,t.exclusive);break;case"unset":this.setElementStatus(t.status,s,!1,t.exclusive);break;case"toggle":var e=-1!==this.state[this.state_id][t.status].indexOf(this.getElementId(s)),a=t.exclusive&&!e;this.setElementStatus(t.status,s,!e,a);break;case"link":if("string"==typeof t.href){var i=k.parseFields(s,t.href);"string"==typeof t.target?window.open(i,t.target):window.location.href=i}}}.bind(this))}.bind(this)},k.DataLayer.prototype.getPageOrigin=function(){var t=this.parent.getPageOrigin();return{x:t.x+this.parent.layout.margin.left,y:t.y+this.parent.layout.margin.top}},k.DataLayer.prototype.exportData=function(t){var e,a="json";switch(t="string"==typeof(t=t||a)?t.toLowerCase():a,-1===["json","csv","tsv"].indexOf(t)&&(t=a),t){case"json":try{e=JSON.stringify(this.data)}catch(t){e=null,console.warn("Unable to export JSON data from data layer: "+this.getBaseId()),console.error(t)}break;case"tsv":case"csv":try{var i=JSON.parse(JSON.stringify(this.data));if("object"!=typeof i)e=i.toString();else if(Array.isArray(i)){var s="tsv"===t?"\t":",";e=this.layout.fields.map(function(t){return JSON.stringify(t)}).join(s)+"\n"+i.map(function(e){return this.layout.fields.map(function(t){return void 0===e[t]?JSON.stringify(null):"object"==typeof e[t]&&null!==e[t]?Array.isArray(e[t])?'"[Array('+e[t].length+')]"':'"[Object]"':JSON.stringify(e[t])}).join(s)}.bind(this)).join("\n")}else e="Object"}catch(t){e=null,console.error("Unable to export CSV data from data layer: "+this.getBaseId()+";",t)}}return e},k.DataLayer.prototype.draw=function(){return this.svg.container.attr("transform","translate("+this.parent.layout.cliparea.origin.x+","+this.parent.layout.cliparea.origin.y+")"),this.svg.clipRect.attr("width",this.parent.layout.cliparea.width).attr("height",this.parent.layout.cliparea.height),this.positionAllTooltips(),this},k.DataLayer.prototype.reMap=function(){this.destroyAllTooltips();var t=this.parent_plot.lzd.getData(this.state,this.layout.fields);return t.then(function(t){this.data=t.body,this.applyDataMethods(),this.initialized=!0}.bind(this)),t},k.DataLayers=(p={},(u={}).get=function(t,e,a){if(t){if(p[t]){if("object"!=typeof e)throw new Error("invalid layout argument for data layer ["+t+"]");return new p[t](e,a)}throw new Error("data layer ["+t+"] not found")}return null},u.set=function(t,e){if(e){if("function"!=typeof e)throw new Error("unable to set data layer ["+t+"], argument provided is not a function");p[t]=e,p[t].prototype=new k.DataLayer}else delete p[t]},u.add=function(t,e){if(p[t])throw new Error("data layer already exists with name: "+t);u.set(t,e)},u.extend=function(t,e,a){a=a||{};var i=p[t];if(!i)throw new Error("Attempted to subclass an unknown or unregistered datalayer type");if("object"!=typeof a)throw new Error("Must specify an object of properties and methods");var s=k.subclass(i,a);return p[e]=s},u.list=function(){return Object.keys(p)},u),k.DataLayers.add("annotation_track",function(t){if(this.DefaultLayout={color:"#000000",filters:[],tooltip_positioning:"middle",hit_area_width:8},t=k.Layouts.merge(t,this.DefaultLayout),!Array.isArray(t.filters))throw new Error("Annotation track must specify array of filters for selecting points to annotate");return k.DataLayer.apply(this,arguments),this.render=function(){var o=this,r=this.filter(this.layout.filters,"elements"),t=this.svg.group.select("g.lz-data_layer-"+o.layout.type+"-visible_lines");0===t.size()&&(t=this.svg.group.append("g").attr("class","lz-data_layer-"+o.layout.type+"-visible_lines"));var e=t.selectAll("rect.lz-data_layer-"+o.layout.type).data(r,function(t){return t[o.layout.id_field]});e.enter().append("rect").attr("class","lz-data_layer-"+this.layout.type).attr("id",function(t){return o.getElementId(t)});e.attr("x",function(t){return o.parent.x_scale(t[o.layout.x_axis.field])-.5}).attr("width",1).attr("height",o.parent.layout.height).attr("fill",function(t){return o.resolveScalableParameter(o.layout.color,t)}),e.exit().remove();var a=this.svg.group.select("g.lz-data_layer-"+o.layout.type+"-hit_areas");0===a.size()&&(a=this.svg.group.append("g").attr("class","lz-data_layer-"+o.layout.type+"-hit_areas"));var i=a.selectAll("rect.lz-data_layer-"+o.layout.type).data(r,function(t){return t[o.layout.id_field]});i.enter().append("rect").attr("class","lz-data_layer-"+this.layout.type).attr("id",function(t){return o.getElementId(t)});var s=function(t,e){var a=o.parent.x_scale(t[o.layout.x_axis.field]),i=a-o.layout.hit_area_width/2;if(1<=e){var s=r[e-1],n=o.parent.x_scale(s[o.layout.x_axis.field]);i=Math.max(i,(a+n)/2)}return[i,a]};i.attr("height",o.parent.layout.height).attr("opacity",0).attr("x",function(t,e){return s(t,e)[0]}).attr("width",function(t,e){var a=s(t,e);return a[1]-a[0]+o.layout.hit_area_width/2}),i.exit().remove(),this.applyBehaviors(i)},this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s,n,o=this.tooltips[t],r=this.getPageOrigin(),l=o.selector.node().getBoundingClientRect(),h=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),d=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right),u=this.parent.x_scale(o.data[this.layout.x_axis.field]),p=h/2,c=Math.max(l.width/2-u,0),y=Math.max(l.width/2+u-d,0);a=r.x+u-l.width/2-y+c,n=l.width/2-7+y-c-.5;var g=0;switch(this.layout.tooltip_positioning){case"top":i="down";break;case"bottom":g=h,i="up";break;case"middle":default:g=p,i=f.mouse(this.svg.container.node())[1]>h/2?"down":"up"}"up"===i?(e=r.y+g+1+7,s=-8):"down"===i&&(e=r.y+g-(l.height+1+7),s=l.height-1),o.selector.style("left",a+"px").style("top",e+"px"),o.arrow||(o.arrow=o.selector.append("div").style("position","absolute")),o.arrow.attr("class","lz-data_layer-tooltip-arrow_"+i).style("left",n+"px").style("top",s+"px")},this}),k.DataLayers.add("forest",function(t){return this.DefaultLayout={point_size:40,point_shape:"square",color:"#888888",fill_opacity:1,y_axis:{axis:2},id_field:"id",confidence_intervals:{start_field:"ci_start",end_field:"ci_end"},show_no_significance_line:!0},t=k.Layouts.merge(t,this.DefaultLayout),k.DataLayer.apply(this,arguments),this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s=this.tooltips[t],n=this.resolveScalableParameter(this.layout.point_size,s.data),o=this.getPageOrigin(),r=this.parent.x_scale(s.data[this.layout.x_axis.field]),l="y"+this.layout.y_axis.axis+"_scale",h=this.parent[l](s.data[this.layout.y_axis.field]),d=s.selector.node().getBoundingClientRect(),u=Math.sqrt(n/Math.PI);r<=this.parent.layout.width/2?(e=o.x+r+u+7+1,a="left",i=-8):(e=o.x+r-d.width-u-7-1,a="right",i=d.width-1);var p,c,y=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom);h-d.height/2<=0?(p=o.y+h-10.5-6,c=6):h+d.height/2>=y?(p=o.y+h+7+6-d.height,c=d.height-14-6):(p=o.y+h-d.height/2,c=d.height/2-7),s.selector.style("left",e+"px").style("top",p+"px"),s.arrow||(s.arrow=s.selector.append("div").style("position","absolute")),s.arrow.attr("class","lz-data_layer-tooltip-arrow_"+a).style("left",i+"px").style("top",c+"px")},this.render=function(){var i="x_scale",s="y"+this.layout.y_axis.axis+"_scale";if(this.layout.confidence_intervals&&-1!==this.layout.fields.indexOf(this.layout.confidence_intervals.start_field)&&-1!==this.layout.fields.indexOf(this.layout.confidence_intervals.end_field)){var t=this.svg.group.selectAll("rect.lz-data_layer-forest.lz-data_layer-forest-ci").data(this.data,function(t){return t[this.layout.id_field]}.bind(this));t.enter().append("rect").attr("class","lz-data_layer-forest lz-data_layer-forest-ci").attr("id",function(t){return this.getElementId(t)+"_ci"}.bind(this)).attr("transform","translate(0,"+(isNaN(this.parent.layout.height)?0:this.parent.layout.height)+")");var e=function(t){var e=this.parent[i](t[this.layout.confidence_intervals.start_field]),a=this.parent[s](t[this.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),isNaN(a)&&(a=-1e3),"translate("+e+","+a+")"}.bind(this),a=function(t){return this.parent[i](t[this.layout.confidence_intervals.end_field])-this.parent[i](t[this.layout.confidence_intervals.start_field])}.bind(this);this.canTransition()?t.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("transform",e).attr("width",a).attr("height",1):t.attr("transform",e).attr("width",a).attr("height",1),t.exit().remove()}var n=this.svg.group.selectAll("path.lz-data_layer-forest.lz-data_layer-forest-point").data(this.data,function(t){return t[this.layout.id_field]}.bind(this)),o=isNaN(this.parent.layout.height)?0:this.parent.layout.height;n.enter().append("path").attr("class","lz-data_layer-forest lz-data_layer-forest-point").attr("id",function(t){return this.getElementId(t)}.bind(this)).attr("transform","translate(0,"+o+")");var r=function(t){var e=this.parent[i](t[this.layout.x_axis.field]),a=this.parent[s](t[this.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),isNaN(a)&&(a=-1e3),"translate("+e+","+a+")"}.bind(this),l=function(t){return this.resolveScalableParameter(this.layout.color,t)}.bind(this),h=function(t){return this.resolveScalableParameter(this.layout.fill_opacity,t)}.bind(this),d=f.svg.symbol().size(function(t){return this.resolveScalableParameter(this.layout.point_size,t)}.bind(this)).type(function(t){return this.resolveScalableParameter(this.layout.point_shape,t)}.bind(this));this.canTransition()?n.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("transform",r).attr("fill",l).attr("fill-opacity",h).attr("d",d):n.attr("transform",r).attr("fill",l).attr("fill-opacity",h).attr("d",d),n.exit().remove(),n.on("click.event_emitter",function(t){this.parent.emit("element_clicked",t,!0)}.bind(this)),this.applyBehaviors(n)},this}),k.DataLayers.extend("forest","category_forest",{_getDataExtent:function(t,e){var a=this.layout.confidence_intervals;if(a&&-1!==this.layout.fields.indexOf(a.start_field)&&-1!==this.layout.fields.indexOf(a.end_field)){return[f.min(t,function(t){return+new k.Data.Field(a.start_field).resolve(t)}),f.max(t,function(t){return+new k.Data.Field(a.end_field).resolve(t)})]}return k.DataLayer.prototype._getDataExtent.call(this,t,e)},getTicks:function(t,e){if(-1===["x","y1","y2"].indexOf(t))throw new Error("Invalid dimension identifier"+t);if(t==="y"+this.layout.y_axis.axis){var a=this.layout.y_axis.category_field;if(!a)throw new Error("Layout for "+this.layout.id+" must specify category_field");return this.data.map(function(t,e){return{y:e+1,text:t[a]}})}return[]},applyCustomDataMethods:function(){var a=this.layout.y_axis.field;if(!a)throw new Error("Layout for "+this.layout.id+" must specify yaxis.field");return this.data=this.data.map(function(t,e){return t[a]=e+1,t}),this.layout.y_axis.floor=0,this.layout.y_axis.ceiling=this.data.length+1,this}}),k.DataLayers.add("genes",function(t){return this.DefaultLayout={stroke:"rgb(54, 54, 150)",color:"#363696",label_font_size:12,label_exon_spacing:4,exon_height:16,bounding_box_padding:6,track_vertical_spacing:10},t=k.Layouts.merge(t,this.DefaultLayout),k.DataLayer.apply(this,arguments),this.getElementStatusNodeId=function(t){return this.getElementId(t)+"-statusnode"},this.getTrackHeight=function(){return 2*this.layout.bounding_box_padding+this.layout.label_font_size+this.layout.label_exon_spacing+this.layout.exon_height+this.layout.track_vertical_spacing},this.transcript_idx=0,this.tracks=1,this.gene_track_index={1:[]},this.assignTracks=function(){return this.getLabelWidth=function(t,e){try{var a=this.svg.group.append("text").attr("x",0).attr("y",0).attr("class","lz-data_layer-genes lz-label").style("font-size",e).text(t+"→"),i=a.node().getBBox().width;return a.remove(),i}catch(t){return 0}},this.tracks=1,this.gene_track_index={1:[]},this.data.map(function(t,i){if(this.data[i].gene_id&&this.data[i].gene_id.indexOf(".")){var e=this.data[i].gene_id.split(".");this.data[i].gene_id=e[0],this.data[i].gene_version=e[1]}if(this.data[i].transcript_id=this.data[i].transcripts[this.transcript_idx].transcript_id,this.data[i].display_range={start:this.parent.x_scale(Math.max(t.start,this.state.start)),end:this.parent.x_scale(Math.min(t.end,this.state.end))},this.data[i].display_range.label_width=this.getLabelWidth(this.data[i].gene_name,this.layout.label_font_size),this.data[i].display_range.width=this.data[i].display_range.end-this.data[i].display_range.start,this.data[i].display_range.text_anchor="middle",this.data[i].display_range.widththis.state.end)this.data[i].display_range.start=this.data[i].display_range.end-this.data[i].display_range.label_width-this.layout.label_font_size,this.data[i].display_range.text_anchor="end";else{var a=(this.data[i].display_range.label_width-this.data[i].display_range.width)/2+this.layout.label_font_size;this.data[i].display_range.start-athis.parent.x_scale(this.state.end)?(this.data[i].display_range.end=this.parent.x_scale(this.state.end),this.data[i].display_range.start=this.data[i].display_range.end-this.data[i].display_range.label_width,this.data[i].display_range.text_anchor="end"):(this.data[i].display_range.start-=a,this.data[i].display_range.end+=a)}this.data[i].display_range.width=this.data[i].display_range.end-this.data[i].display_range.start}this.data[i].display_range.start-=this.layout.bounding_box_padding,this.data[i].display_range.end+=this.layout.bounding_box_padding,this.data[i].display_range.width+=2*this.layout.bounding_box_padding,this.data[i].display_domain={start:this.parent.x_scale.invert(this.data[i].display_range.start),end:this.parent.x_scale.invert(this.data[i].display_range.end)},this.data[i].display_domain.width=this.data[i].display_domain.end-this.data[i].display_domain.start,this.data[i].track=null;for(var s=1;null===this.data[i].track;){var n=!1;this.gene_track_index[s].map(function(t){if(!n){var e=Math.min(t.display_range.start,this.display_range.start);Math.max(t.display_range.end,this.display_range.end)-ethis.tracks&&(this.tracks=s,this.gene_track_index[s]=[]):(this.data[i].track=s,this.gene_track_index[s].push(this.data[i]))}(this.data[i].parent=this).data[i].transcripts.map(function(t,a){this.data[i].transcripts[a].parent=this.data[i],this.data[i].transcripts[a].exons.map(function(t,e){this.data[i].transcripts[a].exons[e].parent=this.data[i].transcripts[a]}.bind(this))}.bind(this))}.bind(this)),this},this.render=function(){var r,l,h,d,u=this;this.assignTracks();var t=this.svg.group.selectAll("g.lz-data_layer-genes").data(this.data,function(t){return t.gene_name});t.enter().append("g").attr("class","lz-data_layer-genes"),t.attr("id",function(t){return this.getElementId(t)}.bind(this)).each(function(t){var e=t.parent,a=f.select(this).selectAll("rect.lz-data_layer-genes.lz-data_layer-genes-statusnode").data([t],function(t){return e.getElementStatusNodeId(t)});a.enter().append("rect").attr("class","lz-data_layer-genes lz-data_layer-genes-statusnode"),a.attr("id",function(t){return e.getElementStatusNodeId(t)}).attr("rx",function(){return e.layout.bounding_box_padding}).attr("ry",function(){return e.layout.bounding_box_padding}),r=function(t){return t.display_range.width},l=function(){return e.getTrackHeight()-e.layout.track_vertical_spacing},h=function(t){return t.display_range.start},d=function(t){return(t.track-1)*e.getTrackHeight()},e.canTransition()?a.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",r).attr("height",l).attr("x",h).attr("y",d):a.attr("width",r).attr("height",l).attr("x",h).attr("y",d),a.exit().remove();var i=f.select(this).selectAll("rect.lz-data_layer-genes.lz-boundary").data([t],function(t){return t.gene_name+"_boundary"}).style({fill:function(t){return u.resolveScalableParameter(u.layout.color,t)},stroke:function(t){return u.resolveScalableParameter(u.layout.stroke,t)}});i.enter().append("rect").attr("class","lz-data_layer-genes lz-boundary"),r=function(t){return e.parent.x_scale(t.end)-e.parent.x_scale(t.start)},l=function(){return 1},h=function(t){return e.parent.x_scale(t.start)},d=function(t){return(t.track-1)*e.getTrackHeight()+e.layout.bounding_box_padding+e.layout.label_font_size+e.layout.label_exon_spacing+Math.max(e.layout.exon_height,3)/2},e.canTransition()?i.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",r).attr("height",l).attr("x",h).attr("y",d):i.attr("width",r).attr("height",l).attr("x",h).attr("y",d),i.exit().remove();var s=f.select(this).selectAll("text.lz-data_layer-genes.lz-label").data([t],function(t){return t.gene_name+"_label"});s.enter().append("text").attr("class","lz-data_layer-genes lz-label"),s.attr("text-anchor",function(t){return t.display_range.text_anchor}).text(function(t){return"+"===t.strand?t.gene_name+"→":"←"+t.gene_name}).style("font-size",t.parent.layout.label_font_size),h=function(t){return"middle"===t.display_range.text_anchor?t.display_range.start+t.display_range.width/2:"start"===t.display_range.text_anchor?t.display_range.start+e.layout.bounding_box_padding:"end"===t.display_range.text_anchor?t.display_range.end-e.layout.bounding_box_padding:void 0},d=function(t){return(t.track-1)*e.getTrackHeight()+e.layout.bounding_box_padding+e.layout.label_font_size},e.canTransition()?s.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("x",h).attr("y",d):s.attr("x",h).attr("y",d),s.exit().remove();var n=f.select(this).selectAll("rect.lz-data_layer-genes.lz-exon").data(t.transcripts[t.parent.transcript_idx].exons,function(t){return t.exon_id});n.enter().append("rect").attr("class","lz-data_layer-genes lz-exon"),n.style({fill:function(t){return u.resolveScalableParameter(u.layout.color,t.parent.parent)},stroke:function(t){return u.resolveScalableParameter(u.layout.stroke,t.parent.parent)}}),r=function(t){return e.parent.x_scale(t.end)-e.parent.x_scale(t.start)},l=function(){return e.layout.exon_height},h=function(t){return e.parent.x_scale(t.start)},d=function(){return(t.track-1)*e.getTrackHeight()+e.layout.bounding_box_padding+e.layout.label_font_size+e.layout.label_exon_spacing},e.canTransition()?n.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",r).attr("height",l).attr("x",h).attr("y",d):n.attr("width",r).attr("height",l).attr("x",h).attr("y",d),n.exit().remove();var o=f.select(this).selectAll("rect.lz-data_layer-genes.lz-clickarea").data([t],function(t){return t.gene_name+"_clickarea"});o.enter().append("rect").attr("class","lz-data_layer-genes lz-clickarea"),o.attr("id",function(t){return e.getElementId(t)+"_clickarea"}).attr("rx",function(){return e.layout.bounding_box_padding}).attr("ry",function(){return e.layout.bounding_box_padding}),r=function(t){return t.display_range.width},l=function(){return e.getTrackHeight()-e.layout.track_vertical_spacing},h=function(t){return t.display_range.start},d=function(t){return(t.track-1)*e.getTrackHeight()},e.canTransition()?o.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",r).attr("height",l).attr("x",h).attr("y",d):o.attr("width",r).attr("height",l).attr("x",h).attr("y",d),o.exit().remove(),o.on("click.event_emitter",function(t){t.parent.parent.emit("element_clicked",t,!0)}),e.applyBehaviors(o)}),t.exit().remove()},this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s=this.tooltips[t],n=this.getPageOrigin(),o=s.selector.node().getBoundingClientRect(),r=this.getElementStatusNodeId(s.data),l=f.select("#"+r).node().getBBox(),h=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),d=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right),u=(s.data.display_range.start+s.data.display_range.end)/2-this.layout.bounding_box_padding/2,p=Math.max(o.width/2-u,0),c=Math.max(o.width/2+u-d,0),y=n.x+u-o.width/2-c+p,g=o.width/2-3.5+c-p;o.height+1+7>h-(l.y+l.height)?(e=n.y+l.y-(o.height+1+7),a="down",i=o.height-1):(e=n.y+l.y+l.height+1+7,a="up",i=-8),s.selector.style("left",y+"px").style("top",e+"px"),s.arrow||(s.arrow=s.selector.append("div").style("position","absolute")),s.arrow.attr("class","lz-data_layer-tooltip-arrow_"+a).style("left",g+"px").style("top",i+"px")},this}),k.DataLayers.add("genome_legend",function(t){return this.DefaultLayout={chromosome_fill_colors:{light:"rgb(155, 155, 188)",dark:"rgb(95, 95, 128)"},chromosome_label_colors:{light:"rgb(120, 120, 186)",dark:"rgb(0, 0, 66)"}},t=k.Layouts.merge(t,this.DefaultLayout),k.DataLayer.apply(this,arguments),this.render=function(){var a=0;this.data.forEach(function(t,e){this.data[e].genome_start=a,this.data[e].genome_end=a+t["genome:base_pairs"],a+=t["genome:base_pairs"]}.bind(this));var t=this.svg.group.selectAll("rect.lz-data_layer-genome_legend").data(this.data,function(t){return t["genome:chr"]});t.enter().append("rect").attr("class","lz-data_layer-genome_legend");var e=this,i=this.parent;t.attr("fill",function(t){return t["genome:chr"]%2?e.layout.chromosome_fill_colors.light:e.layout.chromosome_fill_colors.dark}).attr("x",function(t){return i.x_scale(t.genome_start)}).attr("y",0).attr("width",function(t){return i.x_scale(t["genome:base_pairs"])}).attr("height",i.layout.cliparea.height),t.exit().remove();var s=/([^:]+):(\d+)(?:_.*)?/.exec(this.state.variant);if(!s)throw new Error("Genome legend cannot understand the specified variant position");var n=s[1],o=s[2];a=+this.data[n-1].genome_start+ +o;var r=this.svg.group.selectAll("rect.lz-data_layer-genome_legend-marker").data([{start:a,end:a+1}]);r.enter().append("rect").attr("class","lz-data_layer-genome_legend-marker"),r.transition().duration(500).style({fill:"rgba(255, 250, 50, 0.8)",stroke:"rgba(255, 250, 50, 0.8)","stroke-width":"3px"}).attr("x",function(t){return i.x_scale(t.start)}).attr("y",0).attr("width",function(t){return i.x_scale(t.end-t.start)}).attr("height",i.layout.cliparea.height),r.exit().remove()},this}),k.DataLayers.add("intervals",function(t){return this.DefaultLayout={start_field:"start",end_field:"end",track_split_field:"state_id",track_split_order:"DESC",track_split_legend_to_y_axis:2,split_tracks:!0,track_height:15,track_vertical_spacing:3,bounding_box_padding:2,always_hide_legend:!1,color:"#B8B8B8",fill_opacity:1},t=k.Layouts.merge(t,this.DefaultLayout),k.DataLayer.apply(this,arguments),this.getElementStatusNodeId=function(t){return this.layout.split_tracks?(this.getBaseId()+"-statusnode-"+t[this.layout.track_split_field]).replace(/[:.[\],]/g,"_"):this.getElementId(t)+"-statusnode"}.bind(this),this.getTrackHeight=function(){return this.layout.track_height+this.layout.track_vertical_spacing+2*this.layout.bounding_box_padding},this.tracks=1,this.previous_tracks=1,this.interval_track_index={1:[]},this.assignTracks=function(){if(this.previous_tracks=this.tracks,this.tracks=0,this.interval_track_index={1:[]},this.track_split_field_index={},this.layout.track_split_field&&this.layout.split_tracks){this.data.map(function(t){this.track_split_field_index[t[this.layout.track_split_field]]=null}.bind(this));var t=Object.keys(this.track_split_field_index);"DESC"===this.layout.track_split_order&&t.reverse(),t.forEach(function(t){this.track_split_field_index[t]=this.tracks+1,this.interval_track_index[this.tracks+1]=[],this.tracks++}.bind(this))}return this.data.map(function(t,e){if((this.data[e].parent=this).data[e].display_range={start:this.parent.x_scale(Math.max(t[this.layout.start_field],this.state.start)),end:this.parent.x_scale(Math.min(t[this.layout.end_field],this.state.end))},this.data[e].display_range.width=this.data[e].display_range.end-this.data[e].display_range.start,this.data[e].display_domain={start:this.parent.x_scale.invert(this.data[e].display_range.start),end:this.parent.x_scale.invert(this.data[e].display_range.end)},this.data[e].display_domain.width=this.data[e].display_domain.end-this.data[e].display_domain.start,this.layout.track_split_field&&this.layout.split_tracks){var a=this.data[e][this.layout.track_split_field];this.data[e].track=this.track_split_field_index[a],this.interval_track_index[this.data[e].track].push(e)}else{this.tracks=1,this.data[e].track=null;for(var i=1;null===this.data[e].track;){var s=!1;this.interval_track_index[i].map(function(t){if(!s){var e=Math.min(t.display_range.start,this.display_range.start);Math.max(t.display_range.end,this.display_range.end)-ethis.tracks&&(this.tracks=i,this.interval_track_index[i]=[]):(this.data[e].track=i,this.interval_track_index[i].push(this.data[e]))}}}.bind(this)),this},this.render=function(){var o,r,l,h,d,u;this.assignTracks(),this.svg.group.selectAll(".lz-data_layer-intervals-statusnode.lz-data_layer-intervals-shared").remove(),Object.keys(this.track_split_field_index).forEach(function(t){var e={};e[this.layout.track_split_field]=t;var a={display:this.layout.split_tracks?null:"none"};this.svg.group.insert("rect",":first-child").attr("id",this.getElementStatusNodeId(e)).attr("class","lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-shared").attr("rx",this.layout.bounding_box_padding).attr("ry",this.layout.bounding_box_padding).attr("width",this.parent.layout.cliparea.width).attr("height",this.getTrackHeight()-this.layout.track_vertical_spacing).attr("x",0).attr("y",(this.track_split_field_index[t]-1)*this.getTrackHeight()).style(a)}.bind(this));var t=this.svg.group.selectAll("g.lz-data_layer-intervals").data(this.data,function(t){return t[this.layout.id_field]}.bind(this));return t.enter().append("g").attr("class","lz-data_layer-intervals"),t.attr("id",function(t){return this.getElementId(t)}.bind(this)).each(function(t){var e=t.parent,a={display:e.layout.split_tracks?"none":null},i=f.select(this).selectAll("rect.lz-data_layer-intervals.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-statusnode-discrete").data([t],function(t){return e.getElementId(t)+"-statusnode"});i.enter().insert("rect",":first-child").attr("class","lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-statusnode-discrete"),i.attr("id",function(t){return e.getElementId(t)+"-statusnode"}).attr("rx",function(){return e.layout.bounding_box_padding}).attr("ry",function(){return e.layout.bounding_box_padding}).style(a),o=function(t){return t.display_range.width+2*e.layout.bounding_box_padding},r=function(){return e.getTrackHeight()-e.layout.track_vertical_spacing},l=function(t){return t.display_range.start-e.layout.bounding_box_padding},h=function(t){return(t.track-1)*e.getTrackHeight()},e.canTransition()?i.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",o).attr("height",r).attr("x",l).attr("y",h):i.attr("width",o).attr("height",r).attr("x",l).attr("y",h),i.exit().remove();var s=f.select(this).selectAll("rect.lz-data_layer-intervals.lz-interval_rect").data([t],function(t){return t[e.layout.id_field]+"_interval_rect"});s.enter().append("rect").attr("class","lz-data_layer-intervals lz-interval_rect"),r=e.layout.track_height,o=function(t){return t.display_range.width},l=function(t){return t.display_range.start},h=function(t){return(t.track-1)*e.getTrackHeight()+e.layout.bounding_box_padding},d=function(t){return e.resolveScalableParameter(e.layout.color,t)},u=function(t){return e.resolveScalableParameter(e.layout.fill_opacity,t)},e.canTransition()?s.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",o).attr("height",r).attr("x",l).attr("y",h).attr("fill",d).attr("fill-opacity",u):s.attr("width",o).attr("height",r).attr("x",l).attr("y",h).attr("fill",d).attr("fill-opacity",u),s.exit().remove();var n=f.select(this).selectAll("rect.lz-data_layer-intervals.lz-clickarea").data([t],function(t){return t.interval_name+"_clickarea"});n.enter().append("rect").attr("class","lz-data_layer-intervals lz-clickarea"),n.attr("id",function(t){return e.getElementId(t)+"_clickarea"}).attr("rx",function(){return e.layout.bounding_box_padding}).attr("ry",function(){return e.layout.bounding_box_padding}),o=function(t){return t.display_range.width},r=function(){return e.getTrackHeight()-e.layout.track_vertical_spacing},l=function(t){return t.display_range.start},h=function(t){return(t.track-1)*e.getTrackHeight()},e.canTransition()?n.transition().duration(e.layout.transition.duration||0).ease(e.layout.transition.ease||"cubic-in-out").attr("width",o).attr("height",r).attr("x",l).attr("y",h):n.attr("width",o).attr("height",r).attr("x",l).attr("y",h),n.exit().remove(),n.on("click",function(t){t.parent.parent.emit("element_clicked",t,!0)}.bind(this)),e.applyBehaviors(n)}),t.exit().remove(),this.previous_tracks!==this.tracks&&this.updateSplitTrackAxis(),this},this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s=this.tooltips[t],n=this.getPageOrigin(),o=s.selector.node().getBoundingClientRect(),r=f.select("#"+this.getElementStatusNodeId(s.data)).node().getBBox(),l=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),h=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right),d=(s.data.display_range.start+s.data.display_range.end)/2-this.layout.bounding_box_padding/2,u=Math.max(o.width/2-d,0),p=Math.max(o.width/2+d-h,0),c=n.x+d-o.width/2-p+u,y=o.width/2-3.5+p-u;o.height+1+7>l-(r.y+r.height)?(e=n.y+r.y-(o.height+1+7),a="down",i=o.height-1):(e=n.y+r.y+r.height+1+7,a="up",i=-8),s.selector.style("left",c+"px").style("top",e+"px"),s.arrow||(s.arrow=s.selector.append("div").style("position","absolute")),s.arrow.attr("class","lz-data_layer-tooltip-arrow_"+a).style("left",y+"px").style("top",i+"px")},this.updateSplitTrackAxis=function(){var i=!!this.layout.track_split_legend_to_y_axis&&"y"+this.layout.track_split_legend_to_y_axis;if(this.layout.split_tracks){var s=+this.tracks||0,t=+this.layout.track_height||0,e=2*(+this.layout.bounding_box_padding||0)+(+this.layout.track_vertical_spacing||0),a=s*t+(s-1)*e;this.parent.scaleHeightToData(a),i&&this.parent.legend&&(this.parent.legend.hide(),this.parent.layout.axes[i]={render:!0,ticks:[],range:{start:a-this.layout.track_height/2,end:this.layout.track_height/2}},this.layout.legend.forEach(function(t){var e=t[this.layout.track_split_field],a=this.track_split_field_index[e];a&&("DESC"===this.layout.track_split_order&&(a=Math.abs(a-s-1)),this.parent.layout.axes[i].ticks.push({y:a,text:t.label}))}.bind(this)),this.layout.y_axis={axis:this.layout.track_split_legend_to_y_axis,floor:1,ceiling:s},this.parent.render()),this.parent_plot.positionPanels()}else i&&this.parent.legend&&(this.layout.always_hide_legend||this.parent.legend.show(),this.parent.layout.axes[i]={render:!1},this.parent.render());return this},this.toggleSplitTracks=function(){return this.layout.split_tracks=!this.layout.split_tracks,this.parent.legend&&!this.layout.always_hide_legend&&(this.parent.layout.margin.bottom=5+(this.layout.split_tracks?0:this.parent.legend.layout.height+5)),this.render(),this.updateSplitTrackAxis(),this},this}),k.DataLayers.add("line",function(t){return this.DefaultLayout={style:{fill:"none","stroke-width":"2px"},interpolate:"linear",x_axis:{field:"x"},y_axis:{field:"y",axis:1},hitarea_width:5},t=k.Layouts.merge(t,this.DefaultLayout),this.mouse_event=null,this.line=null,this.tooltip_timeout=null,k.DataLayer.apply(this,arguments),this.getMouseDisplayAndData=function(){var t={display:{x:f.mouse(this.mouse_event)[0],y:null},data:{},slope:null},e=this.layout.x_axis.field,a=this.layout.y_axis.field,i="x_scale",s="y"+this.layout.y_axis.axis+"_scale";t.data[e]=this.parent[i].invert(t.display.x);var n=(0,f.bisector(function(t){return+t[e]}).left)(this.data,t.data[e])-1,o=this.data[n],r=this.data[n+1],l=f.interpolateNumber(+o[a],+r[a]),h=+r[e]-+o[e];return t.data[a]=l(t.data[e]%h/h),t.display.y=this.parent[s](t.data[a]),this.layout.tooltip.x_precision&&(t.data[e]=t.data[e].toPrecision(this.layout.tooltip.x_precision)),this.layout.tooltip.y_precision&&(t.data[a]=t.data[a].toPrecision(this.layout.tooltip.y_precision)),t.slope=(this.parent[s](r[a])-this.parent[s](o[a]))/(this.parent[i](r[e])-this.parent[i](o[e])),t},this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s,n,o=this.tooltips[t],r=o.selector.node().getBoundingClientRect(),l=parseFloat(this.layout.style["stroke-width"])||1,h=this.getPageOrigin(),d=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),u=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right),p=this.getMouseDisplayAndData();if(1=d?(e=h.y+p.display.y+7+6-r.height,i=r.height-14-6):(e=h.y+p.display.y-r.height/2,i=r.height/2-7);else{var c=Math.max(r.width/2-p.display.x,0),y=Math.max(r.width/2+p.display.x-u,0);a=h.x+p.display.x-r.width/2-y+c;var g=r.width-17.5;s=r.width/2-7+y-c,s=Math.min(Math.max(s,3.5),g),r.height+l+7>p.display.y?(e=h.y+p.display.y+l+7,n="up",i=0-l-7):(e=h.y+p.display.y-(r.height+l+7),n="down",i=r.height-l)}o.selector.style({left:a+"px",top:e+"px"}),o.arrow||(o.arrow=o.selector.append("div").style("position","absolute")),o.arrow.attr("class","lz-data_layer-tooltip-arrow_"+n).style({left:s+"px",top:i+"px"})},this.render=function(){var e=this,a=this.parent,i=this.layout.x_axis.field,s=this.layout.y_axis.field,n="x_scale",o="y"+this.layout.y_axis.axis+"_scale",t=this.svg.group.selectAll("path.lz-data_layer-line").data([this.data]);if(this.path=t.enter().append("path").attr("class","lz-data_layer-line"),this.layout.style.fill&&"none"!==this.layout.style.fill?this.line=f.svg.area().x(function(t){return parseFloat(a[n](t[i]))}).y0(function(t){return parseFloat(a[o](0))}).y1(function(t){return parseFloat(a[o](t[s]))}):this.line=f.svg.line().x(function(t){return parseFloat(a[n](t[i]))}).y(function(t){return parseFloat(a[o](t[s]))}).interpolate(this.layout.interpolate),this.canTransition()?t.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("d",this.line).style(this.layout.style):t.attr("d",this.line).style(this.layout.style),this.layout.tooltip){var r=parseFloat(this.layout.hitarea_width).toString()+"px",l=this.svg.group.selectAll("path.lz-data_layer-line-hitarea").data([this.data]);l.enter().append("path").attr("class","lz-data_layer-line-hitarea").style("stroke-width",r);var h=f.svg.line().x(function(t){return parseFloat(a[n](t[i]))}).y(function(t){return parseFloat(a[o](t[s]))}).interpolate(this.layout.interpolate);l.attr("d",h).on("mouseover",function(){clearTimeout(e.tooltip_timeout),e.mouse_event=this;var t=e.getMouseDisplayAndData();e.createTooltip(t.data)}).on("mousemove",function(){clearTimeout(e.tooltip_timeout),e.mouse_event=this;var t=e.getMouseDisplayAndData();e.updateTooltip(t.data),e.positionTooltip(e.getElementId())}).on("mouseout",function(){e.tooltip_timeout=setTimeout(function(){e.mouse_event=null,e.destroyTooltip(e.getElementId())},300)}),l.exit().remove()}t.exit().remove()},this.setElementStatus=function(t,e,a){return this.setAllElementStatus(t,a)},this.setElementStatusByFilters=function(t,e){return this.setAllElementStatus(t,e)},this.setAllElementStatus=function(t,e){if(void 0===t||-1===k.DataLayer.Statuses.adjectives.indexOf(t))throw new Error("Invalid status passed to DataLayer.setAllElementStatus()");if(void 0===this.state[this.state_id][t])return this;void 0===e&&(e=!0),this.global_statuses[t]=e;var a="lz-data_layer-line";return Object.keys(this.global_statuses).forEach(function(t){this.global_statuses[t]&&(a+=" lz-data_layer-line-"+t)}.bind(this)),this.path.attr("class",a),this.parent.emit("layout_changed",!0),this},this}),k.DataLayers.add("orthogonal_line",function(t){return this.DefaultLayout={style:{stroke:"#D3D3D3","stroke-width":"3px","stroke-dasharray":"10px 10px"},orientation:"horizontal",x_axis:{axis:1,decoupled:!0},y_axis:{axis:1,decoupled:!0},offset:0},t=k.Layouts.merge(t,this.DefaultLayout),-1===["horizontal","vertical"].indexOf(t.orientation)&&(t.orientation="horizontal"),this.data=[],this.line=null,k.DataLayer.apply(this,arguments),this.render=function(){var i=this.parent,s="y"+this.layout.y_axis.axis+"_scale",t="x_extent",e="y"+this.layout.y_axis.axis+"_extent";if("horizontal"===this.layout.orientation)this.data=[{x:i[t][0],y:this.layout.offset},{x:i[t][1],y:this.layout.offset}];else{if("vertical"!==this.layout.orientation)throw new Error('Unrecognized vertical line type. Must be "vertical" or "horizontal"');this.data=[{x:this.layout.offset,y:i[e][0]},{x:this.layout.offset,y:i[e][1]}]}var a=this.svg.group.selectAll("path.lz-data_layer-line").data([this.data]);this.path=a.enter().append("path").attr("class","lz-data_layer-line");var n=[i.layout.cliparea.height,0];this.line=f.svg.line().x(function(t,e){var a=parseFloat(i.x_scale(t.x));return isNaN(a)?i.x_range[e]:a}).y(function(t,e){var a=parseFloat(i[s](t.y));return isNaN(a)?n[e]:a}).interpolate("linear"),this.canTransition()?a.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("d",this.line).style(this.layout.style):a.attr("d",this.line).style(this.layout.style),a.exit().remove()},this}),k.DataLayers.add("scatter",function(t){return this.DefaultLayout={point_size:40,point_shape:"circle",tooltip_positioning:"horizontal",color:"#888888",fill_opacity:1,y_axis:{axis:1},id_field:"id"},(t=k.Layouts.merge(t,this.DefaultLayout)).label&&isNaN(t.label.spacing)&&(t.label.spacing=4),k.DataLayer.apply(this,arguments),this.positionTooltip=function(t){if("string"!=typeof t)throw new Error("Unable to position tooltip: id is not a string");if(!this.tooltips[t])throw new Error("Unable to position tooltip: id does not point to a valid tooltip");var e,a,i,s,n,o=this.tooltips[t],r=this.resolveScalableParameter(this.layout.point_size,o.data),l=Math.sqrt(r/Math.PI),h=this.getPageOrigin(),d=this.parent.x_scale(o.data[this.layout.x_axis.field]),u="y"+this.layout.y_axis.axis+"_scale",p=this.parent[u](o.data[this.layout.y_axis.field]),c=o.selector.node().getBoundingClientRect(),y=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),g=this.parent.layout.width-(this.parent.layout.margin.left+this.parent.layout.margin.right);if("vertical"===this.layout.tooltip_positioning){var _=Math.max(c.width/2-d,0),f=Math.max(c.width/2+d-g,0);a=h.x+d-c.width/2-f+_,n=c.width/2-3.5+f-_-l,c.height+1+7>y-(p+l)?(e=h.y+p-(l+c.height+1+7),i="down",s=c.height-1):(e=h.y+p+l+1+7,i="up",s=-8)}else d<=this.parent.layout.width/2?(a=h.x+d+l+7+1,i="left",n=-8):(a=h.x+d-c.width-l-7-1,i="right",n=c.width-1),y=this.parent.layout.height-(this.parent.layout.margin.top+this.parent.layout.margin.bottom),p-c.height/2<=0?(e=h.y+p-10.5-6,s=6):p+c.height/2>=y?(e=h.y+p+7+6-c.height,s=c.height-14-6):(e=h.y+p-c.height/2,s=c.height/2-7);o.selector.style("left",a+"px").style("top",e+"px"),o.arrow||(o.arrow=o.selector.append("div").style("position","absolute")),o.arrow.attr("class","lz-data_layer-tooltip-arrow_"+i).style("left",n+"px").style("top",s+"px")},this.flip_labels=function(){var n=this,o=n.resolveScalableParameter(n.layout.point_size,{}),r=n.layout.label.spacing,l=Boolean(n.layout.label.lines),h=2*r,s=n.parent.layout.width-n.parent.layout.margin.left-n.parent.layout.margin.right-2*r,d=function(t,e){var a=+t.attr("x"),i=2*r+2*Math.sqrt(o);if(l)var s=+e.attr("x2"),n=r+2*Math.sqrt(o);"start"===t.style("text-anchor")?(t.style("text-anchor","end"),t.attr("x",a-i),l&&e.attr("x2",s-n)):(t.style("text-anchor","start"),t.attr("x",a+i),l&&e.attr("x2",s+n))};n.label_texts.each(function(t,e){var a=f.select(this);if(+a.attr("x")+a.node().getBoundingClientRect().width+r>s){var i=l?f.select(n.label_lines[0][e]):null;d(a,i)}}),n.label_texts.each(function(t,e){var a=f.select(this);if("end"!==a.style("text-anchor")){a.attr("x");var i=a.node().getBoundingClientRect(),s=l?f.select(n.label_lines[0][e]):null;n.label_texts.each(function(){var t=f.select(this).node().getBoundingClientRect();i.leftt.left&&i.topt.top&&(d(a,s),+a.attr("x")-i.width-ra.left&&e.topa.top){g=!0;var i,s=t.attr("y"),n=.5*(e.toph?(i=o-+p,o=+p,r-=i):r+a.height/2>h&&(i=r-+s,r=+s,o-=i),u.attr("y",o),t.attr("y",r)}}}})}),g){if(c.layout.label.lines){var a=c.label_texts[0];c.label_lines.attr("y2",function(t,e){return f.select(a[e]).attr("y")})}this.seperate_iterations<150&&setTimeout(function(){this.separate_labels()}.bind(this),1)}}},this.render=function(){var s=this,i="x_scale",n="y"+this.layout.y_axis.axis+"_scale";if(this.layout.label){var t=this.data.filter(function(a){if(s.layout.label.filters){var i=!0;return s.layout.label.filters.forEach(function(t){var e=new k.Data.Field(t.field).resolve(a);if(-1===["!=","="].indexOf(t.operator)&&isNaN(e))i=!1;else switch(t.operator){case"<":e":e>t.value||(i=!1);break;case">=":e>=t.value||(i=!1);break;case"=":e!==t.value&&(i=!1);break;case"!=":e==t.value&&(i=!1);break;default:i=!1}}),i}return!0}),e=this;this.label_groups=this.svg.group.selectAll("g.lz-data_layer-"+this.layout.type+"-label").data(t,function(t){return t[e.layout.id_field]+"_label"}),this.label_groups.enter().append("g").attr("class","lz-data_layer-"+this.layout.type+"-label"),this.label_texts&&this.label_texts.remove(),this.label_texts=this.label_groups.append("text").attr("class","lz-data_layer-"+this.layout.type+"-label"),this.label_texts.text(function(t){return k.parseFields(t,s.layout.label.text||"")}).style(s.layout.label.style||{}).attr({x:function(t){var e=s.parent[i](t[s.layout.x_axis.field])+Math.sqrt(s.resolveScalableParameter(s.layout.point_size,t))+s.layout.label.spacing;return isNaN(e)&&(e=-1e3),e},y:function(t){var e=s.parent[n](t[s.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),e},"text-anchor":function(){return"start"}}),s.layout.label.lines&&(this.label_lines&&this.label_lines.remove(),this.label_lines=this.label_groups.append("line").attr("class","lz-data_layer-"+this.layout.type+"-label"),this.label_lines.style(s.layout.label.lines.style||{}).attr({x1:function(t){var e=s.parent[i](t[s.layout.x_axis.field]);return isNaN(e)&&(e=-1e3),e},y1:function(t){var e=s.parent[n](t[s.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),e},x2:function(t){var e=s.parent[i](t[s.layout.x_axis.field])+Math.sqrt(s.resolveScalableParameter(s.layout.point_size,t))+s.layout.label.spacing/2;return isNaN(e)&&(e=-1e3),e},y2:function(t){var e=s.parent[n](t[s.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),e}})),this.label_groups.exit().remove()}else this.label_groups&&this.label_groups.remove(),this.label_lines&&this.label_lines.remove();var a=this.svg.group.selectAll("path.lz-data_layer-"+this.layout.type).data(this.data,function(t){return t[this.layout.id_field]}.bind(this)),o=isNaN(this.parent.layout.height)?0:this.parent.layout.height;a.enter().append("path").attr("class","lz-data_layer-"+this.layout.type).attr("id",function(t){return this.getElementId(t)}.bind(this)).attr("transform","translate(0,"+o+")");var r=function(t){var e=this.parent[i](t[this.layout.x_axis.field]),a=this.parent[n](t[this.layout.y_axis.field]);return isNaN(e)&&(e=-1e3),isNaN(a)&&(a=-1e3),"translate("+e+","+a+")"}.bind(this),l=function(t){return this.resolveScalableParameter(this.layout.color,t)}.bind(this),h=function(t){return this.resolveScalableParameter(this.layout.fill_opacity,t)}.bind(this),d=f.svg.symbol().size(function(t){return this.resolveScalableParameter(this.layout.point_size,t)}.bind(this)).type(function(t){return this.resolveScalableParameter(this.layout.point_shape,t)}.bind(this));this.canTransition()?a.transition().duration(this.layout.transition.duration||0).ease(this.layout.transition.ease||"cubic-in-out").attr("transform",r).attr("fill",l).attr("fill-opacity",h).attr("d",d):a.attr("transform",r).attr("fill",l).attr("fill-opacity",h).attr("d",d),a.exit().remove(),a.on("click.event_emitter",function(t){this.parent.emit("element_clicked",t,!0)}.bind(this)),this.applyBehaviors(a),this.layout.label&&(this.flip_labels(),this.seperate_iterations=0,this.separate_labels(),this.label_texts.on("click.event_emitter",function(t){this.parent.emit("element_clicked",t,!0)}.bind(this)),this.applyBehaviors(this.label_texts))},this.makeLDReference=function(t){var e=null;if(void 0===t)throw new Error("makeLDReference requires one argument of any type");e="object"==typeof t?this.layout.id_field&&void 0!==t[this.layout.id_field]?t[this.layout.id_field].toString():void 0!==t.id?t.id.toString():t.toString():t.toString(),this.parent_plot.applyState({ldrefvar:e})},this}),k.DataLayers.extend("scatter","category_scatter",{_prepareData:function(){var a=this.layout.x_axis.field||"x",o=this.layout.x_axis.category_field;if(!o)throw new Error("Layout for "+this.layout.id+" must specify category_field");var t=this.data.sort(function(t,e){var a=t[o],i=e[o],s="string"==typeof a?a.toLowerCase():a,n="string"==typeof i?i.toLowerCase():i;return s===n?0:s&`]/g,function(t){switch(t){case"'":return"'";case'"':return""";case"<":return"<";case">":return">";case"&":return"&";case"`":return"`"}}):""}),k.ScaleFunctions=(n={},(s={}).get=function(t,e,a){if(t){if(n[t])return void 0===e&&void 0===a?n[t]:n[t](e,a);throw new Error("scale function ["+t+"] not found")}return null},s.set=function(t,e){e?n[t]=e:delete n[t]},s.add=function(t,e){if(n[t])throw new Error("scale function already exists with name: "+t);s.set(t,e)},s.list=function(){return Object.keys(n)},s),k.ScaleFunctions.add("if",function(t,e){return void 0===e||t.field_value!==e?void 0!==t.else?t.else:null:t.then}),k.ScaleFunctions.add("numerical_bin",function(t,a){var e=t.breaks||[],i=t.values||[];if(null==a||isNaN(+a))return t.null_value?t.null_value:null;var s=e.reduce(function(t,e){return+a=t.breaks[t.breaks.length-1])return e[i.length-1];var n=null;if(i.forEach(function(t,e){e&&i[e-1]<=+a&&i[e]>=+a&&(n=e)}),null===n)return s;var o=(+a-i[n-1])/(i[n]-i[n-1]);return isFinite(o)?f.interpolate(e[n-1],e[n])(o):s}),k.Dashboard=function(t){if(!(t instanceof k.Plot||t instanceof k.Panel))throw new Error("Unable to create dashboard, parent must be a locuszoom plot or panel");return this.parent=t,this.id=this.parent.getBaseId()+".dashboard",this.type=this.parent instanceof k.Plot?"plot":"panel",this.parent_plot="plot"===this.type?this.parent:this.parent.parent,this.selector=null,this.components=[],this.hide_timeout=null,this.persist=!1,this.initialize()},k.Dashboard.prototype.initialize=function(){return Array.isArray(this.parent.layout.dashboard.components)&&this.parent.layout.dashboard.components.forEach(function(t){try{var e=k.Dashboard.Components.get(t.type,t,this);this.components.push(e)}catch(t){console.warn(t)}}.bind(this)),"panel"===this.type&&(f.select(this.parent.parent.svg.node().parentNode).on("mouseover."+this.id,function(){clearTimeout(this.hide_timeout),this.selector&&"hidden"!==this.selector.style("visibility")||this.show()}.bind(this)),f.select(this.parent.parent.svg.node().parentNode).on("mouseout."+this.id,function(){clearTimeout(this.hide_timeout),this.hide_timeout=setTimeout(function(){this.hide()}.bind(this),300)}.bind(this))),this},k.Dashboard.prototype.shouldPersist=function(){if(this.persist)return!0;var e=!1;return this.components.forEach(function(t){e=e||t.shouldPersist()}),!!(e=e||this.parent_plot.panel_boundaries.dragging||this.parent_plot.interaction.dragging)},k.Dashboard.prototype.show=function(){if(!this.selector){switch(this.type){case"plot":this.selector=f.select(this.parent.svg.node().parentNode).insert("div",":first-child");break;case"panel":this.selector=f.select(this.parent.parent.svg.node().parentNode).insert("div",".lz-data_layer-tooltip, .lz-dashboard-menu, .lz-curtain").classed("lz-panel-dashboard",!0)}this.selector.classed("lz-dashboard",!0).classed("lz-"+this.type+"-dashboard",!0).attr("id",this.id)}return this.components.forEach(function(t){t.show()}),this.selector.style({visibility:"visible"}),this.update()},k.Dashboard.prototype.update=function(){return this.selector?(this.components.forEach(function(t){t.update()}),this.position()):this},k.Dashboard.prototype.position=function(){if(!this.selector)return this;if("panel"===this.type){var t=this.parent.getPageOrigin(),e=(t.y+3.5).toString()+"px",a=t.x.toString()+"px",i=(this.parent.layout.width-4).toString()+"px";this.selector.style({position:"absolute",top:e,left:a,width:i})}return this.components.forEach(function(t){t.position()}),this},k.Dashboard.prototype.hide=function(){return!this.selector||this.shouldPersist()||(this.components.forEach(function(t){t.hide()}),this.selector.style({visibility:"hidden"})),this},k.Dashboard.prototype.destroy=function(t){return void 0===t&&(t=!1),this.selector&&(this.shouldPersist()&&!t||(this.components.forEach(function(t){t.destroy(!0)}),this.components=[],this.selector.remove(),this.selector=null)),this},k.Dashboard.Component=function(t,e){return this.layout=t||{},this.layout.color||(this.layout.color="gray"),this.parent=e||null,this.parent_panel=null,this.parent_plot=null,this.parent_svg=null,this.parent instanceof k.Dashboard&&("panel"===this.parent.type?(this.parent_panel=this.parent.parent,this.parent_plot=this.parent.parent.parent,this.parent_svg=this.parent_panel):(this.parent_plot=this.parent.parent,this.parent_svg=this.parent_plot)),this.selector=null,this.button=null,this.persist=!1,this.layout.position||(this.layout.position="left"),this},k.Dashboard.Component.prototype.show=function(){if(this.parent&&this.parent.selector){if(!this.selector){var t=-1!==["start","middle","end"].indexOf(this.layout.group_position)?" lz-dashboard-group-"+this.layout.group_position:"";this.selector=this.parent.selector.append("div").attr("class","lz-dashboard-"+this.layout.position+t),this.layout.style&&this.selector.style(this.layout.style),"function"==typeof this.initialize&&this.initialize()}return this.button&&"highlighted"===this.button.status&&this.button.menu.show(),this.selector.style({visibility:"visible"}),this.update(),this.position()}},k.Dashboard.Component.prototype.update=function(){},k.Dashboard.Component.prototype.position=function(){return this.button&&this.button.menu.position(),this},k.Dashboard.Component.prototype.shouldPersist=function(){return!!this.persist||!(!this.button||!this.button.persist)},k.Dashboard.Component.prototype.hide=function(){return!this.selector||this.shouldPersist()||(this.button&&this.button.menu.hide(),this.selector.style({visibility:"hidden"})),this},k.Dashboard.Component.prototype.destroy=function(t){return void 0===t&&(t=!1),this.selector&&(this.shouldPersist()&&!t||(this.button&&this.button.menu&&this.button.menu.destroy(),this.selector.remove(),this.selector=null,this.button=null)),this},k.Dashboard.Components=(i={},(a={}).get=function(t,e,a){if(t){if(i[t]){if("object"!=typeof e)throw new Error("invalid layout argument for dashboard component ["+t+"]");return new i[t](e,a)}throw new Error("dashboard component ["+t+"] not found")}return null},a.set=function(t,e){if(e){if("function"!=typeof e)throw new Error("unable to set dashboard component ["+t+"], argument provided is not a function");i[t]=e,i[t].prototype=new k.Dashboard.Component}else delete i[t]},a.add=function(t,e){if(i[t])throw new Error("dashboard component already exists with name: "+t);a.set(t,e)},a.list=function(){return Object.keys(i)},a),k.Dashboard.Component.Button=function(t){if(!(t instanceof k.Dashboard.Component))throw new Error("Unable to create dashboard component button, invalid parent");this.parent=t,this.parent_panel=this.parent.parent_panel,this.parent_plot=this.parent.parent_plot,this.parent_svg=this.parent.parent_svg,this.parent_dashboard=this.parent.parent,this.selector=null,this.tag="a",this.setTag=function(t){return void 0!==t&&(this.tag=t.toString()),this},this.html="",this.setHtml=function(t){return void 0!==t&&(this.html=t.toString()),this},this.setText=this.setHtml,this.title="",this.setTitle=function(t){return void 0!==t&&(this.title=t.toString()),this},this.color="gray",this.setColor=function(t){return void 0!==t&&(-1!==["gray","red","orange","yellow","green","blue","purple"].indexOf(t)?this.color=t:this.color="gray"),this},this.style={},this.setStyle=function(t){return void 0!==t&&(this.style=t),this},this.getClass=function(){var t=-1!==["start","middle","end"].indexOf(this.parent.layout.group_position)?" lz-dashboard-button-group-"+this.parent.layout.group_position:"";return"lz-dashboard-button lz-dashboard-button-"+this.color+(this.status?"-"+this.status:"")+t},this.persist=!1,this.permanent=!1,this.setPermanent=function(t){return t=void 0===t||Boolean(t),this.permanent=t,this.permanent&&(this.persist=!0),this},this.shouldPersist=function(){return this.permanent||this.persist},this.status="",this.setStatus=function(t){return void 0!==t&&-1!==["","highlighted","disabled"].indexOf(t)&&(this.status=t),this.update()},this.highlight=function(t){return(t=void 0===t||Boolean(t))?this.setStatus("highlighted"):"highlighted"===this.status?this.setStatus(""):this},this.disable=function(t){return(t=void 0===t||Boolean(t))?this.setStatus("disabled"):"disabled"===this.status?this.setStatus(""):this},this.onmouseover=function(){},this.setOnMouseover=function(t){return this.onmouseover="function"==typeof t?t:function(){},this},this.onmouseout=function(){},this.setOnMouseout=function(t){return this.onmouseout="function"==typeof t?t:function(){},this},this.onclick=function(){},this.setOnclick=function(t){return this.onclick="function"==typeof t?t:function(){},this},this.show=function(){if(this.parent)return this.selector||(this.selector=this.parent.selector.append(this.tag).attr("class",this.getClass())),this.update()},this.preUpdate=function(){return this},this.update=function(){return this.selector&&(this.preUpdate(),this.selector.attr("class",this.getClass()).attr("title",this.title).style(this.style).on("mouseover","disabled"===this.status?null:this.onmouseover).on("mouseout","disabled"===this.status?null:this.onmouseout).on("click","disabled"===this.status?null:this.onclick).html(this.html),this.menu.update(),this.postUpdate()),this},this.postUpdate=function(){return this},this.hide=function(){return this.selector&&!this.shouldPersist()&&(this.selector.remove(),this.selector=null),this},this.menu={outer_selector:null,inner_selector:null,scroll_position:0,hidden:!0,show:function(){return this.menu.outer_selector||(this.menu.outer_selector=f.select(this.parent_plot.svg.node().parentNode).append("div").attr("class","lz-dashboard-menu lz-dashboard-menu-"+this.color).attr("id",this.parent_svg.getBaseId()+".dashboard.menu"),this.menu.inner_selector=this.menu.outer_selector.append("div").attr("class","lz-dashboard-menu-content"),this.menu.inner_selector.on("scroll",function(){this.menu.scroll_position=this.menu.inner_selector.node().scrollTop}.bind(this))),this.menu.outer_selector.style({visibility:"visible"}),this.menu.hidden=!1,this.menu.update()}.bind(this),update:function(){return this.menu.outer_selector?(this.menu.populate(),this.menu.inner_selector&&(this.menu.inner_selector.node().scrollTop=this.menu.scroll_position),this.menu.position()):this.menu}.bind(this),position:function(){if(!this.menu.outer_selector)return this.menu;this.menu.outer_selector.style({height:null});var t=this.parent_svg.getPageOrigin(),e=document.documentElement.scrollTop||document.body.scrollTop,a=this.parent_plot.getContainerOffset(),i=this.parent_dashboard.selector.node().getBoundingClientRect(),s=this.selector.node().getBoundingClientRect(),n=this.menu.outer_selector.node().getBoundingClientRect(),o=this.menu.inner_selector.node().scrollHeight,r=0,l=0;"panel"===this.parent_dashboard.type?(r=t.y+i.height+6,l=Math.max(t.x+this.parent_svg.layout.width-n.width-3,t.x+3)):(r=s.bottom+e+3-a.top,l=Math.max(s.left+s.width-n.width-a.left,t.x+3));var h=Math.max(this.parent_svg.layout.width-6-20,20),d=h,u=h-12,p=Math.max(this.parent_svg.layout.height-30-14,14),c=Math.min(o,p),y=p;return this.menu.outer_selector.style({top:r.toString()+"px",left:l.toString()+"px","max-width":d.toString()+"px","max-height":y.toString()+"px",height:c.toString()+"px"}),this.menu.inner_selector.style({"max-width":u.toString()+"px"}),this.menu.inner_selector.node().scrollTop=this.menu.scroll_position,this.menu}.bind(this),hide:function(){return this.menu.outer_selector&&(this.menu.outer_selector.style({visibility:"hidden"}),this.menu.hidden=!0),this.menu}.bind(this),destroy:function(){return this.menu.outer_selector&&(this.menu.inner_selector.remove(),this.menu.outer_selector.remove(),this.menu.inner_selector=null,this.menu.outer_selector=null),this.menu}.bind(this),populate:function(){}.bind(this),setPopulate:function(t){return"function"==typeof t?(this.menu.populate=t,this.setOnclick(function(){this.menu.hidden?(this.menu.show(),this.highlight().update(),this.persist=!0):(this.menu.hide(),this.highlight(!1).update(),this.permanent||(this.persist=!1))}.bind(this))):this.setOnclick(),this}.bind(this)}},k.Dashboard.Components.add("title",function(e){k.Dashboard.Component.apply(this,arguments),this.show=function(){return this.div_selector||(this.div_selector=this.parent.selector.append("div").attr("class","lz-dashboard-title lz-dashboard-"+this.layout.position),this.title_selector=this.div_selector.append("h3")),this.update()},this.update=function(){var t=e.title.toString();return this.layout.subtitle&&(t+=" "+this.layout.subtitle+""),this.title_selector.html(t),this}}),k.Dashboard.Components.add("dimensions",function(a){k.Dashboard.Component.apply(this,arguments),this.update=function(){var t=-1===this.parent_plot.layout.width.toString().indexOf(".")?this.parent_plot.layout.width:this.parent_plot.layout.width.toFixed(2),e=-1===this.parent_plot.layout.height.toString().indexOf(".")?this.parent_plot.layout.height:this.parent_plot.layout.height.toFixed(2);return this.selector.html(t+"px × "+e+"px"),a.class&&this.selector.attr("class",a.class),a.style&&this.selector.style(a.style),this}}),k.Dashboard.Components.add("region_scale",function(t){k.Dashboard.Component.apply(this,arguments),this.update=function(){return isNaN(this.parent_plot.state.start)||isNaN(this.parent_plot.state.end)||null===this.parent_plot.state.start||null===this.parent_plot.state.end?this.selector.style("display","none"):(this.selector.style("display",null),this.selector.html(k.positionIntToString(this.parent_plot.state.end-this.parent_plot.state.start,null,!0))),t.class&&this.selector.attr("class",t.class),t.style&&this.selector.style(t.style),this}}),k.Dashboard.Components.add("download",function(a){for(var t in k.Dashboard.Component.apply(this,arguments),this.update=function(){return this.button||(this.button=new k.Dashboard.Component.Button(this).setColor(a.color).setHtml(a.button_html||"Download Image").setTitle(a.button_title||"Download image of the current plot as locuszoom.svg").setOnMouseover(function(){this.button.selector.classed("lz-dashboard-button-gray-disabled",!0).html("Preparing Image"),this.generateBase64SVG().then(function(t){var e=this.button.selector.attr("href");e&&URL.revokeObjectURL(e),this.button.selector.attr("href",t).classed("lz-dashboard-button-gray-disabled",!1).classed("lz-dashboard-button-gray-highlighted",!0).html(a.button_html||"Download Image")}.bind(this))}.bind(this)).setOnMouseout(function(){this.button.selector.classed("lz-dashboard-button-gray-highlighted",!1)}.bind(this)),this.button.show(),this.button.selector.attr("href-lang","image/svg+xml").attr("download",a.filename||"locuszoom.svg")),this},this.css_string="",Object.keys(document.styleSheets))if(null!==document.styleSheets[t].href&&-1!==document.styleSheets[t].href.indexOf("locuszoom.css")){k.createCORSPromise("GET",document.styleSheets[t].href).then(function(t){this.css_string=t.replace(/[\r\n]/g," ").replace(/\s+/g," "),this.css_string.indexOf("/* ! LocusZoom HTML Styles */")&&(this.css_string=this.css_string.substring(0,this.css_string.indexOf("/* ! LocusZoom HTML Styles */")))}.bind(this));break}this.generateBase64SVG=function(){return new Promise(function(t,e){var a=this.parent.selector.append("div").style("display","none").html(this.parent_plot.svg.node().outerHTML);a.selectAll("g.lz-curtain").remove(),a.selectAll("g.lz-mouse_guide").remove(),a.selectAll("g.tick text").each(function(){var t=10*+f.select(this).attr("dy").substring(-2).slice(0,-2);f.select(this).attr("dy",t)});var i=f.select(a.select("svg").node().parentNode).html(),s='",n=i.indexOf(">")+1;i=i.slice(0,n)+s+i.slice(n),a.remove();var o=new Blob([i],{type:"image/svg+xml"});t(URL.createObjectURL(o))}.bind(this))}}),k.Dashboard.Components.add("remove_panel",function(e){k.Dashboard.Component.apply(this,arguments),this.update=function(){return this.button||(this.button=new k.Dashboard.Component.Button(this).setColor(e.color).setHtml("×").setTitle("Remove panel").setOnclick(function(){if(!e.suppress_confirm&&!confirm("Are you sure you want to remove this panel? This cannot be undone!"))return!1;var t=this.parent_panel;return t.dashboard.hide(!0),f.select(t.parent.svg.node().parentNode).on("mouseover."+t.getBaseId()+".dashboard",null),f.select(t.parent.svg.node().parentNode).on("mouseout."+t.getBaseId()+".dashboard",null),t.parent.removePanel(t.id)}.bind(this)),this.button.show()),this}}),k.Dashboard.Components.add("move_panel_up",function(e){k.Dashboard.Component.apply(this,arguments),this.update=function(){if(this.button){var t=0===this.parent_panel.layout.y_index;return this.button.disable(t),this}return this.button=new k.Dashboard.Component.Button(this).setColor(e.color).setHtml("▴").setTitle("Move panel up").setOnclick(function(){this.parent_panel.moveUp(),this.update()}.bind(this)),this.button.show(),this.update()}}),k.Dashboard.Components.add("move_panel_down",function(e){k.Dashboard.Component.apply(this,arguments),this.update=function(){if(this.button){var t=this.parent_panel.layout.y_index===this.parent_plot.panel_ids_by_y_index.length-1;return this.button.disable(t),this}return this.button=new k.Dashboard.Component.Button(this).setColor(e.color).setHtml("▾").setTitle("Move panel down").setOnclick(function(){this.parent_panel.moveDown(),this.update()}.bind(this)),this.button.show(),this.update()}}),k.Dashboard.Components.add("shift_region",function(t){if(k.Dashboard.Component.apply(this,arguments),isNaN(this.parent_plot.state.start)||isNaN(this.parent_plot.state.end))return this.update=function(){},void console.warn("Unable to add shift_region dashboard component: plot state does not have region bounds");(isNaN(t.step)||0===t.step)&&(t.step=5e4),"string"!=typeof t.button_html&&(t.button_html=0":"<"),"string"!=typeof t.button_title&&(t.button_title="Shift region by "+(0=this.parent_plot.layout.max_region_scale&&(t=!1),i.step<0&&!isNaN(this.parent_plot.layout.min_region_scale)&&e<=this.parent_plot.layout.min_region_scale&&(t=!1),this.button.disable(!t),this}return this.button=new k.Dashboard.Component.Button(this).setColor(i.color).setHtml(i.button_html).setTitle(i.button_title).setOnclick(function(){var t=this.parent_plot.state.end-this.parent_plot.state.start,e=t*(1+i.step);isNaN(this.parent_plot.layout.max_region_scale)||(e=Math.min(e,this.parent_plot.layout.max_region_scale)),isNaN(this.parent_plot.layout.min_region_scale)||(e=Math.max(e,this.parent_plot.layout.min_region_scale));var a=Math.floor((e-t)/2);this.parent_plot.applyState({start:Math.max(this.parent_plot.state.start-a,1),end:this.parent_plot.state.end+a})}.bind(this)),this.button.show(),this}}),k.Dashboard.Components.add("menu",function(t){k.Dashboard.Component.apply(this,arguments),this.update=function(){return this.button||(this.button=new k.Dashboard.Component.Button(this).setColor(t.color).setHtml(t.button_html).setTitle(t.button_title),this.button.menu.setPopulate(function(){this.button.menu.inner_selector.html(t.menu_html)}.bind(this)),this.button.show()),this}}),k.Dashboard.Components.add("covariates_model",function(t){k.Dashboard.Component.apply(this,arguments),this.initialize=function(){this.parent_plot.state.model=this.parent_plot.state.model||{},this.parent_plot.state.model.covariates=this.parent_plot.state.model.covariates||[],this.parent_plot.CovariatesModel={button:this,add:function(t){var e=JSON.parse(JSON.stringify(t));"object"==typeof t&&"string"!=typeof e.html&&(e.html="function"==typeof t.toHTML?t.toHTML():t.toString());for(var a=0;athis.parent.layout.width&&(g+=_,y=c,e.attr("transform","translate("+y+","+g+")")),y+=u.width+3*c}this.elements.push(e)}.bind(this))}.bind(this));var t=this.elements_group.node().getBoundingClientRect();return this.layout.width=t.width+2*this.layout.padding,this.layout.height=t.height+2*this.layout.padding,this.background_rect.attr("width",this.layout.width).attr("height",this.layout.height),this.selector.style({visibility:this.layout.hidden?"hidden":"visible"}),this.position()},k.Legend.prototype.position=function(){if(!this.selector)return this;var t=this.selector.node().getBoundingClientRect();isNaN(+this.layout.pad_from_bottom)||(this.layout.origin.y=this.parent.layout.height-t.height-+this.layout.pad_from_bottom),isNaN(+this.layout.pad_from_right)||(this.layout.origin.x=this.parent.layout.width-t.width-+this.layout.pad_from_right),this.selector.attr("transform","translate("+this.layout.origin.x+","+this.layout.origin.y+")")},k.Legend.prototype.hide=function(){this.layout.hidden=!0,this.render()},k.Legend.prototype.show=function(){this.layout.hidden=!1,this.render()},k.Data=k.Data||{},k.DataSources=function(){this.sources={}},k.DataSources.prototype.addSource=function(t,e){return console.warn("Warning: .addSource() is deprecated. Use .add() instead"),this.add(t,e)},k.DataSources.prototype.add=function(t,e){return t.match(/[^A-Za-z0-9_]/)&&console.warn("Deprecation warning: source name '"+t+"' should contain only alphanumeric characters or underscores. Use of other characters may break layouts, and will be disallowed in the future."),this.set(t,e)},k.DataSources.prototype.set=function(t,e){if(Array.isArray(e)){var a=k.KnownDataSources.create.apply(null,e);a.source_id=t,this.sources[t]=a}else null!==e?(e.source_id=t,this.sources[t]=e):delete this.sources[t];return this},k.DataSources.prototype.getSource=function(t){return console.warn("Warning: .getSource() is deprecated. Use .get() instead"),this.get(t)},k.DataSources.prototype.get=function(t){return this.sources[t]},k.DataSources.prototype.removeSource=function(t){return console.warn("Warning: .removeSource() is deprecated. Use .remove() instead"),this.remove(t)},k.DataSources.prototype.remove=function(t){return this.set(t,null)},k.DataSources.prototype.fromJSON=function(e){"string"==typeof e&&(e=JSON.parse(e));var a=this;return Object.keys(e).forEach(function(t){a.set(t,e[t])}),a},k.DataSources.prototype.keys=function(){return Object.keys(this.sources)},k.DataSources.prototype.toJSON=function(){return this.sources},k.Data.Field=function(t){var e=/^(?:([^:]+):)?([^:|]*)(\|.+)*$/.exec(t);this.full_name=t,this.namespace=e[1]||null,this.name=e[2]||null,this.transformations=[],"string"==typeof e[3]&&1e[d]))for(var o=0;othis.layout.height&&(s=Math.floor((this.layout.margin.top+this.layout.margin.bottom-this.layout.height)/2),this.layout.margin.top-=s,this.layout.margin.bottom-=s),this.layout.margin.left+this.layout.margin.right>this.layout.width&&(s=Math.floor((this.layout.margin.left+this.layout.margin.right-this.layout.width)/2),this.layout.margin.left-=s,this.layout.margin.right-=s),["top","right","bottom","left"].forEach(function(t){this.layout.margin[t]=Math.max(this.layout.margin[t],0)}.bind(this)),this.layout.cliparea.width=Math.max(this.layout.width-(this.layout.margin.left+this.layout.margin.right),0),this.layout.cliparea.height=Math.max(this.layout.height-(this.layout.margin.top+this.layout.margin.bottom),0),this.layout.cliparea.origin.x=this.layout.margin.left,this.layout.cliparea.origin.y=this.layout.margin.top,this.initialized&&this.render(),this},k.Panel.prototype.setTitle=function(t){if("string"==typeof this.layout.title){var e=this.layout.title;this.layout.title={text:e,x:0,y:0,style:{}}}return"string"==typeof t?this.layout.title.text=t:"object"==typeof t&&null!==t&&(this.layout.title=k.Layouts.merge(t,this.layout.title)),this.layout.title.text.length?this.title.attr("display",null).attr("x",parseFloat(this.layout.title.x)).attr("y",parseFloat(this.layout.title.y)).style(this.layout.title.style).text(this.layout.title.text):this.title.attr("display","none"),this},k.Panel.prototype.initialize=function(){this.svg.container=this.parent.svg.append("g").attr("id",this.getBaseId()+".panel_container").attr("transform","translate("+(this.layout.origin.x||0)+","+(this.layout.origin.y||0)+")");var t=this.svg.container.append("clipPath").attr("id",this.getBaseId()+".clip");if(this.svg.clipRect=t.append("rect").attr("width",this.layout.width).attr("height",this.layout.height),this.svg.group=this.svg.container.append("g").attr("id",this.getBaseId()+".panel").attr("clip-path","url(#"+this.getBaseId()+".clip)"),this.curtain=k.generateCurtain.call(this),this.loader=k.generateLoader.call(this),this.dashboard=new k.Dashboard(this),this.inner_border=this.svg.group.append("rect").attr("class","lz-panel-background").on("click",function(){"clear_selections"===this.layout.background_click&&this.clearSelections()}.bind(this)),this.title=this.svg.group.append("text").attr("class","lz-panel-title"),void 0!==this.layout.title&&this.setTitle(),this.svg.x_axis=this.svg.group.append("g").attr("id",this.getBaseId()+".x_axis").attr("class","lz-x lz-axis"),this.layout.axes.x.render&&(this.svg.x_axis_label=this.svg.x_axis.append("text").attr("class","lz-x lz-axis lz-label").attr("text-anchor","middle")),this.svg.y1_axis=this.svg.group.append("g").attr("id",this.getBaseId()+".y1_axis").attr("class","lz-y lz-y1 lz-axis"),this.layout.axes.y1.render&&(this.svg.y1_axis_label=this.svg.y1_axis.append("text").attr("class","lz-y1 lz-axis lz-label").attr("text-anchor","middle")),this.svg.y2_axis=this.svg.group.append("g").attr("id",this.getBaseId()+".y2_axis").attr("class","lz-y lz-y2 lz-axis"),this.layout.axes.y2.render&&(this.svg.y2_axis_label=this.svg.y2_axis.append("text").attr("class","lz-y2 lz-axis lz-label").attr("text-anchor","middle")),this.data_layer_ids_by_z_index.forEach(function(t){this.data_layers[t].initialize()}.bind(this)),this.legend=null,this.layout.legend&&(this.legend=new k.Legend(this)),this.layout.interaction.drag_background_to_pan){var e="."+this.parent.id+"."+this.id+".interaction.drag",a=function(){this.parent.startDrag(this,"background")}.bind(this);this.svg.container.select(".lz-panel-background").on("mousedown"+e+".background",a).on("touchstart"+e+".background",a)}return this},k.Panel.prototype.resortDataLayers=function(){var e=[];this.data_layer_ids_by_z_index.forEach(function(t){e.push(this.data_layers[t].layout.z_index)}.bind(this)),this.svg.group.selectAll("g.lz-data_layer-container").data(e).sort(f.ascending),this.applyDataLayerZIndexesToDataLayerLayouts()},k.Panel.prototype.getLinkedPanelIds=function(e){var a=[];return-1===["x","y1","y2"].indexOf(e=e||null)||this.layout.interaction[e+"_linked"]&&this.parent.panel_ids_by_y_index.forEach(function(t){t!==this.id&&this.parent.panels[t].layout.interaction[e+"_linked"]&&a.push(t)}.bind(this)),a},k.Panel.prototype.moveUp=function(){return this.parent.panel_ids_by_y_index[this.layout.y_index-1]&&(this.parent.panel_ids_by_y_index[this.layout.y_index]=this.parent.panel_ids_by_y_index[this.layout.y_index-1],this.parent.panel_ids_by_y_index[this.layout.y_index-1]=this.id,this.parent.applyPanelYIndexesToPanelLayouts(),this.parent.positionPanels()),this},k.Panel.prototype.moveDown=function(){return this.parent.panel_ids_by_y_index[this.layout.y_index+1]&&(this.parent.panel_ids_by_y_index[this.layout.y_index]=this.parent.panel_ids_by_y_index[this.layout.y_index+1],this.parent.panel_ids_by_y_index[this.layout.y_index+1]=this.id,this.parent.applyPanelYIndexesToPanelLayouts(),this.parent.positionPanels()),this},k.Panel.prototype.addDataLayer=function(t){if("object"!=typeof t||"string"!=typeof t.id||!t.id.length)throw new Error("Invalid data layer layout passed to LocusZoom.Panel.prototype.addDataLayer()");if(void 0!==this.data_layers[t.id])throw new Error("Cannot create data_layer with id ["+t.id+"]; data layer with that id already exists in the panel");if("string"!=typeof t.type)throw new Error("Invalid data layer type in layout passed to LocusZoom.Panel.prototype.addDataLayer()");"object"!=typeof t.y_axis||void 0!==t.y_axis.axis&&-1!==[1,2].indexOf(t.y_axis.axis)||(t.y_axis.axis=1);var a=k.DataLayers.get(t.type,t,this);if(null!==(this.data_layers[a.id]=a).layout.z_index&&!isNaN(a.layout.z_index)&&0[SHIFT] while scrolling to zoom").hide(1e3)}.bind(this);this.zoom_listener=f.behavior.zoom(),this.svg.container.call(this.zoom_listener).on("wheel.zoom",g).on("mousewheel.zoom",g).on("DOMMouseScroll.zoom",g)}return this.data_layer_ids_by_z_index.forEach(function(t){this.data_layers[t].draw().render()}.bind(this)),this},k.Panel.prototype.renderAxis=function(i){if(-1===["x","y1","y2"].indexOf(i))throw new Error("Unable to render axis; invalid axis identifier: "+i);var t=this.layout.axes[i].render&&"function"==typeof this[i+"_scale"]&&!isNaN(this[i+"_scale"](0));if(this[i+"_axis"]&&this.svg.container.select("g.lz-axis.lz-"+i).style("display",t?null:"none"),!t)return this;var e={x:{position:"translate("+this.layout.margin.left+","+(this.layout.height-this.layout.margin.bottom)+")",orientation:"bottom",label_x:this.layout.cliparea.width/2,label_y:this.layout.axes[i].label_offset||0,label_rotate:null},y1:{position:"translate("+this.layout.margin.left+","+this.layout.margin.top+")",orientation:"left",label_x:-1*(this.layout.axes[i].label_offset||0),label_y:this.layout.cliparea.height/2,label_rotate:-90},y2:{position:"translate("+(this.layout.width-this.layout.margin.right)+","+this.layout.margin.top+")",orientation:"right",label_x:this.layout.axes[i].label_offset||0,label_y:this.layout.cliparea.height/2,label_rotate:-90}};this[i+"_ticks"]=this.generateTicks(i);var a=function(t){for(var e=0;e",">=","%","filterIndexes","filterElements","verb","adjective","antiverb","setElementStatus","setElementStatusByFilters","setAllElementStatus","active","get_element_id_error","element_status_node_id","element_status_idx","added_status","emit","is_selected","value_to_broadcast","toggle","applyBehaviors","selection","event_match","executeBehaviors","requiredKeyStates","ctrlKey","shiftKey","behavior","current_status_boolean","href","target","window","location","panel_origin","exportData","format","default_format","toLowerCase","e","warn","jsonified","delimiter","record","draw","cliparea","reMap","promise","lzd","getData","new_data","DataLayers","datalayer","extend","parent_name","overrides","child","subclass","hit_area_width","render","self","trackData","visible_lines_group","enter","exit","hit_areas_group","hit_areas_selection","_getX","x_center","x_left","left_node","left_node_x_center","crds","arrow_type","arrow_top","arrow_left","tooltip_box","data_layer_height","data_layer_width","x_scale","y_center","offset_right","offset_left","stroke_width","top_offset","mouse","confidence_intervals","show_no_significance_line","y_scale","sqrt","PI","ci_selection","ci_transform","ci_width","duration","ease","points_selection","initial_y","symbol","element_data","ci_config","item","field_to_add","label_font_size","label_exon_spacing","exon_height","bounding_box_padding","track_vertical_spacing","getTrackHeight","transcript_idx","tracks","gene_track_index","1","assignTracks","getLabelWidth","gene_name","font_size","temp_text","label_width","getBBox","g","gene_id","gene_version","transcript_id","transcripts","display_range","text_anchor","centered_margin","display_domain","invert","track","potential_track","collision_on_potential_track","placed_gene","min_start","t","exons","bboxes","boundaries","labels","strand","exon_id","clickareas","gene_bbox_id","gene_bbox","gene_center_x","arrow_width","chromosome_fill_colors","light","dark","chromosome_label_colors","genome_start","genome_end","chromosomes","variant_parts","variant","track_split_order","track_split_legend_to_y_axis","track_height","previous_tracks","interval_track_index","track_split_field_index","reverse","placed_interval","psuedoElement","sharedstatusnode_style","interval","statusnode_style","statusnodes","rects","interval_name","updateSplitTrackAxis","interval_bbox","interval_center_x","legend_axis","track_spacing","target_height","scaleHeightToData","toggleSplitTracks","interpolate","hitarea_width","mouse_event","line","tooltip_timeout","getMouseDisplayAndData","slope","x_field","y_field","bisect","bisector","datum","startDatum","endDatum","interpolateNumber","x_precision","toPrecision","y_precision","dd","max_arrow_left","path","area","y0","hitarea","hitarea_line","path_class","global_status","decoupled","x_extent","y_extent","default_y","flip_labels","handle_lines","Boolean","min_x","max_x","flip","dn","dnl","dnx","text_swing","dnlx2","line_swing","label_texts","da","dal","label_lines","abound","bbound","separate_labels","seperate_iterations","again","db","delta","adjust","new_a_y","new_b_y","min_y","max_y","label_elements","filtered_data","label_groups","x1","x2","makeLDReference","ref","applyState","ldrefvar","_prepareData","xField","sourceData","sort","ak","bk","av","bv","_generateCategoryBounds","uniqueCategories","category","bounds","categoryNames","_setDynamicColorScheme","_getColorScale","from_source","color_params","find","colors","colorParams","baseParams","parameters_categories_hash","every","scale","category10","category20","concat","categoryBounds","_categories","knownCategories","knownColors","xPos","diff","KnownDataSources","SOURCE_NAME","source_name","newObj","params","Function","getAll","setAll","clear","TransformationFunctions","fun","getTrans","substring","result","funs","parseTransString","fn","ceil","toExponential","str","encodeURIComponent","s","input","threshold","prev","curr","nullval","upper_idx","brk","normalized_input","isFinite","Dashboard","hide_timeout","persist","component","Components","shouldPersist","visibility","destroy","force","Component","parent_panel","parent_svg","button","menu","Button","parent_dashboard","tag","setTag","setHtml","setText","setTitle","setColor","setStyle","getClass","permanent","setPermanent","bool","setStatus","highlight","disable","setOnMouseover","setOnMouseout","setOnclick","preUpdate","postUpdate","outer_selector","inner_selector","scroll_position","scrollTop","page_scroll_top","document","documentElement","container_offset","getContainerOffset","dashboard_client_rect","button_client_rect","menu_client_rect","total_content_height","scrollHeight","base_max_width","container_max_width","content_max_width","base_max_height","max_height","setPopulate","menu_populate_function","div_selector","title_selector","display_width","display_height","positionIntToString","stylesheet","generateBase64SVG","old","URL","revokeObjectURL","filename","css_string","styleSheets","createCORSPromise","outerHTML","dy","initial_html","style_def","insert_at","Blob","createObjectURL","suppress_confirm","confirm","removePanel","is_at_top","y_index","is_at_bottom","panel_ids_by_y_index","can_zoom","current_region_scale","new_region_scale","menu_html","model","covariates","CovariatesModel","element_reference","updateComponent","removeByIdx","removeAll","table","covariate","row","cov","scale_timeout","status_adj","status_idx","status_verb","at_top","at_bottom","td","removeDataLayer","allowed_fields","fields_whitelist","dataLayer","dataLayerLayout","defaultConfig","configSlot","undefined","_selected_item","uniqueID","random","menuLayout","renderRow","display_options","row_id","radioId","field_name","defaultName","Legend","background_rect","elements","elements_group","padding","label_size","line_height","label_x","label_y","path_y","symbolTypes","radius","bcr","right_x","pad_from_right","DataSources","addSource","ns","dsobj","source_id","getSource","removeSource","fromJSON","ds","toJSON","parts","full_name","applyTransformations","Requester","requests","raw","trans","outnames","request_handles","discrete","Source","enableCache","dependentSource","parseInit","init","getCacheKey","chain","getURL","fetchRequest","getRequest","req","cacheKey","_cachedKey","_cachedResponse","preGetData","pre","resp","parseResponse","normalizeResponse","N","records","j","prepareData","annotateData","extractFields","fieldFound","output_record","v","combineChainBody","json","standardized","one_source_body","new_body","parseArraysToObjects","standard","parseObjectsToObjects","parseData","constructorFun","uniqueName","getPrototypeOf","AssociationSource","unshift","analysis","LDSource","findMergeFields","arr","dataFields","position_field","pvalue","pvalue_field","_names_","names","nameMatch","regexes","id_match","RegExp","findRequestedFields","isrefvarin","isrefvarout","ldin","ldout","getRefvar","refVar","columns","pval_field","cmp","test","extremeVal","extremeIdx","findExtremeValue","refSource","ldrefsource","reqFields","corrField","rsquare","lfield","rfield","position2","leftJoin","refvar","idfield","outrefname","outldname","tagRefVariant","LDSource2","genome_build","ld_source","population","ld_pop","combined","chainRequests","payload","next","GwasCatalog","build_option","default_source","posMatch","decider","decider_out","n_matches","outn","chainNames","catNames","GeneSource","GeneConstraintSource","geneids","substr","Content-Type","constraint_fields","RecombinationRateSource","IntervalSource","bedtracksource","StaticSource","_data","PheWASSource","ConnectorSource","_source_name_mapping","specified_ids","REQUIRED_SOURCES","chain_source_id","applyPanelYIndexesToPanelLayouts","pid","remap_promises","window_onresize","event_hooks","layout_changed","data_requested","data_rendered","element_clicked","element_selection","match_requested","panel_removed","state_changed","hook","off","theseHooks","hookMatch","eventData","sourceID","hookToRun","eventContext","bounding_client_rect","x_offset","scrollLeft","y_offset","offsetParent","offsetTop","offsetLeft","canInteract","loading_data","zooming","initializeLayout","aspect_ratio","sumProportional","total","rescaleSVG","clientRect","RESIZE_MODES","panel_layout","addPanel","min-width","min-height","panel_width","panel_height","setOrigin","proportional_origin","clearPanelData","panelId","mode","panelsList","dlid","layer","x_linked_margins","total_proportional_height","proportional_adjustment","calculated_plot_height","mouse_guide_svg","mouse_guide_vertical_svg","mouse_guide_horizontal_svg","vertical","horizontal","generateCurtain","generateLoader","selectors","corner_selector","panel_idx","panel_resize_drag","drag","this_panel","original_panel_height","panel_height_change","new_calculated_plot_height","loop_panel_id","loop_panel_idx","loop_panel","corner_drag","dx","plot_page_origin","panel_page_origin","mouseout_mouse_guide","mousemove_mouse_guide","coords","mouseup","stopDrag","mousemove","preventDefault","dragged_x","start_x","dragged_y","start_y","linked_panel_ids","to_send","client_rect","subscribeToData","success_callback","opts","error_callback","onerror","err","listener","catch","state_changes","validateState","all","message","startDrag","getLinkedPanelIds","overrideAxisLayout","axis_number","y_axis_number","generateID","applyDataLayerZIndexesToDataLayerLayouts","data_promises","y1_scale","y2_scale","y1_extent","y2_extent","x_ticks","y1_ticks","y2_ticks","zoom_timeout","bubble","plot_origin","background_click","y1_linked","y2_linked","panel_count","setMargin","x_range","y1_range","y2_range","label_function","data_layer_layout","addDataLayer","clipPath","clearSelections","x_axis_label","y1_axis","y1_axis_label","y2_axis","y2_axis_label","mousedown","ascending","generateExtents","generateTicks","baseTickConfig","acc","nextLayer","itemConfig","prettyTicks","constrain","limit_exponent","neg_min","neg_max","pos_min","pos_max","Infinity","ranges","base_x_range","x_shifted","base_y1_range","y1_shifted","base_y2_range","y2_shifted","anchor","scalar","current_extent_size","current_scaled_extent_size","zoom_factor","potential_extent_size","new_extent_size","offset_ratio","new_x_extent_start","y_shifted","linear","domain","renderAxis","zoom_handler","wheelDelta","detail","deltaY","zoom_listener","zoom","canRender","axis_params","label_rotate","ticksAreAllNumbers","orient","tickPadding","tickValues","tickFormat","tick_selector","tick_mouseover","focus","cursor","dh","addBasicLoader","show_immediately","plugin_loading_error","define","amd","module","exports","require"],"mappings":"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","file":"locuszoom.app.min.js","sourcesContent":["(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n define(['d3'], function (d3) {\n // amd\n return root.LocusZoom = factory(d3);\n });\n } else if (typeof module === 'object' && module.exports) {\n // commonJS\n module.exports = root.LocusZoom = factory(require('d3'));\n } else {\n // globals\n root.LocusZoom = factory(root.d3);\n }\n}(this, function (d3) {\n var semanticVersionIsOk = function (minimum_version, current_version) {\n // handle the trivial case\n if (current_version == minimum_version) {\n return true;\n } // compare semantic versions by component as integers\n // compare semantic versions by component as integers\n var minimum_version_array = minimum_version.split('.');\n var current_version_array = current_version.split('.');\n var version_is_ok = false;\n minimum_version_array.forEach(function (d, i) {\n if (!version_is_ok && +current_version_array[i] > +minimum_version_array[i]) {\n version_is_ok = true;\n }\n });\n return version_is_ok;\n };\n try {\n // Verify dependency: d3.js\n var minimum_d3_version = '3.5.6';\n if (typeof d3 != 'object') {\n throw new Error('d3 dependency not met. Library missing.');\n }\n if (!semanticVersionIsOk(minimum_d3_version, d3.version)) {\n throw new Error('d3 dependency not met. Outdated version detected.\\nRequired d3 version: ' + minimum_d3_version + ' or higher (found: ' + d3.version + ').');\n } // ESTemplate: module content goes here\n // ESTemplate: module content goes here\n ;\n (function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n define(['d3'], function (d3) {\n // amd\n return root.LocusZoom = factory(d3);\n });\n } else if (typeof module === 'object' && module.exports) {\n // commonJS\n module.exports = root.LocusZoom = factory(require('d3'));\n } else {\n // globals\n root.LocusZoom = factory(root.d3);\n }\n }(this, function (d3) {\n var semanticVersionIsOk = function (minimum_version, current_version) {\n // handle the trivial case\n if (current_version == minimum_version) {\n return true;\n }\n // compare semantic versions by component as integers\n // compare semantic versions by component as integers\n var minimum_version_array = minimum_version.split('.');\n var current_version_array = current_version.split('.');\n var version_is_ok = false;\n minimum_version_array.forEach(function (d, i) {\n if (!version_is_ok && +current_version_array[i] > +minimum_version_array[i]) {\n version_is_ok = true;\n }\n });\n return version_is_ok;\n };\n try {\n // Verify dependency: d3.js\n var minimum_d3_version = '3.5.6';\n if (typeof d3 != 'object') {\n throw new Error('d3 dependency not met. Library missing.');\n }\n if (!semanticVersionIsOk(minimum_d3_version, d3.version)) {\n throw new Error('d3 dependency not met. Outdated version detected.\\nRequired d3 version: ' + minimum_d3_version + ' or higher (found: ' + d3.version + ').');\n }\n // ESTemplate: module content goes here\n // ESTemplate: module content goes here\n ;\n var LocusZoom = { version: '0.10.0' };\n /**\n * Populate a single element with a LocusZoom plot.\n * selector can be a string for a DOM Query or a d3 selector.\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot} The newly created plot instance\n */\n LocusZoom.populate = function (selector, datasource, layout) {\n if (typeof selector == 'undefined') {\n throw new Error('LocusZoom.populate selector not defined');\n }\n // Empty the selector of any existing content\n d3.select(selector).html('');\n var plot;\n d3.select(selector).call(function () {\n // Require each containing element have an ID. If one isn't present, create one.\n if (typeof this.node().id == 'undefined') {\n var iterator = 0;\n while (!d3.select('#lz-' + iterator).empty()) {\n iterator++;\n }\n this.attr('id', '#lz-' + iterator);\n }\n // Create the plot\n plot = new LocusZoom.Plot(this.node().id, datasource, layout);\n plot.container = this.node();\n // Detect data-region and fill in state values if present\n if (typeof this.node().dataset !== 'undefined' && typeof this.node().dataset.region !== 'undefined') {\n var parsed_state = LocusZoom.parsePositionQuery(this.node().dataset.region);\n Object.keys(parsed_state).forEach(function (key) {\n plot.state[key] = parsed_state[key];\n });\n }\n // Add an SVG to the div and set its dimensions\n plot.svg = d3.select('div#' + plot.id).append('svg').attr('version', '1.1').attr('xmlns', 'http://www.w3.org/2000/svg').attr('id', plot.id + '_svg').attr('class', 'lz-locuszoom').style(plot.layout.style);\n plot.setDimensions();\n plot.positionPanels();\n // Initialize the plot\n plot.initialize();\n // If the plot has defined data sources then trigger its first mapping based on state values\n if (typeof datasource == 'object' && Object.keys(datasource).length) {\n plot.refresh();\n }\n });\n return plot;\n };\n /**\n * Populate arbitrarily many elements each with a LocusZoom plot\n * using a common datasource and layout\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot[]}\n */\n LocusZoom.populateAll = function (selector, datasource, layout) {\n var plots = [];\n d3.selectAll(selector).each(function (d, i) {\n plots[i] = LocusZoom.populate(this, datasource, layout);\n });\n return plots;\n };\n /**\n * Convert an integer chromosome position to an SI string representation (e.g. 23423456 => \"23.42\" (Mb))\n * @param {Number} pos Position\n * @param {Number} [exp] Exponent to use for the returned string, eg 6=> MB. If not specified, will attempt to guess\n * the most appropriate SI prefix based on the number provided.\n * @param {Boolean} [suffix=false] Whether or not to append a suffix (e.g. \"Mb\") to the end of the returned string\n * @returns {string}\n */\n LocusZoom.positionIntToString = function (pos, exp, suffix) {\n var exp_symbols = {\n 0: '',\n 3: 'K',\n 6: 'M',\n 9: 'G'\n };\n suffix = suffix || false;\n if (isNaN(exp) || exp === null) {\n var log = Math.log(pos) / Math.LN10;\n exp = Math.min(Math.max(log - log % 3, 0), 9);\n }\n var places_exp = exp - Math.floor((Math.log(pos) / Math.LN10).toFixed(exp + 3));\n var min_exp = Math.min(Math.max(exp, 0), 2);\n var places = Math.min(Math.max(places_exp, min_exp), 12);\n var ret = '' + (pos / Math.pow(10, exp)).toFixed(places);\n if (suffix && typeof exp_symbols[exp] !== 'undefined') {\n ret += ' ' + exp_symbols[exp] + 'b';\n }\n return ret;\n };\n /**\n * Convert an SI string chromosome position to an integer representation (e.g. \"5.8 Mb\" => 58000000)\n * @param {String} p The chromosome position\n * @returns {Number}\n */\n LocusZoom.positionStringToInt = function (p) {\n var val = p.toUpperCase();\n val = val.replace(/,/g, '');\n var suffixre = /([KMG])[B]*$/;\n var suffix = suffixre.exec(val);\n var mult = 1;\n if (suffix) {\n if (suffix[1] === 'M') {\n mult = 1000000;\n } else if (suffix[1] === 'G') {\n mult = 1000000000;\n } else {\n mult = 1000; //K\n }\n val = val.replace(suffixre, '');\n }\n val = Number(val) * mult;\n return val;\n };\n /**\n * Parse region queries into their constituent parts\n * TODO: handle genes (or send off to API)\n * @param {String} x A chromosome position query. May be any of the forms `chr:start-end`, `chr:center+offset`,\n * or `chr:pos`\n * @returns {{chr:*, start: *, end:*} | {chr:*, position:*}}\n */\n LocusZoom.parsePositionQuery = function (x) {\n var chrposoff = /^(\\w+):([\\d,.]+[kmgbKMGB]*)([-+])([\\d,.]+[kmgbKMGB]*)$/;\n var chrpos = /^(\\w+):([\\d,.]+[kmgbKMGB]*)$/;\n var match = chrposoff.exec(x);\n if (match) {\n if (match[3] === '+') {\n var center = LocusZoom.positionStringToInt(match[2]);\n var offset = LocusZoom.positionStringToInt(match[4]);\n return {\n chr: match[1],\n start: center - offset,\n end: center + offset\n };\n } else {\n return {\n chr: match[1],\n start: LocusZoom.positionStringToInt(match[2]),\n end: LocusZoom.positionStringToInt(match[4])\n };\n }\n }\n match = chrpos.exec(x);\n if (match) {\n return {\n chr: match[1],\n position: LocusZoom.positionStringToInt(match[2])\n };\n }\n return null;\n };\n /**\n * Generate a \"pretty\" set of ticks (multiples of 1, 2, or 5 on the same order of magnitude for the range)\n * Based on R's \"pretty\" function: https://github.com/wch/r-source/blob/b156e3a711967f58131e23c1b1dc1ea90e2f0c43/src/appl/pretty.c\n * @param {Number[]} range A two-item array specifying [low, high] values for the axis range\n * @param {('low'|'high'|'both'|'neither')} [clip_range='neither'] What to do if first and last generated ticks extend\n * beyond the range. Set this to \"low\", \"high\", \"both\", or \"neither\" to clip the first (low) or last (high) tick to\n * be inside the range or allow them to extend beyond.\n * e.g. \"low\" will clip the first (low) tick if it extends beyond the low end of the range but allow the\n * last (high) tick to extend beyond the range. \"both\" clips both ends, \"neither\" allows both to extend beyond.\n * @param {Number} [target_tick_count=5] The approximate number of ticks you would like to be returned; may not be exact\n * @returns {Number[]}\n */\n LocusZoom.prettyTicks = function (range, clip_range, target_tick_count) {\n if (typeof target_tick_count == 'undefined' || isNaN(parseInt(target_tick_count))) {\n target_tick_count = 5;\n }\n target_tick_count = parseInt(target_tick_count);\n var min_n = target_tick_count / 3;\n var shrink_sml = 0.75;\n var high_u_bias = 1.5;\n var u5_bias = 0.5 + 1.5 * high_u_bias;\n var d = Math.abs(range[0] - range[1]);\n var c = d / target_tick_count;\n if (Math.log(d) / Math.LN10 < -2) {\n c = Math.max(Math.abs(d)) * shrink_sml / min_n;\n }\n var base = Math.pow(10, Math.floor(Math.log(c) / Math.LN10));\n var base_toFixed = 0;\n if (base < 1 && base !== 0) {\n base_toFixed = Math.abs(Math.round(Math.log(base) / Math.LN10));\n }\n var unit = base;\n if (2 * base - c < high_u_bias * (c - unit)) {\n unit = 2 * base;\n if (5 * base - c < u5_bias * (c - unit)) {\n unit = 5 * base;\n if (10 * base - c < high_u_bias * (c - unit)) {\n unit = 10 * base;\n }\n }\n }\n var ticks = [];\n var i = parseFloat((Math.floor(range[0] / unit) * unit).toFixed(base_toFixed));\n while (i < range[1]) {\n ticks.push(i);\n i += unit;\n if (base_toFixed > 0) {\n i = parseFloat(i.toFixed(base_toFixed));\n }\n }\n ticks.push(i);\n if (typeof clip_range == 'undefined' || [\n 'low',\n 'high',\n 'both',\n 'neither'\n ].indexOf(clip_range) === -1) {\n clip_range = 'neither';\n }\n if (clip_range === 'low' || clip_range === 'both') {\n if (ticks[0] < range[0]) {\n ticks = ticks.slice(1);\n }\n }\n if (clip_range === 'high' || clip_range === 'both') {\n if (ticks[ticks.length - 1] > range[1]) {\n ticks.pop();\n }\n }\n return ticks;\n };\n /**\n * Make an AJAX request and return a promise.\n * From http://www.html5rocks.com/en/tutorials/cors/\n * and with promises from https://gist.github.com/kriskowal/593076\n *\n * @param {String} method The HTTP verb\n * @param {String} url\n * @param {String} [body] The request body to send to the server\n * @param {Object} [headers] Object of custom request headers\n * @param {Number} [timeout] If provided, wait this long (in ms) before timing out\n * @returns {Promise}\n */\n LocusZoom.createCORSPromise = function (method, url, body, headers, timeout) {\n return new Promise(function (resolve, reject) {\n var xhr = new XMLHttpRequest();\n if ('withCredentials' in xhr) {\n // Check if the XMLHttpRequest object has a \"withCredentials\" property.\n // \"withCredentials\" only exists on XMLHTTPRequest2 objects.\n xhr.open(method, url, true);\n } else if (typeof XDomainRequest != 'undefined') {\n // Otherwise, check if XDomainRequest.\n // XDomainRequest only exists in IE, and is IE's way of making CORS requests.\n xhr = new XDomainRequest();\n xhr.open(method, url);\n } else {\n // Otherwise, CORS is not supported by the browser.\n xhr = null;\n }\n if (xhr) {\n xhr.onreadystatechange = function () {\n if (xhr.readyState === 4) {\n if (xhr.status === 200 || xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject('HTTP ' + xhr.status + ' for ' + url);\n }\n }\n };\n timeout && setTimeout(reject, timeout);\n body = typeof body !== 'undefined' ? body : '';\n if (typeof headers !== 'undefined') {\n for (var header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n }\n // Send the request\n xhr.send(body);\n }\n });\n };\n /**\n * Validate a (presumed complete) plot state object against internal rules for consistency, and ensure the plot fits\n * within any constraints imposed by the layout.\n * @param {Object} new_state\n * @param {Number} new_state.start\n * @param {Number} new_state.end\n * @param {Object} layout\n * @returns {*|{}}\n */\n LocusZoom.validateState = function (new_state, layout) {\n new_state = new_state || {};\n layout = layout || {};\n // If a \"chr\", \"start\", and \"end\" are present then resolve start and end\n // to numeric values that are not decimal, negative, or flipped\n var validated_region = false;\n if (typeof new_state.chr != 'undefined' && typeof new_state.start != 'undefined' && typeof new_state.end != 'undefined') {\n // Determine a numeric scale and midpoint for the attempted region,\n var attempted_midpoint = null;\n var attempted_scale;\n new_state.start = Math.max(parseInt(new_state.start), 1);\n new_state.end = Math.max(parseInt(new_state.end), 1);\n if (isNaN(new_state.start) && isNaN(new_state.end)) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_midpoint = 0.5;\n attempted_scale = 0;\n } else if (isNaN(new_state.start) || isNaN(new_state.end)) {\n attempted_midpoint = new_state.start || new_state.end;\n attempted_scale = 0;\n new_state.start = isNaN(new_state.start) ? new_state.end : new_state.start;\n new_state.end = isNaN(new_state.end) ? new_state.start : new_state.end;\n } else {\n attempted_midpoint = Math.round((new_state.start + new_state.end) / 2);\n attempted_scale = new_state.end - new_state.start;\n if (attempted_scale < 0) {\n var temp = new_state.start;\n new_state.end = new_state.start;\n new_state.start = temp;\n attempted_scale = new_state.end - new_state.start;\n }\n if (attempted_midpoint < 0) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_scale = 0;\n }\n }\n validated_region = true;\n }\n // Constrain w/r/t layout-defined minimum region scale\n if (!isNaN(layout.min_region_scale) && validated_region && attempted_scale < layout.min_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.min_region_scale / 2), 1);\n new_state.end = new_state.start + layout.min_region_scale;\n }\n // Constrain w/r/t layout-defined maximum region scale\n if (!isNaN(layout.max_region_scale) && validated_region && attempted_scale > layout.max_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.max_region_scale / 2), 1);\n new_state.end = new_state.start + layout.max_region_scale;\n }\n return new_state;\n };\n //\n /**\n * Replace placeholders in an html string with field values defined in a data object\n * Only works on scalar values! Will ignore non-scalars.\n *\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @param {Object} data\n * @param {String} html A placeholder string in which to substitute fields. Supports several template options:\n * `{{field_name}}` is a variable placeholder for the value of `field_name` from the provided data\n * `{{#if field_name}} Conditional text {{/if}}` will insert the contents of the tag only if the value exists.\n * Since this is only an existence check, **variables with a value of 0 will be evaluated as true**.\n * This can be used with namespaced values, `{{#if assoc:field}}`; any dynamic namespacing will be applied when the\n * layout is first retrieved.\n * @returns {string}\n */\n LocusZoom.parseFields = function (data, html) {\n if (typeof data != 'object') {\n throw new Error('LocusZoom.parseFields invalid arguments: data is not an object');\n }\n if (typeof html != 'string') {\n throw new Error('LocusZoom.parseFields invalid arguments: html is not a string');\n }\n // `tokens` is like [token,...]\n // `token` is like {text: '...'} or {variable: 'foo|bar'} or {condition: 'foo|bar'} or {close: 'if'}\n var tokens = [];\n var regex = /\\{\\{(?:(#if )?([A-Za-z0-9_:|]+)|(\\/if))\\}\\}/;\n while (html.length > 0) {\n var m = regex.exec(html);\n if (!m) {\n tokens.push({ text: html });\n html = '';\n } else if (m.index !== 0) {\n tokens.push({ text: html.slice(0, m.index) });\n html = html.slice(m.index);\n } else if (m[1] === '#if ') {\n tokens.push({ condition: m[2] });\n html = html.slice(m[0].length);\n } else if (m[2]) {\n tokens.push({ variable: m[2] });\n html = html.slice(m[0].length);\n } else if (m[3] === '/if') {\n tokens.push({ close: 'if' });\n html = html.slice(m[0].length);\n } else {\n console.error('Error tokenizing tooltip when remaining template is ' + JSON.stringify(html) + ' and previous tokens are ' + JSON.stringify(tokens) + ' and current regex match is ' + JSON.stringify([\n m[1],\n m[2],\n m[3]\n ]));\n html = html.slice(m[0].length);\n }\n }\n var astify = function () {\n var token = tokens.shift();\n if (typeof token.text !== 'undefined' || token.variable) {\n return token;\n } else if (token.condition) {\n token.then = [];\n while (tokens.length > 0) {\n if (tokens[0].close === 'if') {\n tokens.shift();\n break;\n }\n token.then.push(astify());\n }\n return token;\n } else {\n console.error('Error making tooltip AST due to unknown token ' + JSON.stringify(token));\n return { text: '' };\n }\n };\n // `ast` is like [thing,...]\n // `thing` is like {text: \"...\"} or {variable:\"foo|bar\"} or {condition: \"foo|bar\", then:[thing,...]}\n var ast = [];\n while (tokens.length > 0) {\n ast.push(astify());\n }\n var resolve = function (variable) {\n if (!resolve.cache.hasOwnProperty(variable)) {\n resolve.cache[variable] = new LocusZoom.Data.Field(variable).resolve(data);\n }\n return resolve.cache[variable];\n };\n resolve.cache = {};\n var render_node = function (node) {\n if (typeof node.text !== 'undefined') {\n return node.text;\n } else if (node.variable) {\n try {\n var value = resolve(node.variable);\n if ([\n 'string',\n 'number',\n 'boolean'\n ].indexOf(typeof value) !== -1) {\n return value;\n }\n if (value === null) {\n return '';\n }\n } catch (error) {\n console.error('Error while processing variable ' + JSON.stringify(node.variable));\n }\n return '{{' + node.variable + '}}';\n } else if (node.condition) {\n try {\n var condition = resolve(node.condition);\n if (condition || condition === 0) {\n return node.then.map(render_node).join('');\n }\n } catch (error) {\n console.error('Error while processing condition ' + JSON.stringify(node.variable));\n }\n return '';\n } else {\n console.error('Error rendering tooltip due to unknown AST node ' + JSON.stringify(node));\n }\n };\n return ast.map(render_node).join('');\n };\n /**\n * Shortcut method for getting the data bound to a tool tip.\n * @param {Element} node\n * @returns {*} The first element of data bound to the tooltip\n */\n LocusZoom.getToolTipData = function (node) {\n if (typeof node != 'object' || typeof node.parentNode == 'undefined') {\n throw new Error('Invalid node object');\n }\n // If this node is a locuszoom tool tip then return its data\n var selector = d3.select(node);\n if (selector.classed('lz-data_layer-tooltip') && typeof selector.data()[0] != 'undefined') {\n return selector.data()[0];\n } else {\n return LocusZoom.getToolTipData(node.parentNode);\n }\n };\n /**\n * Shortcut method for getting a reference to the data layer that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.getToolTipDataLayer = function (node) {\n var data = LocusZoom.getToolTipData(node);\n if (data.getDataLayer) {\n return data.getDataLayer();\n }\n return null;\n };\n /**\n * Shortcut method for getting a reference to the panel that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.getToolTipPanel = function (node) {\n var data_layer = LocusZoom.getToolTipDataLayer(node);\n if (data_layer) {\n return data_layer.parent;\n }\n return null;\n };\n /**\n * Shortcut method for getting a reference to the plot that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.getToolTipPlot = function (node) {\n var panel = LocusZoom.getToolTipPanel(node);\n if (panel) {\n return panel.parent;\n }\n return null;\n };\n /**\n * Generate a curtain object for a plot, panel, or any other subdivision of a layout\n * The panel curtain, like the plot curtain is an HTML overlay that obscures the entire panel. It can be styled\n * arbitrarily and display arbitrary messages. It is useful for reporting error messages visually to an end user\n * when the error renders the panel unusable.\n * TODO: Improve type doc here\n * @returns {object}\n */\n LocusZoom.generateCurtain = function () {\n var curtain = {\n showing: false,\n selector: null,\n content_selector: null,\n hide_delay: null,\n /**\n * Generate the curtain. Any content (string) argument passed will be displayed in the curtain as raw HTML.\n * CSS (object) can be passed which will apply styles to the curtain and its content.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n show: function (content, css) {\n if (!this.curtain.showing) {\n this.curtain.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div').attr('class', 'lz-curtain').attr('id', this.id + '.curtain');\n this.curtain.content_selector = this.curtain.selector.append('div').attr('class', 'lz-curtain-content');\n this.curtain.selector.append('div').attr('class', 'lz-curtain-dismiss').html('Dismiss').on('click', function () {\n this.curtain.hide();\n }.bind(this));\n this.curtain.showing = true;\n }\n return this.curtain.update(content, css);\n }.bind(this),\n /**\n * Update the content and css of the curtain that's currently being shown. This method also adjusts the size\n * and positioning of the curtain to ensure it still covers the entire panel with no overlap.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n update: function (content, css) {\n if (!this.curtain.showing) {\n return this.curtain;\n }\n clearTimeout(this.curtain.hide_delay);\n // Apply CSS if provided\n if (typeof css == 'object') {\n this.curtain.selector.style(css);\n }\n // Update size and position\n var page_origin = this.getPageOrigin();\n this.curtain.selector.style({\n top: page_origin.y + 'px',\n left: page_origin.x + 'px',\n width: this.layout.width + 'px',\n height: this.layout.height + 'px'\n });\n this.curtain.content_selector.style({\n 'max-width': this.layout.width - 40 + 'px',\n 'max-height': this.layout.height - 40 + 'px'\n });\n // Apply content if provided\n if (typeof content == 'string') {\n this.curtain.content_selector.html(content);\n }\n return this.curtain;\n }.bind(this),\n /**\n * Remove the curtain\n * @param {number} delay Time to wait (in ms)\n */\n hide: function (delay) {\n if (!this.curtain.showing) {\n return this.curtain;\n }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.curtain.hide_delay);\n this.curtain.hide_delay = setTimeout(this.curtain.hide, delay);\n return this.curtain;\n }\n // Remove curtain\n this.curtain.selector.remove();\n this.curtain.selector = null;\n this.curtain.content_selector = null;\n this.curtain.showing = false;\n return this.curtain;\n }.bind(this)\n };\n return curtain;\n };\n /**\n * Generate a loader object for a plot, panel, or any other subdivision of a layout\n *\n * The panel loader is a small HTML overlay that appears in the lower left corner of the panel. It cannot be styled\n * arbitrarily, but can show a custom message and show a minimalist loading bar that can be updated to specific\n * completion percentages or be animated.\n * TODO Improve type documentation\n * @returns {object}\n */\n LocusZoom.generateLoader = function () {\n var loader = {\n showing: false,\n selector: null,\n content_selector: null,\n progress_selector: null,\n cancel_selector: null,\n /**\n * Show a loading indicator\n * @param {string} [content='Loading...'] Loading message (displayed as raw HTML)\n */\n show: function (content) {\n // Generate loader\n if (!this.loader.showing) {\n this.loader.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div').attr('class', 'lz-loader').attr('id', this.id + '.loader');\n this.loader.content_selector = this.loader.selector.append('div').attr('class', 'lz-loader-content');\n this.loader.progress_selector = this.loader.selector.append('div').attr('class', 'lz-loader-progress-container').append('div').attr('class', 'lz-loader-progress');\n /* TODO: figure out how to make this cancel button work\n this.loader.cancel_selector = this.loader.selector.append(\"div\")\n .attr(\"class\", \"lz-loader-cancel\").html(\"Cancel\")\n .on(\"click\", function(){\n this.loader.hide();\n }.bind(this));\n */\n this.loader.showing = true;\n if (typeof content == 'undefined') {\n content = 'Loading...';\n }\n }\n return this.loader.update(content);\n }.bind(this),\n /**\n * Update the currently displayed loader and ensure the new content is positioned correctly.\n * @param {string} content The text to display (as raw HTML). If not a string, will be ignored.\n * @param {number} [percent] A number from 1-100. If a value is specified, it will stop all animations\n * in progress.\n */\n update: function (content, percent) {\n if (!this.loader.showing) {\n return this.loader;\n }\n clearTimeout(this.loader.hide_delay);\n // Apply content if provided\n if (typeof content == 'string') {\n this.loader.content_selector.html(content);\n }\n // Update size and position\n var padding = 6;\n // is there a better place to store/define this?\n var page_origin = this.getPageOrigin();\n var loader_boundrect = this.loader.selector.node().getBoundingClientRect();\n this.loader.selector.style({\n top: page_origin.y + this.layout.height - loader_boundrect.height - padding + 'px',\n left: page_origin.x + padding + 'px'\n });\n /* Uncomment this code when a functional cancel button can be shown\n var cancel_boundrect = this.loader.cancel_selector.node().getBoundingClientRect();\n this.loader.content_selector.style({\n \"padding-right\": (cancel_boundrect.width + padding) + \"px\"\n });\n */\n // Apply percent if provided\n if (typeof percent == 'number') {\n this.loader.progress_selector.style({ width: Math.min(Math.max(percent, 1), 100) + '%' });\n }\n return this.loader;\n }.bind(this),\n /**\n * Adds a class to the loading bar that makes it loop infinitely in a loading animation. Useful when exact\n * percent progress is not available.\n */\n animate: function () {\n this.loader.progress_selector.classed('lz-loader-progress-animated', true);\n return this.loader;\n }.bind(this),\n /**\n * Sets the loading bar in the loader to percentage width equal to the percent (number) value passed. Percents\n * will automatically be limited to a range of 1 to 100. Will stop all animations in progress.\n */\n setPercentCompleted: function (percent) {\n this.loader.progress_selector.classed('lz-loader-progress-animated', false);\n return this.loader.update(null, percent);\n }.bind(this),\n /**\n * Remove the loader\n * @param {number} delay Time to wait (in ms)\n */\n hide: function (delay) {\n if (!this.loader.showing) {\n return this.loader;\n }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.loader.hide_delay);\n this.loader.hide_delay = setTimeout(this.loader.hide, delay);\n return this.loader;\n }\n // Remove loader\n this.loader.selector.remove();\n this.loader.selector = null;\n this.loader.content_selector = null;\n this.loader.progress_selector = null;\n this.loader.cancel_selector = null;\n this.loader.showing = false;\n return this.loader;\n }.bind(this)\n };\n return loader;\n };\n /**\n * Create a new subclass following classical inheritance patterns. Some registry singletons use this internally to\n * enable code reuse and customization of known LZ core functionality.\n *\n * @param {Function} parent A parent class constructor that will be extended by the child class\n * @param {Object} extra An object of additional properties and methods to add/override behavior for the child class.\n * The special \"constructor\" property can be used to specify a custom constructor, or it will call parent by default.\n * Implementer must manage super calls when overriding the constructor.\n * @returns {Function} The constructor for the new child class\n */\n LocusZoom.subclass = function (parent, extra) {\n if (typeof parent !== 'function') {\n throw new Error('Parent must be a callable constructor');\n }\n extra = extra || {};\n var Sub = extra.hasOwnProperty('constructor') ? extra.constructor : function () {\n parent.apply(this, arguments);\n };\n Sub.prototype = Object.create(parent.prototype);\n Object.keys(extra).forEach(function (k) {\n Sub.prototype[k] = extra[k];\n });\n return Sub;\n };\n /**\n * LocusZoom optional extensions will live under this namespace.\n *\n * Extension code is not part of the core LocusZoom app.js bundle.\n * @namespace\n * @public\n */\n LocusZoom.ext = {};\n /* global LocusZoom */\n 'use strict';\n var LZ_SIG_THRESHOLD_LOGP = 7.301;\n // -log10(.05/1e6)\n /**\n * Manage known layouts for all parts of the LocusZoom plot\n *\n * This registry allows for layouts to be reused and customized many times on a page, using a common base pattern.\n * It handles the work of ensuring that each new instance of the layout has no shared state with other copies.\n *\n * @class\n */\n LocusZoom.Layouts = function () {\n var obj = {};\n var layouts = {\n 'plot': {},\n 'panel': {},\n 'data_layer': {},\n 'dashboard': {},\n 'dashboard_components': {},\n 'tooltip': {}\n };\n /**\n * Generate a layout configuration object\n * @param {('plot'|'panel'|'data_layer'|'dashboard'|'tooltip')} type The type of layout to retrieve\n * @param {string} name Identifier of the predefined layout within the specified type\n * @param {object} [modifications] Custom properties that override default settings for this layout\n * @returns {object} A JSON-serializable object representation\n */\n obj.get = function (type, name, modifications) {\n if (typeof type != 'string' || typeof name != 'string') {\n throw new Error('invalid arguments passed to LocusZoom.Layouts.get, requires string (layout type) and string (layout name)');\n } else if (layouts[type][name]) {\n // Get the base layout\n var layout = LocusZoom.Layouts.merge(modifications || {}, layouts[type][name]);\n // If \"unnamespaced\" is true then strike that from the layout and return the layout without namespacing\n if (layout.unnamespaced) {\n delete layout.unnamespaced;\n return JSON.parse(JSON.stringify(layout));\n }\n // Determine the default namespace for namespaced values\n var default_namespace = '';\n if (typeof layout.namespace == 'string') {\n default_namespace = layout.namespace;\n } else if (typeof layout.namespace == 'object' && Object.keys(layout.namespace).length) {\n if (typeof layout.namespace.default != 'undefined') {\n default_namespace = layout.namespace.default;\n } else {\n default_namespace = layout.namespace[Object.keys(layout.namespace)[0]].toString();\n }\n }\n default_namespace += default_namespace.length ? ':' : '';\n // Apply namespaces to layout, recursively\n var applyNamespaces = function (element, namespace) {\n if (namespace) {\n if (typeof namespace == 'string') {\n namespace = { default: namespace };\n }\n } else {\n namespace = { default: '' };\n }\n if (typeof element == 'string') {\n var re = /\\{\\{namespace(\\[[A-Za-z_0-9]+\\]|)\\}\\}/g;\n var match, base, key, resolved_namespace;\n var replace = [];\n while ((match = re.exec(element)) !== null) {\n base = match[0];\n key = match[1].length ? match[1].replace(/(\\[|\\])/g, '') : null;\n resolved_namespace = default_namespace;\n if (namespace != null && typeof namespace == 'object' && typeof namespace[key] != 'undefined') {\n resolved_namespace = namespace[key] + (namespace[key].length ? ':' : '');\n }\n replace.push({\n base: base,\n namespace: resolved_namespace\n });\n }\n for (var r in replace) {\n element = element.replace(replace[r].base, replace[r].namespace);\n }\n } else if (typeof element == 'object' && element != null) {\n if (typeof element.namespace != 'undefined') {\n var merge_namespace = typeof element.namespace == 'string' ? { default: element.namespace } : element.namespace;\n namespace = LocusZoom.Layouts.merge(namespace, merge_namespace);\n }\n var namespaced_element, namespaced_property;\n for (var property in element) {\n if (property === 'namespace') {\n continue;\n }\n namespaced_element = applyNamespaces(element[property], namespace);\n namespaced_property = applyNamespaces(property, namespace);\n if (property !== namespaced_property) {\n delete element[property];\n }\n element[namespaced_property] = namespaced_element;\n }\n }\n return element;\n };\n layout = applyNamespaces(layout, layout.namespace);\n // Return the layout as valid JSON only\n return JSON.parse(JSON.stringify(layout));\n } else {\n throw new Error('layout type [' + type + '] name [' + name + '] not found');\n }\n };\n /** @private */\n obj.set = function (type, name, layout) {\n if (typeof type != 'string' || typeof name != 'string' || typeof layout != 'object') {\n throw new Error('unable to set new layout; bad arguments passed to set()');\n }\n if (!layouts[type]) {\n layouts[type] = {};\n }\n if (layout) {\n return layouts[type][name] = JSON.parse(JSON.stringify(layout));\n } else {\n delete layouts[type][name];\n return null;\n }\n };\n /**\n * Register a new layout definition by name.\n *\n * @param {string} type The type of layout to add. Usually, this will be one of the predefined LocusZoom types,\n * but if you pass a different name, this method will automatically create the new `type` bucket\n * @param {string} name The identifier of the newly added layout\n * @param {object} [layout] A JSON-serializable object containing configuration properties for this layout\n * @returns The JSON representation of the newly created layout\n */\n obj.add = function (type, name, layout) {\n return obj.set(type, name, layout);\n };\n /**\n * List all registered layouts\n * @param [type] Optionally narrow the list to only layouts of a specific type; else return all known layouts\n * @returns {*}\n */\n obj.list = function (type) {\n if (!layouts[type]) {\n var list = {};\n Object.keys(layouts).forEach(function (type) {\n list[type] = Object.keys(layouts[type]);\n });\n return list;\n } else {\n return Object.keys(layouts[type]);\n }\n };\n /**\n * A helper method used for merging two objects. If a key is present in both, takes the value from the first object\n * Values from `default_layout` will be cleanly copied over, ensuring no references or shared state.\n *\n * Frequently used for preparing custom layouts. Both objects should be JSON-serializable.\n *\n * @param {object} custom_layout An object containing configuration parameters that override or add to defaults\n * @param {object} default_layout An object containing default settings.\n * @returns {object} The custom layout is modified in place and also returned from this method.\n */\n obj.merge = function (custom_layout, default_layout) {\n if (typeof custom_layout !== 'object' || typeof default_layout !== 'object') {\n throw new Error('LocusZoom.Layouts.merge only accepts two layout objects; ' + typeof custom_layout + ', ' + typeof default_layout + ' given');\n }\n for (var property in default_layout) {\n if (!default_layout.hasOwnProperty(property)) {\n continue;\n }\n // Get types for comparison. Treat nulls in the custom layout as undefined for simplicity.\n // (javascript treats nulls as \"object\" when we just want to overwrite them as if they're undefined)\n // Also separate arrays from objects as a discrete type.\n var custom_type = custom_layout[property] === null ? 'undefined' : typeof custom_layout[property];\n var default_type = typeof default_layout[property];\n if (custom_type === 'object' && Array.isArray(custom_layout[property])) {\n custom_type = 'array';\n }\n if (default_type === 'object' && Array.isArray(default_layout[property])) {\n default_type = 'array';\n }\n // Unsupported property types: throw an exception\n if (custom_type === 'function' || default_type === 'function') {\n throw new Error('LocusZoom.Layouts.merge encountered an unsupported property type');\n }\n // Undefined custom value: pull the default value\n if (custom_type === 'undefined') {\n custom_layout[property] = JSON.parse(JSON.stringify(default_layout[property]));\n continue;\n }\n // Both values are objects: merge recursively\n if (custom_type === 'object' && default_type === 'object') {\n custom_layout[property] = LocusZoom.Layouts.merge(custom_layout[property], default_layout[property]);\n continue;\n }\n }\n return custom_layout;\n };\n return obj;\n }();\n /**\n * Tooltip Layouts\n * @namespace LocusZoom.Layouts.tooltips\n */\n LocusZoom.Layouts.add('tooltip', 'standard_association', {\n namespace: { 'assoc': 'assoc' },\n closable: true,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: '{{{{namespace[assoc]}}variant|htmlescape}}
' + 'P Value: {{{{namespace[assoc]}}log_pvalue|logtoscinotation|htmlescape}}
' + 'Ref. Allele: {{{{namespace[assoc]}}ref_allele|htmlescape}}
' + 'Make LD Reference
'\n });\n LocusZoom.Layouts.add('tooltip', 'covariates_model_association', function () {\n var covariates_model_association = LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true });\n covariates_model_association.html += 'Condition on Variant
';\n return covariates_model_association;\n }());\n LocusZoom.Layouts.add('tooltip', 'standard_genes', {\n closable: true,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: '

{{gene_name|htmlescape}}

' + 'Gene ID: {{gene_id|htmlescape}}
' + 'Transcript ID: {{transcript_id|htmlescape}}
' + 'More data on gnomAD'\n });\n LocusZoom.Layouts.add('tooltip', 'standard_intervals', {\n namespace: { 'intervals': 'intervals' },\n closable: false,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: '{{{{namespace[intervals]}}state_name|htmlescape}}
{{{{namespace[intervals]}}start|htmlescape}}-{{{{namespace[intervals]}}end|htmlescape}}'\n });\n LocusZoom.Layouts.add('tooltip', 'catalog_variant', {\n namespace: {\n 'assoc': 'assoc',\n 'catalog': 'catalog'\n },\n closable: true,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: '{{{{namespace[catalog]}}variant|htmlescape}}
' + 'Catalog entries: {{n_catalog_matches|htmlescape}}
' + 'Top Trait: {{{{namespace[catalog]}}trait|htmlescape}}
' + 'Top P Value: {{{{namespace[catalog]}}log_pvalue|logtoscinotation}}
' // User note: if a different catalog is used, the tooltip will need to be replaced with a different link URL\n+ 'More: GWAS catalog / dbSNP'\n });\n /**\n * Data Layer Layouts: represent specific information from a data source\n * @namespace Layouts.data_layer\n */\n LocusZoom.Layouts.add('data_layer', 'significance', {\n id: 'significance',\n type: 'orthogonal_line',\n orientation: 'horizontal',\n offset: LZ_SIG_THRESHOLD_LOGP\n });\n LocusZoom.Layouts.add('data_layer', 'recomb_rate', {\n namespace: { 'recomb': 'recomb' },\n id: 'recombrate',\n type: 'line',\n fields: [\n '{{namespace[recomb]}}position',\n '{{namespace[recomb]}}recomb_rate'\n ],\n z_index: 1,\n style: {\n 'stroke': '#0000FF',\n 'stroke-width': '1.5px'\n },\n x_axis: { field: '{{namespace[recomb]}}position' },\n y_axis: {\n axis: 2,\n field: '{{namespace[recomb]}}recomb_rate',\n floor: 0,\n ceiling: 100\n }\n });\n LocusZoom.Layouts.add('data_layer', 'association_pvalues', {\n namespace: {\n 'assoc': 'assoc',\n 'ld': 'ld'\n },\n id: 'associationpvalues',\n type: 'scatter',\n point_shape: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 'diamond',\n else: 'circle'\n }\n },\n point_size: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 80,\n else: 40\n }\n },\n color: [\n {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: '#9632b8'\n }\n },\n {\n scale_function: 'numerical_bin',\n field: '{{namespace[ld]}}state',\n parameters: {\n breaks: [\n 0,\n 0.2,\n 0.4,\n 0.6,\n 0.8\n ],\n values: [\n '#357ebd',\n '#46b8da',\n '#5cb85c',\n '#eea236',\n '#d43f3a'\n ]\n }\n },\n '#B8B8B8'\n ],\n legend: [\n {\n shape: 'diamond',\n color: '#9632b8',\n size: 40,\n label: 'LD Ref Var',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#d43f3a',\n size: 40,\n label: '1.0 > r\\xB2 \\u2265 0.8',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#eea236',\n size: 40,\n label: '0.8 > r\\xB2 \\u2265 0.6',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#5cb85c',\n size: 40,\n label: '0.6 > r\\xB2 \\u2265 0.4',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#46b8da',\n size: 40,\n label: '0.4 > r\\xB2 \\u2265 0.2',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#357ebd',\n size: 40,\n label: '0.2 > r\\xB2 \\u2265 0.0',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#B8B8B8',\n size: 40,\n label: 'no r\\xB2 data',\n class: 'lz-data_layer-scatter'\n }\n ],\n label: null,\n fields: [\n '{{namespace[assoc]}}variant',\n '{{namespace[assoc]}}position',\n '{{namespace[assoc]}}log_pvalue',\n '{{namespace[assoc]}}log_pvalue|logtoscinotation',\n '{{namespace[assoc]}}ref_allele',\n '{{namespace[ld]}}state',\n '{{namespace[ld]}}isrefvar'\n ],\n id_field: '{{namespace[assoc]}}variant',\n z_index: 2,\n x_axis: { field: '{{namespace[assoc]}}position' },\n y_axis: {\n axis: 1,\n field: '{{namespace[assoc]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.1,\n min_extent: [\n 0,\n 10\n ]\n },\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true })\n });\n LocusZoom.Layouts.add('data_layer', 'association_pvalues_catalog', function () {\n // Slightly modify an existing layout\n var l = LocusZoom.Layouts.get('data_layer', 'association_pvalues', {\n unnamespaced: true,\n id: 'associationpvaluescatalog',\n fill_opacity: 0.7\n });\n l.tooltip.html += '{{#if {{namespace[catalog]}}rsid}}
See hits in GWAS catalog{{/if}}';\n l.namespace.catalog = 'catalog';\n l.fields.push('{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait', '{{namespace[catalog]}}log_pvalue');\n return l;\n }());\n LocusZoom.Layouts.add('data_layer', 'phewas_pvalues', {\n namespace: { 'phewas': 'phewas' },\n id: 'phewaspvalues',\n type: 'category_scatter',\n point_shape: 'circle',\n point_size: 70,\n tooltip_positioning: 'vertical',\n id_field: '{{namespace[phewas]}}id',\n fields: [\n '{{namespace[phewas]}}id',\n '{{namespace[phewas]}}log_pvalue',\n '{{namespace[phewas]}}trait_group',\n '{{namespace[phewas]}}trait_label'\n ],\n x_axis: {\n field: '{{namespace[phewas]}}x',\n // Synthetic/derived field added by `category_scatter` layer\n category_field: '{{namespace[phewas]}}trait_group',\n lower_buffer: 0.025,\n upper_buffer: 0.025\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[phewas]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.15\n },\n color: [{\n field: '{{namespace[phewas]}}trait_group',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [],\n values: [],\n null_value: '#B8B8B8'\n }\n }],\n fill_opacity: 0.7,\n tooltip: {\n closable: true,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: [\n 'Trait: {{{{namespace[phewas]}}trait_label|htmlescape}}
',\n 'Trait Category: {{{{namespace[phewas]}}trait_group|htmlescape}}
',\n 'P-value: {{{{namespace[phewas]}}log_pvalue|logtoscinotation|htmlescape}}
'\n ].join('')\n },\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n label: {\n text: '{{{{namespace[phewas]}}trait_label|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [{\n field: '{{namespace[phewas]}}log_pvalue',\n operator: '>=',\n value: 20\n }],\n style: {\n 'font-size': '14px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n });\n LocusZoom.Layouts.add('data_layer', 'genes', {\n namespace: { 'gene': 'gene' },\n id: 'genes',\n type: 'genes',\n fields: ['{{namespace[gene]}}all'],\n id_field: 'gene_id',\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_genes', { unnamespaced: true })\n });\n LocusZoom.Layouts.add('data_layer', 'genome_legend', {\n namespace: { 'genome': 'genome' },\n id: 'genome_legend',\n type: 'genome_legend',\n fields: [\n '{{namespace[genome]}}chr',\n '{{namespace[genome]}}base_pairs'\n ],\n x_axis: {\n floor: 0,\n ceiling: 2881033286\n }\n });\n LocusZoom.Layouts.add('data_layer', 'intervals', {\n namespace: { 'intervals': 'intervals' },\n id: 'intervals',\n type: 'intervals',\n fields: [\n '{{namespace[intervals]}}start',\n '{{namespace[intervals]}}end',\n '{{namespace[intervals]}}state_id',\n '{{namespace[intervals]}}state_name'\n ],\n id_field: '{{namespace[intervals]}}start',\n start_field: '{{namespace[intervals]}}start',\n end_field: '{{namespace[intervals]}}end',\n track_split_field: '{{namespace[intervals]}}state_id',\n split_tracks: true,\n always_hide_legend: false,\n color: {\n field: '{{namespace[intervals]}}state_id',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13\n ],\n values: [\n 'rgb(212,63,58)',\n 'rgb(250,120,105)',\n 'rgb(252,168,139)',\n 'rgb(240,189,66)',\n 'rgb(250,224,105)',\n 'rgb(240,238,84)',\n 'rgb(244,252,23)',\n 'rgb(23,232,252)',\n 'rgb(32,191,17)',\n 'rgb(23,166,77)',\n 'rgb(32,191,17)',\n 'rgb(162,133,166)',\n 'rgb(212,212,212)'\n ],\n null_value: '#B8B8B8'\n }\n },\n legend: [\n {\n shape: 'rect',\n color: 'rgb(212,63,58)',\n width: 9,\n label: 'Active Promoter',\n '{{namespace[intervals]}}state_id': 1\n },\n {\n shape: 'rect',\n color: 'rgb(250,120,105)',\n width: 9,\n label: 'Weak Promoter',\n '{{namespace[intervals]}}state_id': 2\n },\n {\n shape: 'rect',\n color: 'rgb(252,168,139)',\n width: 9,\n label: 'Poised Promoter',\n '{{namespace[intervals]}}state_id': 3\n },\n {\n shape: 'rect',\n color: 'rgb(240,189,66)',\n width: 9,\n label: 'Strong enhancer',\n '{{namespace[intervals]}}state_id': 4\n },\n {\n shape: 'rect',\n color: 'rgb(250,224,105)',\n width: 9,\n label: 'Strong enhancer',\n '{{namespace[intervals]}}state_id': 5\n },\n {\n shape: 'rect',\n color: 'rgb(240,238,84)',\n width: 9,\n label: 'Weak enhancer',\n '{{namespace[intervals]}}state_id': 6\n },\n {\n shape: 'rect',\n color: 'rgb(244,252,23)',\n width: 9,\n label: 'Weak enhancer',\n '{{namespace[intervals]}}state_id': 7\n },\n {\n shape: 'rect',\n color: 'rgb(23,232,252)',\n width: 9,\n label: 'Insulator',\n '{{namespace[intervals]}}state_id': 8\n },\n {\n shape: 'rect',\n color: 'rgb(32,191,17)',\n width: 9,\n label: 'Transcriptional transition',\n '{{namespace[intervals]}}state_id': 9\n },\n {\n shape: 'rect',\n color: 'rgb(23,166,77)',\n width: 9,\n label: 'Transcriptional elongation',\n '{{namespace[intervals]}}state_id': 10\n },\n {\n shape: 'rect',\n color: 'rgb(136,240,129)',\n width: 9,\n label: 'Weak transcribed',\n '{{namespace[intervals]}}state_id': 11\n },\n {\n shape: 'rect',\n color: 'rgb(162,133,166)',\n width: 9,\n label: 'Polycomb-repressed',\n '{{namespace[intervals]}}state_id': 12\n },\n {\n shape: 'rect',\n color: 'rgb(212,212,212)',\n width: 9,\n label: 'Heterochromatin / low signal',\n '{{namespace[intervals]}}state_id': 13\n }\n ],\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_intervals', { unnamespaced: true })\n });\n LocusZoom.Layouts.add('data_layer', 'annotation_catalog', {\n // Identify GWAS hits that are present in the GWAS catalog\n namespace: {\n 'assoc': 'assoc',\n 'catalog': 'catalog'\n },\n id: 'annotation_catalog',\n type: 'annotation_track',\n id_field: '{{namespace[catalog]}}variant',\n x_axis: { field: '{{namespace[assoc]}}position' },\n color: '#0000CC',\n fields: [\n '{{namespace[assoc]}}variant',\n '{{namespace[assoc]}}chromosome',\n '{{namespace[assoc]}}position',\n '{{namespace[catalog]}}variant',\n '{{namespace[catalog]}}rsid',\n '{{namespace[catalog]}}trait',\n '{{namespace[catalog]}}log_pvalue',\n '{{namespace[catalog]}}pos'\n ],\n filters: [\n // Specify which points to show on the track. Any selection must satisfy ALL filters\n [\n '{{namespace[catalog]}}rsid',\n '!=',\n null\n ],\n [\n '{{namespace[catalog]}}log_pvalue',\n '>',\n LZ_SIG_THRESHOLD_LOGP\n ]\n ],\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'catalog_variant', { unnamespaced: true }),\n tooltip_positioning: 'top'\n });\n /**\n * Individual dashboard buttons\n * @namespace Layouts.dashboard_components\n */\n LocusZoom.Layouts.add('dashboard_components', 'ldlz2_pop_selector', {\n // **Note**: this widget is aimed at the LDLZ2 datasource, and the UM 1000G LDServer. Older LZ usages\n // (on the original LD data source) will not work with these population names.\n type: 'set_state',\n position: 'right',\n color: 'blue',\n button_html: 'LD Population: ',\n show_selected: true,\n button_title: 'Select LD Population: ',\n state_field: 'ld_pop',\n // This list below is hardcoded to work with the UMich LDServer, default 1000G populations\n // It can be customized to work with other LD servers that specify population differently\n // https://portaldev.sph.umich.edu/ld/genome_builds/GRCh37/references/1000G/populations\n options: [\n {\n display_name: 'ALL (default)',\n value: 'ALL'\n },\n {\n display_name: 'AFR',\n value: 'AFR'\n },\n {\n display_name: 'AMR',\n value: 'AMR'\n },\n {\n display_name: 'EAS',\n value: 'EAS'\n },\n {\n display_name: 'EUR',\n value: 'EUR'\n },\n {\n display_name: 'SAS',\n value: 'SAS'\n }\n ]\n });\n /**\n * Dashboard Layouts: Collections of toolbar buttons etc\n * @namespace Layouts.dashboard\n */\n LocusZoom.Layouts.add('dashboard', 'standard_panel', {\n components: [\n {\n type: 'remove_panel',\n position: 'right',\n color: 'red',\n group_position: 'end'\n },\n {\n type: 'move_panel_up',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'move_panel_down',\n position: 'right',\n group_position: 'start',\n style: { 'margin-left': '0.75em' }\n }\n ]\n });\n LocusZoom.Layouts.add('dashboard', 'standard_plot', {\n components: [\n {\n type: 'title',\n title: 'LocusZoom',\n subtitle: 'v' + LocusZoom.version + '',\n position: 'left'\n },\n {\n type: 'download',\n position: 'right'\n }\n ]\n });\n LocusZoom.Layouts.add('dashboard', 'covariates_model_plot', function () {\n var covariates_model_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n covariates_model_plot_dashboard.components.push({\n type: 'covariates_model',\n button_html: 'Model',\n button_title: 'Show and edit covariates currently in model',\n position: 'left'\n });\n return covariates_model_plot_dashboard;\n }());\n LocusZoom.Layouts.add('dashboard', 'region_nav_plot', function () {\n var region_nav_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n region_nav_plot_dashboard.components.push({\n type: 'shift_region',\n step: 500000,\n button_html: '>>',\n position: 'right',\n group_position: 'end'\n }, {\n type: 'shift_region',\n step: 50000,\n button_html: '>',\n position: 'right',\n group_position: 'middle'\n }, {\n type: 'zoom_region',\n step: 0.2,\n position: 'right',\n group_position: 'middle'\n }, {\n type: 'zoom_region',\n step: -0.2,\n position: 'right',\n group_position: 'middle'\n }, {\n type: 'shift_region',\n step: -50000,\n button_html: '<',\n position: 'right',\n group_position: 'middle'\n }, {\n type: 'shift_region',\n step: -500000,\n button_html: '<<',\n position: 'right',\n group_position: 'start'\n });\n return region_nav_plot_dashboard;\n }());\n /**\n * Panel Layouts\n * @namespace Layouts.panel\n */\n LocusZoom.Layouts.add('panel', 'association', {\n id: 'association',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 200,\n proportional_width: 1,\n margin: {\n top: 35,\n right: 50,\n bottom: 40,\n left: 50\n },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_legend',\n position: 'right'\n });\n return l;\n }(),\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n },\n y2: {\n label: 'Recombination Rate (cM/Mb)',\n label_offset: 40\n }\n },\n legend: {\n orientation: 'vertical',\n origin: {\n x: 55,\n y: 40\n },\n hidden: true\n },\n interaction: {\n drag_background_to_pan: true,\n drag_x_ticks_to_scale: true,\n drag_y1_ticks_to_scale: true,\n drag_y2_ticks_to_scale: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues', { unnamespaced: true })\n ]\n });\n LocusZoom.Layouts.add('panel', 'association_catalog', function () {\n var l = LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n id: 'associationcatalog',\n namespace: {\n 'assoc': 'assoc',\n 'ld': 'ld',\n 'catalog': 'catalog'\n } // Required to resolve display options\n });\n l.dashboard.components.push({\n type: 'display_options',\n position: 'right',\n color: 'blue',\n // Below: special config specific to this widget\n button_html: 'Display options...',\n button_title: 'Control how plot items are displayed',\n layer_name: 'associationpvaluescatalog',\n default_config_display_name: 'No catalog labels (default)',\n // display name for the default plot color option (allow user to revert to plot defaults)\n options: [{\n // First dropdown menu item\n display_name: 'Label catalog traits',\n // Human readable representation of field name\n display: {\n // Specify layout directives that control display of the plot for this option\n label: {\n text: '{{{{namespace[catalog]}}trait|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n // Only label points if they are significant for some trait in the catalog, AND in high LD\n // with the top hit of interest\n {\n field: '{{namespace[catalog]}}trait',\n operator: '!=',\n value: null\n },\n {\n field: '{{namespace[catalog]}}log_pvalue',\n operator: '>',\n value: LZ_SIG_THRESHOLD_LOGP\n },\n {\n field: '{{namespace[ld]}}state',\n operator: '>',\n value: 0.4\n }\n ],\n style: {\n 'font-size': '10px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n }\n }]\n });\n l.data_layers = [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues_catalog', { unnamespaced: true })\n ];\n return l;\n }());\n LocusZoom.Layouts.add('panel', 'genes', {\n id: 'genes',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 112.5,\n proportional_width: 1,\n margin: {\n top: 20,\n right: 50,\n bottom: 20,\n left: 50\n },\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n dashboard: function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'resize_to_data',\n position: 'right',\n button_html: 'Show all genes'\n });\n return l;\n }(),\n data_layers: [LocusZoom.Layouts.get('data_layer', 'genes', { unnamespaced: true })]\n });\n LocusZoom.Layouts.add('panel', 'phewas', {\n id: 'phewas',\n width: 800,\n height: 300,\n min_width: 800,\n min_height: 300,\n proportional_width: 1,\n margin: {\n top: 20,\n right: 50,\n bottom: 120,\n left: 50\n },\n inner_border: 'rgb(210, 210, 210)',\n axes: {\n x: {\n ticks: {\n // Object based config (shared defaults; allow layers to specify ticks)\n style: {\n 'font-weight': 'bold',\n 'font-size': '11px',\n 'text-anchor': 'start'\n },\n transform: 'rotate(50)',\n position: 'left' // Special param recognized by `category_scatter` layers\n }\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'phewas_pvalues', { unnamespaced: true })\n ]\n });\n LocusZoom.Layouts.add('panel', 'genome_legend', {\n id: 'genome_legend',\n width: 800,\n height: 50,\n origin: {\n x: 0,\n y: 300\n },\n min_width: 800,\n min_height: 50,\n proportional_width: 1,\n margin: {\n top: 0,\n right: 50,\n bottom: 35,\n left: 50\n },\n axes: {\n x: {\n label: 'Genomic Position (number denotes chromosome)',\n label_offset: 35,\n ticks: [\n {\n x: 124625310,\n text: '1',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 370850307,\n text: '2',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 591461209,\n text: '3',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 786049562,\n text: '4',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 972084330,\n text: '5',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1148099493,\n text: '6',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1313226358,\n text: '7',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1465977701,\n text: '8',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1609766427,\n text: '9',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1748140516,\n text: '10',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1883411148,\n text: '11',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2017840353,\n text: '12',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2142351240,\n text: '13',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2253610949,\n text: '14',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2358551415,\n text: '15',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2454994487,\n text: '16',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2540769469,\n text: '17',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2620405698,\n text: '18',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2689008813,\n text: '19',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2750086065,\n text: '20',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2805663772,\n text: '21',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2855381003,\n text: '22',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n }\n ]\n }\n },\n data_layers: [LocusZoom.Layouts.get('data_layer', 'genome_legend', { unnamespaced: true })]\n });\n LocusZoom.Layouts.add('panel', 'intervals', {\n id: 'intervals',\n width: 1000,\n height: 50,\n min_width: 500,\n min_height: 50,\n margin: {\n top: 25,\n right: 150,\n bottom: 5,\n left: 50\n },\n dashboard: function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_split_tracks',\n data_layer_id: 'intervals',\n position: 'right'\n });\n return l;\n }(),\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n legend: {\n hidden: true,\n orientation: 'horizontal',\n origin: {\n x: 50,\n y: 0\n },\n pad_from_bottom: 5\n },\n data_layers: [LocusZoom.Layouts.get('data_layer', 'intervals', { unnamespaced: true })]\n });\n LocusZoom.Layouts.add('panel', 'annotation_catalog', {\n id: 'annotationcatalog',\n width: 800,\n height: 50,\n min_height: 50,\n proportional_width: 1,\n margin: {\n top: 25,\n right: 50,\n bottom: 0,\n left: 50\n },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true }),\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [LocusZoom.Layouts.get('data_layer', 'annotation_catalog', { unnamespaced: true })]\n });\n /**\n * Plot Layouts\n * @namespace Layouts.plot\n */\n LocusZoom.Layouts.add('plot', 'standard_association', {\n state: {},\n width: 800,\n height: 450,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n proportional_height: 0.5\n }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true,\n proportional_height: 0.5\n })\n ]\n });\n LocusZoom.Layouts.add('plot', 'association_catalog', {\n state: {},\n width: 800,\n height: 500,\n responsive_resize: 'width_only',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'annotation_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'association_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true })\n ]\n });\n // Shortcut to \"StandardLayout\" for backward compatibility\n LocusZoom.StandardLayout = LocusZoom.Layouts.get('plot', 'standard_association');\n LocusZoom.Layouts.add('plot', 'standard_phewas', {\n width: 800,\n height: 600,\n min_width: 800,\n min_height: 600,\n responsive_resize: 'both',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'phewas', {\n unnamespaced: true,\n proportional_height: 0.45\n }),\n LocusZoom.Layouts.get('panel', 'genome_legend', {\n unnamespaced: true,\n proportional_height: 0.1\n }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true,\n proportional_height: 0.45,\n margin: { bottom: 40 },\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n }\n }\n })\n ],\n mouse_guide: false\n });\n LocusZoom.Layouts.add('plot', 'interval_association', {\n state: {},\n width: 800,\n height: 550,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n width: 800,\n proportional_height: 225 / 570\n }),\n LocusZoom.Layouts.get('panel', 'intervals', {\n unnamespaced: true,\n proportional_height: 120 / 570\n }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true,\n width: 800,\n proportional_height: 225 / 570\n })\n ]\n });\n /* global LocusZoom */\n 'use strict';\n /**\n * A data layer is an abstract class representing a data set and its graphical representation within a panel\n * @public\n * @class\n * @param {Object} layout A JSON-serializable object describing the layout for this layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n*/\n LocusZoom.DataLayer = function (layout, parent) {\n /** @member {Boolean} */\n this.initialized = false;\n /** @member {Number} */\n this.layout_idx = null;\n /** @member {String} */\n this.id = null;\n /** @member {LocusZoom.Panel} */\n this.parent = parent || null;\n /**\n * @member {{group: d3.selection, container: d3.selection, clipRect: d3.selection}}\n */\n this.svg = {};\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n if (typeof parent != 'undefined' && parent instanceof LocusZoom.Panel) {\n this.parent_plot = parent.parent;\n }\n /** @member {Object} */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.DataLayer.DefaultLayout);\n if (this.layout.id) {\n this.id = this.layout.id;\n }\n // Ensure any axes defined in the layout have an explicit axis number (default: 1)\n if (this.layout.x_axis !== {} && typeof this.layout.x_axis.axis !== 'number') {\n this.layout.x_axis.axis = 1;\n }\n if (this.layout.y_axis !== {} && typeof this.layout.y_axis.axis !== 'number') {\n this.layout.y_axis.axis = 1;\n }\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original data layer state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n /** @member {Object} */\n this.state = {};\n /** @member {String} */\n this.state_id = null;\n this.setDefaultState();\n // Initialize parameters for storing data and tool tips\n /** @member {Array} */\n this.data = [];\n if (this.layout.tooltip) {\n /** @member {Object} */\n this.tooltips = {};\n }\n // Initialize flags for tracking global statuses\n this.global_statuses = {\n 'highlighted': false,\n 'selected': false,\n 'faded': false,\n 'hidden': false\n };\n return this;\n };\n /**\n * Instruct this datalayer to begin tracking additional fields from data sources (does not guarantee that such a field actually exists)\n *\n * Custom plots can use this to dynamically extend datalayer functionality after the plot is drawn\n *\n * (since removing core fields may break layer functionality, there is presently no hook for the inverse behavior)\n * @param fieldName\n * @param namespace\n * @param {String|String[]} transformations The name (or array of names) of transformations to apply to this field\n * @returns {String} The raw string added to the fields array\n */\n LocusZoom.DataLayer.prototype.addField = function (fieldName, namespace, transformations) {\n if (!fieldName || !namespace) {\n throw new Error('Must specify field name and namespace to use when adding field');\n }\n var fieldString = namespace + ':' + fieldName;\n if (transformations) {\n fieldString += '|';\n if (typeof transformations === 'string') {\n fieldString += transformations;\n } else if (Array.isArray(transformations)) {\n fieldString += transformations.join('|');\n } else {\n throw new Error('Must provide transformations as either a string or array of strings');\n }\n }\n var fields = this.layout.fields;\n if (fields.indexOf(fieldString) === -1) {\n fields.push(fieldString);\n }\n return fieldString;\n };\n /**\n * Define default state that should get tracked during the lifetime of this layer.\n *\n * In some special custom usages, it may be useful to completely reset a panel (eg \"click for\n * genome region\" links), plotting new data that invalidates any previously tracked state. This hook makes it\n * possible to reset without destroying the panel entirely. It is used by `Plot.clearPanelData`.\n */\n LocusZoom.DataLayer.prototype.setDefaultState = function () {\n // Define state parameters specific to this data layer. Within plot state, this will live under a key\n // `panel_name.layer_name`.\n if (this.parent) {\n this.state = this.parent.state;\n this.state_id = this.parent.id + '.' + this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n var layer_state = this.state[this.state_id];\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function (status) {\n layer_state[status] = layer_state[status] || [];\n });\n // Also initialize \"internal-only\" state fields\n layer_state['has_tooltip'] = layer_state['has_tooltip'] || [];\n }\n };\n /**\n * A basic description of keys expected in a layout. Not intended to be directly used or modified by an end user.\n * @protected\n * @type {{type: string, fields: Array, x_axis: {}, y_axis: {}}}\n */\n LocusZoom.DataLayer.DefaultLayout = {\n type: '',\n fields: [],\n x_axis: {},\n y_axis: {}\n };\n /**\n * Available statuses that individual elements can have. Each status is described by\n * a verb/antiverb and an adjective. Verbs and antiverbs are used to generate data layer\n * methods for updating the status on one or more elements. Adjectives are used in class\n * names and applied or removed from elements to have a visual representation of the status,\n * as well as used as keys in the state for tracking which elements are in which status(es)\n * @static\n * @type {{verbs: String[], adjectives: String[], menu_antiverbs: String[]}}\n */\n LocusZoom.DataLayer.Statuses = {\n verbs: [\n 'highlight',\n 'select',\n 'fade',\n 'hide'\n ],\n adjectives: [\n 'highlighted',\n 'selected',\n 'faded',\n 'hidden'\n ],\n menu_antiverbs: [\n 'unhighlight',\n 'deselect',\n 'unfade',\n 'show'\n ]\n };\n /**\n * Get the fully qualified identifier for the data layer, prefixed by any parent or container elements\n *\n * @returns {string} A dot-delimited string of the format ..\n */\n LocusZoom.DataLayer.prototype.getBaseId = function () {\n return this.parent_plot.id + '.' + this.parent.id + '.' + this.id;\n };\n /**\n * Determine the pixel height of data-bound objects represented inside this data layer. (excluding elements such as axes)\n *\n * May be used by operations that resize the data layer to fit available data\n *\n * @public\n * @returns {number}\n */\n LocusZoom.DataLayer.prototype.getAbsoluteDataHeight = function () {\n var dataBCR = this.svg.group.node().getBoundingClientRect();\n return dataBCR.height;\n };\n /**\n * Whether transitions can be applied to this data layer\n * @returns {boolean}\n */\n LocusZoom.DataLayer.prototype.canTransition = function () {\n if (!this.layout.transition) {\n return false;\n }\n return !(this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.panel_id);\n };\n /**\n * Fetch the fully qualified ID to be associated with a specific visual element, based on the data to which that\n * element is bound. In general this element ID will be unique, allowing it to be addressed directly via selectors.\n * @param {String|Object} element\n * @returns {String}\n */\n LocusZoom.DataLayer.prototype.getElementId = function (element) {\n var element_id = 'element';\n if (typeof element == 'string') {\n element_id = element;\n } else if (typeof element == 'object') {\n var id_field = this.layout.id_field || 'id';\n if (typeof element[id_field] == 'undefined') {\n throw new Error('Unable to generate element ID');\n }\n element_id = element[id_field].toString().replace(/\\W/g, '');\n }\n return (this.getBaseId() + '-' + element_id).replace(/([:.[\\],])/g, '_');\n };\n /**\n * Fetch an ID that may bind a data element to a separate visual node for displaying status\n * Examples of this might be seperate visual nodes to show select/highlight statuses, or\n * even a common/shared node to show status across many elements in a set.\n * Abstract method. It should be overridden by data layers that implement seperate status\n * nodes specifically to the use case of the data layer type.\n * @param {String|Object} element\n * @returns {String|null}\n */\n LocusZoom.DataLayer.prototype.getElementStatusNodeId = function (element) {\n return null;\n };\n /**\n * Returns a reference to the underlying data associated with a single visual element in the data layer, as\n * referenced by the unique identifier for the element\n\n * @param {String} id The unique identifier for the element, as defined by `getElementId`\n * @returns {Object|null} The data bound to that element\n */\n LocusZoom.DataLayer.prototype.getElementById = function (id) {\n var selector = d3.select('#' + id.replace(/([:.[\\],])/g, '\\\\$1'));\n // escape special characters\n if (!selector.empty() && selector.data() && selector.data().length) {\n return selector.data()[0];\n } else {\n return null;\n }\n };\n /**\n * Basic method to apply arbitrary methods and properties to data elements.\n * This is called on all data immediately after being fetched.\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.applyDataMethods = function () {\n var field_to_match = this.layout.match && this.layout.match.receive;\n var broadcast_value = this.parent_plot.state.lz_match_value;\n this.data.forEach(function (d, i) {\n // Basic toHTML() method - return the stringified value in the id_field, if defined.\n // When this layer receives data, mark whether points match (via a synthetic boolean field)\n // Any field-based layout directives (color, size, shape) can then be used to control display\n if (field_to_match && broadcast_value !== null && broadcast_value !== undefined) {\n d.lz_highlight_match = d[field_to_match] === broadcast_value;\n }\n this.data[i].toHTML = function () {\n var id_field = this.layout.id_field || 'id';\n var html = '';\n if (this.data[i][id_field]) {\n html = this.data[i][id_field].toString();\n }\n return html;\n }.bind(this);\n // getDataLayer() method - return a reference to the data layer\n this.data[i].getDataLayer = function () {\n return this;\n }.bind(this);\n // deselect() method - shortcut method to deselect the element\n this.data[i].deselect = function () {\n var data_layer = this.getDataLayer();\n data_layer.unselectElement(this);\n };\n }.bind(this));\n this.applyCustomDataMethods();\n return this;\n };\n /**\n * Hook that allows custom datalayers to apply additional methods and properties to data elements as needed\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.applyCustomDataMethods = function () {\n return this;\n };\n /**\n * Initialize a data layer\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.initialize = function () {\n // Append a container group element to house the main data layer group element and the clip path\n this.svg.container = this.parent.svg.group.append('g').attr('class', 'lz-data_layer-container').attr('id', this.getBaseId() + '.data_layer_container');\n // Append clip path to the container element\n this.svg.clipRect = this.svg.container.append('clipPath').attr('id', this.getBaseId() + '.clip').append('rect');\n // Append svg group for rendering all data layer elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g').attr('id', this.getBaseId() + '.data_layer').attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n return this;\n };\n /**\n * Move a data layer up relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.moveUp = function () {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n };\n /**\n * Move a data layer down relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.moveDown = function () {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n };\n /**\n * Apply scaling functions to an element or parameter as needed, based on its layout and the element's data\n * If the layout parameter is already a primitive type, simply return the value as given\n * @param {Array|Number|String|Object} layout\n * @param {*} data The value to be used with the filter\n * @returns {*} The transformed value\n */\n LocusZoom.DataLayer.prototype.resolveScalableParameter = function (layout, data) {\n var ret = null;\n if (Array.isArray(layout)) {\n var idx = 0;\n while (ret === null && idx < layout.length) {\n ret = this.resolveScalableParameter(layout[idx], data);\n idx++;\n }\n } else {\n switch (typeof layout) {\n case 'number':\n case 'string':\n ret = layout;\n break;\n case 'object':\n if (layout.scale_function) {\n if (layout.field) {\n var f = new LocusZoom.Data.Field(layout.field);\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, f.resolve(data));\n } else {\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, data);\n }\n }\n break;\n }\n }\n return ret;\n };\n /**\n * Implementation hook for fetching the min and max values of available data. Used to determine axis range, if no other\n * explicit axis settings override. Useful for data layers where the data extent depends on more than one field.\n * (eg confidence intervals in a forest plot)\n * @param data\n * @param axis_config The configuration object for the specified axis.\n * @returns {Array} [min, max] without any padding applied\n * @private\n */\n LocusZoom.DataLayer.prototype._getDataExtent = function (data, axis_config) {\n data = data || this.data;\n // By default this depends only on a single field.\n return d3.extent(data, function (d) {\n var f = new LocusZoom.Data.Field(axis_config.field);\n return +f.resolve(d);\n });\n };\n /**\n * Generate dimension extent function based on layout parameters\n * @param {('x'|'y')} dimension\n */\n LocusZoom.DataLayer.prototype.getAxisExtent = function (dimension) {\n if ([\n 'x',\n 'y'\n ].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier passed to LocusZoom.DataLayer.getAxisExtent()');\n }\n var axis_name = dimension + '_axis';\n var axis_layout = this.layout[axis_name];\n // If a floor AND a ceiling are explicitly defined then just return that extent and be done\n if (!isNaN(axis_layout.floor) && !isNaN(axis_layout.ceiling)) {\n return [\n +axis_layout.floor,\n +axis_layout.ceiling\n ];\n }\n // If a field is defined for the axis and the data layer has data then generate the extent from the data set\n var data_extent = [];\n if (axis_layout.field && this.data) {\n if (!this.data.length) {\n // If data has been fetched (but no points in region), enforce the min_extent (with no buffers,\n // because we don't need padding around an empty screen)\n data_extent = axis_layout.min_extent || [];\n return data_extent;\n } else {\n data_extent = this._getDataExtent(this.data, axis_layout);\n // Apply upper/lower buffers, if applicable\n var original_extent_span = data_extent[1] - data_extent[0];\n if (!isNaN(axis_layout.lower_buffer)) {\n data_extent[0] -= original_extent_span * axis_layout.lower_buffer;\n }\n if (!isNaN(axis_layout.upper_buffer)) {\n data_extent[1] += original_extent_span * axis_layout.upper_buffer;\n }\n if (typeof axis_layout.min_extent == 'object') {\n // The data should span at least the range specified by min_extent, an array with [low, high]\n var range_min = axis_layout.min_extent[0];\n var range_max = axis_layout.min_extent[1];\n if (!isNaN(range_min) && !isNaN(range_max)) {\n data_extent[0] = Math.min(data_extent[0], range_min);\n }\n if (!isNaN(range_max)) {\n data_extent[1] = Math.max(data_extent[1], range_max);\n }\n }\n // If specified, floor and ceiling will override the actual data range\n return [\n isNaN(axis_layout.floor) ? data_extent[0] : axis_layout.floor,\n isNaN(axis_layout.ceiling) ? data_extent[1] : axis_layout.ceiling\n ];\n }\n }\n // If this is for the x axis and no extent could be generated yet but state has a defined start and end\n // then default to using the state-defined region as the extent\n if (dimension === 'x' && !isNaN(this.state.start) && !isNaN(this.state.end)) {\n return [\n this.state.start,\n this.state.end\n ];\n }\n // No conditions met for generating a valid extent, return an empty array\n return [];\n };\n /**\n * Allow this data layer to tell the panel what axis ticks it thinks it will require. The panel may choose whether\n * to use some, all, or none of these when rendering, either alone or in conjunction with other data layers.\n *\n * This method is a stub and should be overridden in data layers that need to specify custom behavior.\n *\n * @param {('x'|'y1'|'y2')} dimension\n * @param {Object} [config] Additional parameters for the panel to specify how it wants ticks to be drawn. The names\n * and meanings of these parameters may vary between different data layers.\n * @returns {Object[]}\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\n LocusZoom.DataLayer.prototype.getTicks = function (dimension, config) {\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier at layer level' + dimension);\n }\n return [];\n };\n /**\n * Generate a tool tip for a given element\n * @param {String|Object} data Data for the element associated with the tooltip\n */\n LocusZoom.DataLayer.prototype.createTooltip = function (data) {\n if (typeof this.layout.tooltip != 'object') {\n throw new Error('DataLayer [' + this.id + '] layout does not define a tooltip');\n }\n var id = this.getElementId(data);\n if (this.tooltips[id]) {\n this.positionTooltip(id);\n return;\n }\n this.tooltips[id] = {\n data: data,\n arrow: null,\n selector: d3.select(this.parent_plot.svg.node().parentNode).append('div').attr('class', 'lz-data_layer-tooltip').attr('id', id + '-tooltip')\n };\n this.state[this.state_id]['has_tooltip'].push(id);\n this.updateTooltip(data);\n return this;\n };\n /**\n * Update a tool tip (generate its inner HTML)\n * @param {String|Object} d The element associated with the tooltip\n * @param {String} [id] An identifier to the tooltip\n */\n LocusZoom.DataLayer.prototype.updateTooltip = function (d, id) {\n if (typeof id == 'undefined') {\n id = this.getElementId(d);\n }\n // Empty the tooltip of all HTML (including its arrow!)\n this.tooltips[id].selector.html('');\n this.tooltips[id].arrow = null;\n // Set the new HTML\n if (this.layout.tooltip.html) {\n this.tooltips[id].selector.html(LocusZoom.parseFields(d, this.layout.tooltip.html));\n }\n // If the layout allows tool tips on this data layer to be closable then add the close button\n // and add padding to the tooltip to accommodate it\n if (this.layout.tooltip.closable) {\n this.tooltips[id].selector.insert('button', ':first-child').attr('class', 'lz-tooltip-close-button').attr('title', 'Close').text('\\xD7').on('click', function () {\n this.destroyTooltip(id);\n }.bind(this));\n }\n // Apply data directly to the tool tip for easier retrieval by custom UI elements inside the tool tip\n this.tooltips[id].selector.data([d]);\n // Reposition and draw a new arrow\n this.positionTooltip(id);\n return this;\n };\n /**\n * Destroy tool tip - remove the tool tip element from the DOM and delete the tool tip's record on the data layer\n * @param {String|Object} element_or_id The element (or id) associated with the tooltip\n * @param {boolean} [temporary=false] Whether this is temporary (not to be tracked in state). Differentiates\n * \"recreate tooltips on re-render\" (which is temporary) from \"user has closed this tooltip\" (permanent)\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.destroyTooltip = function (element_or_id, temporary) {\n var id;\n if (typeof element_or_id == 'string') {\n id = element_or_id;\n } else {\n id = this.getElementId(element_or_id);\n }\n if (this.tooltips[id]) {\n if (typeof this.tooltips[id].selector == 'object') {\n this.tooltips[id].selector.remove();\n }\n delete this.tooltips[id];\n }\n // When a tooltip is removed, also remove the reference from the state\n if (!temporary) {\n var state = this.state[this.state_id]['has_tooltip'];\n var label_mark_position = state.indexOf(id);\n state.splice(label_mark_position, 1);\n }\n return this;\n };\n /**\n * Loop through and destroy all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.destroyAllTooltips = function () {\n for (var id in this.tooltips) {\n this.destroyTooltip(id, true);\n }\n return this;\n };\n //\n /**\n * Position tool tip - naïve function to place a tool tip to the lower right of the current mouse element\n * Most data layers reimplement this method to position tool tips specifically for the data they display\n * @param {String} id The identifier of the tooltip to position\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n // Position the div itself\n this.tooltips[id].selector.style('left', d3.event.pageX + 'px').style('top', d3.event.pageY + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!this.tooltips[id].arrow) {\n this.tooltips[id].arrow = this.tooltips[id].selector.append('div').style('position', 'absolute').attr('class', 'lz-data_layer-tooltip-arrow_top_left');\n }\n this.tooltips[id].arrow.style('left', '-1px').style('top', '-1px');\n return this;\n };\n /**\n * Loop through and position all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.positionAllTooltips = function () {\n for (var id in this.tooltips) {\n this.positionTooltip(id);\n }\n return this;\n };\n /**\n * Show or hide a tool tip by ID depending on directives in the layout and state values relative to the ID\n * @param {String|Object} element The element associated with the tooltip\n * @param {boolean} first_time Because panels can re-render, the rules for showing a tooltip\n * depend on whether this is the first time a status change affecting display has been applied.\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.showOrHideTooltip = function (element, first_time) {\n if (typeof this.layout.tooltip != 'object') {\n return;\n }\n var id = this.getElementId(element);\n /**\n * Apply rules and decide whether to show or hide the tooltip\n * @param {Object} statuses All statuses that apply to an element\n * @param {String[]|object} directive A layout directive object\n * @param operator\n * @returns {null|bool}\n */\n var resolveStatus = function (statuses, directive, operator) {\n var status = null;\n if (typeof statuses != 'object' || statuses === null) {\n return null;\n }\n if (Array.isArray(directive)) {\n // This happens when the function is called on the inner part of the directive\n operator = operator || 'and';\n if (directive.length === 1) {\n status = statuses[directive[0]];\n } else {\n status = directive.reduce(function (previousValue, currentValue) {\n if (operator === 'and') {\n return statuses[previousValue] && statuses[currentValue];\n } else if (operator === 'or') {\n return statuses[previousValue] || statuses[currentValue];\n }\n return null;\n });\n }\n } else if (typeof directive == 'object') {\n var sub_status;\n for (var sub_operator in directive) {\n sub_status = resolveStatus(statuses, directive[sub_operator], sub_operator);\n if (status === null) {\n status = sub_status;\n } else if (operator === 'and') {\n status = status && sub_status;\n } else if (operator === 'or') {\n status = status || sub_status;\n }\n }\n } else {\n return false;\n }\n return status;\n };\n var show_directive = {};\n if (typeof this.layout.tooltip.show == 'string') {\n show_directive = { and: [this.layout.tooltip.show] };\n } else if (typeof this.layout.tooltip.show == 'object') {\n show_directive = this.layout.tooltip.show;\n }\n var hide_directive = {};\n if (typeof this.layout.tooltip.hide == 'string') {\n hide_directive = { and: [this.layout.tooltip.hide] };\n } else if (typeof this.layout.tooltip.hide == 'object') {\n hide_directive = this.layout.tooltip.hide;\n }\n // Find all the statuses that apply to just this single element\n var layer_state = this.state[this.state_id];\n var statuses = {};\n // {status_name: bool}\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function (status) {\n var antistatus = 'un' + status;\n statuses[status] = layer_state[status].indexOf(id) !== -1;\n statuses[antistatus] = !statuses[status];\n });\n // Decide whether to show/hide the tooltip based solely on the underlying element\n var show_resolved = resolveStatus(statuses, show_directive);\n var hide_resolved = resolveStatus(statuses, hide_directive);\n // Most of the tooltip display logic depends on behavior layouts: was point (un)selected, (un)highlighted, etc.\n // But sometimes, a point is selected, and the user then closes the tooltip. If the panel is re-rendered for\n // some outside reason (like state change), we must track this in the create/destroy events as tooltip state.\n var has_tooltip = layer_state['has_tooltip'].indexOf(id) !== -1;\n var tooltip_was_closed = first_time ? false : !has_tooltip;\n if (show_resolved && !tooltip_was_closed && !hide_resolved) {\n this.createTooltip(element);\n } else {\n this.destroyTooltip(element);\n }\n return this;\n };\n /**\n * Find the elements (or indices) that match any of a set of provided filters\n * @protected\n * @param {Array[]} filters A list of filter entries: [field, value] (for equivalence testing) or\n * [field, operator, value] for other operators\n * @param {('indexes'|'elements')} [return_type='indexes'] Specify whether to return either the indices of the matching\n * elements, or references to the elements themselves\n * @returns {Array}\n */\n LocusZoom.DataLayer.prototype.filter = function (filters, return_type) {\n if (typeof return_type == 'undefined' || [\n 'indexes',\n 'elements'\n ].indexOf(return_type) === -1) {\n return_type = 'indexes';\n }\n if (!Array.isArray(filters)) {\n return [];\n }\n var test = function (element, filter) {\n var operators = {\n '=': function (a, b) {\n return a === b;\n },\n // eslint-disable-next-line eqeqeq\n '!=': function (a, b) {\n return a != b;\n },\n // For absence of a value, deliberately allow weak comparisons (eg undefined/null)\n '<': function (a, b) {\n return a < b;\n },\n '<=': function (a, b) {\n return a <= b;\n },\n '>': function (a, b) {\n return a > b;\n },\n '>=': function (a, b) {\n return a >= b;\n },\n '%': function (a, b) {\n return a % b;\n }\n };\n if (!Array.isArray(filter)) {\n return false;\n }\n if (filter.length === 2) {\n return element[filter[0]] === filter[1];\n } else if (filter.length === 3 && operators[filter[1]]) {\n return operators[filter[1]](element[filter[0]], filter[2]);\n } else {\n return false;\n }\n };\n var matches = [];\n this.data.forEach(function (element, idx) {\n var match = true;\n filters.forEach(function (filter) {\n if (!test(element, filter)) {\n match = false;\n }\n });\n if (match) {\n matches.push(return_type === 'indexes' ? idx : element);\n }\n });\n return matches;\n };\n /**\n * @param filters\n * @returns {Array}\n */\n LocusZoom.DataLayer.prototype.filterIndexes = function (filters) {\n return this.filter(filters, 'indexes');\n };\n /**\n * @param filters\n * @returns {Array}\n */\n LocusZoom.DataLayer.prototype.filterElements = function (filters) {\n return this.filter(filters, 'elements');\n };\n LocusZoom.DataLayer.Statuses.verbs.forEach(function (verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset a single element's status\n // TODO: Improve documentation for dynamically generated methods/properties\n LocusZoom.DataLayer.prototype[verb + 'Element'] = function (element, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n this.setElementStatus(adjective, element, true, exclusive);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'Element'] = function (element, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n this.setElementStatus(adjective, element, false, exclusive);\n return this;\n };\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.DataLayer.prototype[verb + 'ElementsByFilters'] = function (filters, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.DataLayer.prototype[antiverb + 'ElementsByFilters'] = function (filters, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.DataLayer.prototype[verb + 'AllElements'] = function () {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'AllElements'] = function () {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n });\n /**\n * Toggle a status (e.g. highlighted, selected, identified) on an element\n * @param {String} status The name of a recognized status to be added/removed on an appropriate element\n * @param {String|Object} element The data bound to the element of interest\n * @param {Boolean} active True to add the status (and associated CSS styles); false to remove it\n * @param {Boolean} exclusive Whether to only allow a state for a single element at a time\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.setElementStatus = function (status, element, active, exclusive) {\n if (status === 'has_tooltip') {\n // This is a special adjective that exists solely to track tooltip state. It has no CSS and never gets set\n // directly. It is invisible to the official enums.\n return this;\n }\n // Sanity checks\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatus()');\n }\n if (typeof element == 'undefined') {\n throw new Error('Invalid element passed to DataLayer.setElementStatus()');\n }\n if (typeof active == 'undefined') {\n active = true;\n }\n // Get an ID for the element or return having changed nothing\n try {\n var element_id = this.getElementId(element);\n } catch (get_element_id_error) {\n return this;\n }\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !active);\n }\n // Set/unset the proper status class on the appropriate DOM element(s)\n d3.select('#' + element_id).classed('lz-data_layer-' + this.layout.type + '-' + status, active);\n var element_status_node_id = this.getElementStatusNodeId(element);\n if (element_status_node_id !== null) {\n d3.select('#' + element_status_node_id).classed('lz-data_layer-' + this.layout.type + '-statusnode-' + status, active);\n }\n // Track element ID in the proper status state array\n var element_status_idx = this.state[this.state_id][status].indexOf(element_id);\n var added_status = element_status_idx === -1;\n // On a re-render, existing statuses will be reapplied.\n if (active && added_status) {\n this.state[this.state_id][status].push(element_id);\n }\n if (!active && !added_status) {\n this.state[this.state_id][status].splice(element_status_idx, 1);\n }\n // Trigger tool tip show/hide logic\n this.showOrHideTooltip(element, added_status);\n // Trigger layout changed event hook\n if (added_status) {\n this.parent.emit('layout_changed', true);\n }\n var is_selected = status === 'selected';\n if (is_selected && (added_status || !active)) {\n // Notify parents that an element has changed selection status (either active, or inactive)\n this.parent.emit('element_selection', {\n element: element,\n active: active\n }, true);\n }\n var value_to_broadcast = this.layout.match && this.layout.match.send;\n if (is_selected && value_to_broadcast && (added_status || !active)) {\n this.parent.emit('match_requested', {\n value: element[value_to_broadcast],\n active: active\n }, true);\n }\n return this;\n };\n /**\n * Toggle a status on elements in the data layer based on a set of filters\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.setElementStatusByFilters = function (status, toggle, filters, exclusive) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatusByFilters()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') {\n return this;\n }\n if (typeof toggle == 'undefined') {\n toggle = true;\n } else {\n toggle = !!toggle;\n }\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n if (!Array.isArray(filters)) {\n filters = [];\n }\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !toggle);\n }\n // Apply statuses\n this.filterElements(filters).forEach(function (element) {\n this.setElementStatus(status, element, toggle);\n }.bind(this));\n return this;\n };\n /**\n * Toggle a status on all elements in the data layer\n * @param {String} status\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.setAllElementStatus = function (status, toggle) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') {\n return this;\n }\n if (typeof toggle == 'undefined') {\n toggle = true;\n }\n // Apply statuses\n if (toggle) {\n this.data.forEach(function (element) {\n this.setElementStatus(status, element, true);\n }.bind(this));\n } else {\n var status_ids = this.state[this.state_id][status].slice();\n status_ids.forEach(function (id) {\n var element = this.getElementById(id);\n if (typeof element == 'object' && element !== null) {\n this.setElementStatus(status, element, false);\n }\n }.bind(this));\n this.state[this.state_id][status] = [];\n }\n // Update global status flag\n this.global_statuses[status] = toggle;\n return this;\n };\n /**\n * Apply all layout-defined behaviors (DOM event handlers) to a selection of elements\n * @param {d3.selection} selection\n */\n LocusZoom.DataLayer.prototype.applyBehaviors = function (selection) {\n if (typeof this.layout.behaviors != 'object') {\n return;\n }\n Object.keys(this.layout.behaviors).forEach(function (directive) {\n var event_match = /(click|mouseover|mouseout)/.exec(directive);\n if (!event_match) {\n return;\n }\n selection.on(event_match[0] + '.' + directive, this.executeBehaviors(directive, this.layout.behaviors[directive]));\n }.bind(this));\n };\n /**\n * Generate a function that executes an arbitrary list of behaviors on an element during an event\n * @param {String} directive The name of the event, as described in layout.behaviors for this datalayer\n * @param {Object} behaviors An object describing the behavior to attach to this single element\n * @param {string} behaviors.action The name of the action that would trigger this behavior (eg click, mouseover, etc)\n * @param {string} behaviors.status What status to apply to the element when this behavior is triggered (highlighted,\n * selected, etc)\n * @param {string} [behaviors.exclusive] Whether triggering the event for this element should unset the relevant status\n * for all other elements. Useful for, eg, click events that exclusively highlight one thing.\n * @returns {function(this:LocusZoom.DataLayer)} Return a function that handles the event in context with the behavior\n * and the element- can be attached as an event listener\n */\n LocusZoom.DataLayer.prototype.executeBehaviors = function (directive, behaviors) {\n // Determine the required state of control and shift keys during the event\n var requiredKeyStates = {\n 'ctrl': directive.indexOf('ctrl') !== -1,\n 'shift': directive.indexOf('shift') !== -1\n };\n return function (element) {\n // Do nothing if the required control and shift key presses (or lack thereof) doesn't match the event\n if (requiredKeyStates.ctrl !== !!d3.event.ctrlKey || requiredKeyStates.shift !== !!d3.event.shiftKey) {\n return;\n }\n // Loop through behaviors making each one go in succession\n behaviors.forEach(function (behavior) {\n // Route first by the action, if defined\n if (typeof behavior != 'object' || behavior === null) {\n return;\n }\n switch (behavior.action) {\n // Set a status (set to true regardless of current status, optionally with exclusivity)\n case 'set':\n this.setElementStatus(behavior.status, element, true, behavior.exclusive);\n break;\n // Unset a status (set to false regardless of current status, optionally with exclusivity)\n case 'unset':\n this.setElementStatus(behavior.status, element, false, behavior.exclusive);\n break;\n // Toggle a status\n case 'toggle':\n var current_status_boolean = this.state[this.state_id][behavior.status].indexOf(this.getElementId(element)) !== -1;\n var exclusive = behavior.exclusive && !current_status_boolean;\n this.setElementStatus(behavior.status, element, !current_status_boolean, exclusive);\n break;\n // Link to a dynamic URL\n case 'link':\n if (typeof behavior.href == 'string') {\n var url = LocusZoom.parseFields(element, behavior.href);\n if (typeof behavior.target == 'string') {\n window.open(url, behavior.target);\n } else {\n window.location.href = url;\n }\n }\n break;\n // Action not defined, just return\n default:\n break;\n }\n return;\n }.bind(this));\n }.bind(this);\n };\n /**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\n LocusZoom.DataLayer.prototype.getPageOrigin = function () {\n var panel_origin = this.parent.getPageOrigin();\n return {\n x: panel_origin.x + this.parent.layout.margin.left,\n y: panel_origin.y + this.parent.layout.margin.top\n };\n };\n /**\n * Get a data layer's current underlying data in a standard format (e.g. JSON or CSV)\n * @param {('csv'|'tsv'|'json')} format How to export the data\n * @returns {*}\n */\n LocusZoom.DataLayer.prototype.exportData = function (format) {\n var default_format = 'json';\n format = format || default_format;\n format = typeof format == 'string' ? format.toLowerCase() : default_format;\n if ([\n 'json',\n 'csv',\n 'tsv'\n ].indexOf(format) === -1) {\n format = default_format;\n }\n var ret;\n switch (format) {\n case 'json':\n try {\n ret = JSON.stringify(this.data);\n } catch (e) {\n ret = null;\n console.warn('Unable to export JSON data from data layer: ' + this.getBaseId());\n console.error(e);\n }\n break;\n case 'tsv':\n case 'csv':\n try {\n var jsonified = JSON.parse(JSON.stringify(this.data));\n if (typeof jsonified != 'object') {\n ret = jsonified.toString();\n } else if (!Array.isArray(jsonified)) {\n ret = 'Object';\n } else {\n var delimiter = format === 'tsv' ? '\\t' : ',';\n var header = this.layout.fields.map(function (header) {\n return JSON.stringify(header);\n }).join(delimiter) + '\\n';\n ret = header + jsonified.map(function (record) {\n return this.layout.fields.map(function (field) {\n if (typeof record[field] == 'undefined') {\n return JSON.stringify(null);\n } else if (typeof record[field] == 'object' && record[field] !== null) {\n return Array.isArray(record[field]) ? '\"[Array(' + record[field].length + ')]\"' : '\"[Object]\"';\n } else {\n return JSON.stringify(record[field]);\n }\n }).join(delimiter);\n }.bind(this)).join('\\n');\n }\n } catch (e) {\n ret = null;\n console.error('Unable to export CSV data from data layer: ' + this.getBaseId() + ';', e);\n }\n break;\n }\n return ret;\n };\n /**\n * Position the datalayer and all tooltips\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.draw = function () {\n this.svg.container.attr('transform', 'translate(' + this.parent.layout.cliparea.origin.x + ',' + this.parent.layout.cliparea.origin.y + ')');\n this.svg.clipRect.attr('width', this.parent.layout.cliparea.width).attr('height', this.parent.layout.cliparea.height);\n this.positionAllTooltips();\n return this;\n };\n /**\n * Re-Map a data layer to reflect changes in the state of a plot (such as viewing region/ chromosome range)\n * @return {Promise}\n */\n LocusZoom.DataLayer.prototype.reMap = function () {\n this.destroyAllTooltips();\n // hack - only non-visible tooltips should be destroyed\n // and then recreated if returning to visibility\n // Fetch new data. Datalayers are only given access to the final consolidated data from the chain (not headers or raw payloads)\n var promise = this.parent_plot.lzd.getData(this.state, this.layout.fields);\n promise.then(function (new_data) {\n this.data = new_data.body;\n this.applyDataMethods();\n this.initialized = true;\n }.bind(this));\n return promise;\n };\n /**\n * The central registry of known data layer definitions (which may be stored in separate files due to length)\n * @namespace\n */\n LocusZoom.DataLayers = function () {\n var obj = {};\n var datalayers = {};\n /**\n * @name LocusZoom.DataLayers.get\n * @param {String} name The name of the datalayer\n * @param {Object} layout The configuration object for this data layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n * @returns {LocusZoom.DataLayer}\n */\n obj.get = function (name, layout, parent) {\n if (!name) {\n return null;\n } else if (datalayers[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for data layer [' + name + ']');\n } else {\n return new datalayers[name](layout, parent);\n }\n } else {\n throw new Error('data layer [' + name + '] not found');\n }\n };\n /**\n * @name LocusZoom.DataLayers.set\n * @protected\n * @param {String} name\n * @param {Function} datalayer Constructor for the datalayer\n */\n obj.set = function (name, datalayer) {\n if (datalayer) {\n if (typeof datalayer != 'function') {\n throw new Error('unable to set data layer [' + name + '], argument provided is not a function');\n } else {\n datalayers[name] = datalayer;\n datalayers[name].prototype = new LocusZoom.DataLayer();\n }\n } else {\n delete datalayers[name];\n }\n };\n /**\n * Add a new type of datalayer to the registry of known layer types\n * @name LocusZoom.DataLayers.add\n * @param {String} name The name of the data layer to register\n * @param {Function} datalayer\n */\n obj.add = function (name, datalayer) {\n if (datalayers[name]) {\n throw new Error('data layer already exists with name: ' + name);\n } else {\n obj.set(name, datalayer);\n }\n };\n /**\n * Register a new datalayer that inherits and extends basic behaviors from a known datalayer\n * @param {String} parent_name The name of the parent data layer whose behavior is to be extended\n * @param {String} name The name of the new datalayer to register\n * @param {Object} [overrides] Object of properties and methods to combine with the prototype of the parent datalayer\n * @returns {Function} The constructor for the new child class\n */\n obj.extend = function (parent_name, name, overrides) {\n // TODO: Consider exposing additional constructor argument, if there is a use case for very granular extension\n overrides = overrides || {};\n var parent = datalayers[parent_name];\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered datalayer type');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n // Bypass .set() because we want a layer of inheritance below `DataLayer`\n datalayers[name] = child;\n return child;\n };\n /**\n * List the names of all known datalayers\n * @name LocusZoom.DataLayers.list\n * @returns {String[]}\n */\n obj.list = function () {\n return Object.keys(datalayers);\n };\n return obj;\n }();\n 'use strict';\n /**\n * Create a single continuous 2D track that provides information about each datapoint\n *\n * For example, this can be used to color by membership in a group, alongside information in other panels\n *\n * @class LocusZoom.DataLayers.annotation_track\n * @augments LocusZoom.DataLayer\n * @param {Object} layout\n * @param {Object|String} [layout.color]\n * @param {Array[]} An array of filter entries specifying which points to draw annotations for.\n * See `LocusZoom.DataLayer.filter` for details\n */\n LocusZoom.DataLayers.add('annotation_track', function (layout) {\n // In the future we may add additional options for controlling marker size/ shape, based on user feedback\n this.DefaultLayout = {\n color: '#000000',\n filters: [],\n tooltip_positioning: 'middle',\n // Allowed values: top, middle, bottom\n hit_area_width: 8\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n if (!Array.isArray(layout.filters)) {\n throw new Error('Annotation track must specify array of filters for selecting points to annotate');\n }\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n this.render = function () {\n var self = this;\n // Only render points that currently satisfy all provided filter conditions.\n var trackData = this.filter(this.layout.filters, 'elements');\n // Put the containing visible lines before the one containing hit areas, so that the hit areas will be on top.\n var visible_lines_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-visible_lines');\n if (visible_lines_group.size() === 0) {\n visible_lines_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-visible_lines');\n }\n var selection = visible_lines_group.selectAll('rect.lz-data_layer-' + self.layout.type).data(trackData, function (d) {\n return d[self.layout.id_field];\n });\n // Draw rectangles (visual and tooltip positioning)\n selection.enter().append('rect').attr('class', 'lz-data_layer-' + this.layout.type).attr('id', function (d) {\n return self.getElementId(d);\n });\n var width = 1;\n selection.attr('x', function (d) {\n return self.parent['x_scale'](d[self.layout.x_axis.field]) - width / 2;\n }).attr('width', width).attr('height', self.parent.layout.height).attr('fill', function (d) {\n return self.resolveScalableParameter(self.layout.color, d);\n });\n // Remove unused elements\n selection.exit().remove();\n var hit_areas_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-hit_areas');\n if (hit_areas_group.size() === 0) {\n hit_areas_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-hit_areas');\n }\n var hit_areas_selection = hit_areas_group.selectAll('rect.lz-data_layer-' + self.layout.type).data(trackData, function (d) {\n return d[self.layout.id_field];\n });\n // Add new elements as needed\n hit_areas_selection.enter().append('rect').attr('class', 'lz-data_layer-' + this.layout.type).attr('id', function (d) {\n return self.getElementId(d);\n });\n // Update the set of elements to reflect new data\n var _getX = function (d, i) {\n // Helper for position calcs below\n var x_center = self.parent['x_scale'](d[self.layout.x_axis.field]);\n var x_left = x_center - self.layout.hit_area_width / 2;\n if (i >= 1) {\n // This assumes that the data are in sorted order.\n var left_node = trackData[i - 1];\n var left_node_x_center = self.parent['x_scale'](left_node[self.layout.x_axis.field]);\n x_left = Math.max(x_left, (x_center + left_node_x_center) / 2);\n }\n return [\n x_left,\n x_center\n ];\n };\n hit_areas_selection.attr('height', self.parent.layout.height).attr('opacity', 0).attr('x', function (d, i) {\n var crds = _getX(d, i);\n return crds[0];\n }).attr('width', function (d, i) {\n var crds = _getX(d, i);\n return crds[1] - crds[0] + self.layout.hit_area_width / 2;\n });\n // Remove unused elements\n hit_areas_selection.exit().remove();\n // Set up tooltips and mouse interaction\n this.applyBehaviors(hit_areas_selection);\n };\n // Reimplement the positionTooltip() method to be annotation-specific\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var offset = stroke_width / 2;\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_center = data_layer_height / 2;\n // Tooltip should be horizontally centered above the point to be annotated. (or below if space is limited)\n var offset_right = Math.max(tooltip_box.width / 2 - x_center, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - tooltip_box.width / 2 - offset_left + offset_right;\n arrow_left = tooltip_box.width / 2 - arrow_width + offset_left - offset_right - offset;\n var top_offset = 0;\n switch (this.layout.tooltip_positioning) {\n case 'top':\n arrow_type = 'down';\n break;\n case 'bottom':\n top_offset = data_layer_height;\n arrow_type = 'up';\n break;\n case 'middle':\n default:\n var position = d3.mouse(this.svg.container.node());\n // Position the tooltip so that it does not overlap the mouse pointer\n top_offset = y_center;\n if (position[1] > data_layer_height / 2) {\n arrow_type = 'down';\n } else {\n arrow_type = 'up';\n }\n }\n if (arrow_type === 'up') {\n top = page_origin.y + top_offset + stroke_width + arrow_width;\n arrow_top = 0 - stroke_width - arrow_width;\n } else if (arrow_type === 'down') {\n top = page_origin.y + top_offset - (tooltip_box.height + stroke_width + arrow_width);\n arrow_top = tooltip_box.height - stroke_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n return this;\n });\n 'use strict';\n /**\n * Forest Data Layer\n * Implements a standard forest plot. In order to space out points, any layout using this must specify axis ticks\n * and extent in advance.\n *\n * If you are using dynamically fetched data, consider using `category_forest` instead.\n *\n * @class LocusZoom.DataLayers.forest\n */\n LocusZoom.DataLayers.add('forest', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'square',\n color: '#888888',\n fill_opacity: 1,\n y_axis: { axis: 2 },\n id_field: 'id',\n confidence_intervals: {\n start_field: 'ci_start',\n end_field: 'ci_end'\n },\n show_no_significance_line: true\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n // Reimplement the positionTooltip() method to be forest-specific\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var border_radius = 6;\n // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n var offset = Math.sqrt(point_size / Math.PI);\n var left, arrow_type, arrow_left;\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var top, arrow_top;\n if (y_center - tooltip_box.height / 2 <= 0) {\n // Too close to the top, push it down\n top = page_origin.y + y_center - 1.5 * arrow_width - border_radius;\n arrow_top = border_radius;\n } else if (y_center + tooltip_box.height / 2 >= data_layer_height) {\n // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - 2 * arrow_width - border_radius;\n } else {\n // vertically centered\n top = page_origin.y + y_center - tooltip_box.height / 2;\n arrow_top = tooltip_box.height / 2 - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n // Implement the main render function\n this.render = function () {\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n // Generate confidence interval paths if fields are defined\n if (this.layout.confidence_intervals && this.layout.fields.indexOf(this.layout.confidence_intervals.start_field) !== -1 && this.layout.fields.indexOf(this.layout.confidence_intervals.end_field) !== -1) {\n // Generate a selection for all forest plot confidence intervals\n var ci_selection = this.svg.group.selectAll('rect.lz-data_layer-forest.lz-data_layer-forest-ci').data(this.data, function (d) {\n return d[this.layout.id_field];\n }.bind(this));\n // Create confidence interval rect elements\n ci_selection.enter().append('rect').attr('class', 'lz-data_layer-forest lz-data_layer-forest-ci').attr('id', function (d) {\n return this.getElementId(d) + '_ci';\n }.bind(this)).attr('transform', 'translate(0,' + (isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height) + ')');\n // Apply position and size parameters using transition if necessary\n var ci_transform = function (d) {\n var x = this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) {\n x = -1000;\n }\n if (isNaN(y)) {\n y = -1000;\n }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var ci_width = function (d) {\n return this.parent[x_scale](d[this.layout.confidence_intervals.end_field]) - this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n }.bind(this);\n var ci_height = 1;\n if (this.canTransition()) {\n ci_selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('transform', ci_transform).attr('width', ci_width).attr('height', ci_height);\n } else {\n ci_selection.attr('transform', ci_transform).attr('width', ci_width).attr('height', ci_height);\n }\n // Remove old elements as needed\n ci_selection.exit().remove();\n }\n // Generate a selection for all forest plot points\n var points_selection = this.svg.group.selectAll('path.lz-data_layer-forest.lz-data_layer-forest-point').data(this.data, function (d) {\n return d[this.layout.id_field];\n }.bind(this));\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n points_selection.enter().append('path').attr('class', 'lz-data_layer-forest lz-data_layer-forest-point').attr('id', function (d) {\n return this.getElementId(d);\n }.bind(this)).attr('transform', 'translate(0,' + initial_y + ')');\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function (d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) {\n x = -1000;\n }\n if (isNaN(y)) {\n y = -1000;\n }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var fill = function (d) {\n return this.resolveScalableParameter(this.layout.color, d);\n }.bind(this);\n var fill_opacity = function (d) {\n return this.resolveScalableParameter(this.layout.fill_opacity, d);\n }.bind(this);\n var shape = d3.svg.symbol().size(function (d) {\n return this.resolveScalableParameter(this.layout.point_size, d);\n }.bind(this)).type(function (d) {\n return this.resolveScalableParameter(this.layout.point_shape, d);\n }.bind(this));\n // Apply position and color, using a transition if necessary\n if (this.canTransition()) {\n points_selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('transform', transform).attr('fill', fill).attr('fill-opacity', fill_opacity).attr('d', shape);\n } else {\n points_selection.attr('transform', transform).attr('fill', fill).attr('fill-opacity', fill_opacity).attr('d', shape);\n }\n // Remove old elements as needed\n points_selection.exit().remove();\n // Apply default event emitters to selection\n points_selection.on('click.event_emitter', function (element_data) {\n this.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n // Apply behaviors to points\n this.applyBehaviors(points_selection);\n };\n return this;\n });\n /**\n * A y-aligned forest plot in which the y-axis represents item labels, which are dynamically chosen when data is loaded.\n * Each item is assumed to include both data and confidence intervals.\n * This allows generating forest plots without defining the layout in advance.\n *\n * @class LocusZoom.DataLayers.category_forest\n * @augments LocusZoom.DataLayers.forest\n */\n LocusZoom.DataLayers.extend('forest', 'category_forest', {\n _getDataExtent: function (data, axis_config) {\n // In a forest plot, the data range is determined by *three* fields (beta + CI start/end)\n var ci_config = this.layout.confidence_intervals;\n if (ci_config && this.layout.fields.indexOf(ci_config.start_field) !== -1 && this.layout.fields.indexOf(ci_config.end_field) !== -1) {\n var min = function (d) {\n var f = new LocusZoom.Data.Field(ci_config.start_field);\n return +f.resolve(d);\n };\n var max = function (d) {\n var f = new LocusZoom.Data.Field(ci_config.end_field);\n return +f.resolve(d);\n };\n return [\n d3.min(data, min),\n d3.max(data, max)\n ];\n }\n // If there are no confidence intervals set, then range must depend only on a single field\n return LocusZoom.DataLayer.prototype._getDataExtent.call(this, data, axis_config);\n },\n getTicks: function (dimension, config) {\n // Overrides parent method\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier' + dimension);\n }\n // Design assumption: one axis (y1 or y2) has the ticks, and the layout says which to use\n // Also assumes that every tick gets assigned a unique matching label\n var axis_num = this.layout.y_axis.axis;\n if (dimension === 'y' + axis_num) {\n var category_field = this.layout.y_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n return this.data.map(function (item, index) {\n return {\n y: index + 1,\n text: item[category_field]\n };\n });\n } else {\n return [];\n }\n },\n applyCustomDataMethods: function () {\n // Add a synthetic yaxis field to ensure data is spread out on plot. Then, set axis floor and ceiling to\n // correct extents.\n var field_to_add = this.layout.y_axis.field;\n if (!field_to_add) {\n throw new Error('Layout for ' + this.layout.id + ' must specify yaxis.field');\n }\n this.data = this.data.map(function (item, index) {\n item[field_to_add] = index + 1;\n return item;\n });\n // Update axis extents based on one label for every point (with a bit of padding above and below)\n this.layout.y_axis.floor = 0;\n this.layout.y_axis.ceiling = this.data.length + 1;\n return this;\n }\n });\n 'use strict';\n /*********************\n * Genes Data Layer\n * Implements a data layer that will render gene tracks\n * @class\n * @augments LocusZoom.DataLayer\n*/\n LocusZoom.DataLayers.add('genes', function (layout) {\n /**\n * Define a default layout for this DataLayer type and merge it with the passed argument\n * @protected\n * @member {Object}\n * */\n this.DefaultLayout = {\n // Optionally specify different fill and stroke properties\n stroke: 'rgb(54, 54, 150)',\n color: '#363696',\n label_font_size: 12,\n label_exon_spacing: 4,\n exon_height: 16,\n bounding_box_padding: 6,\n track_vertical_spacing: 10\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n /**\n * Generate a statusnode ID for a given element\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function (element) {\n return this.getElementId(element) + '-statusnode';\n };\n /**\n * Helper function to sum layout values to derive total height for a single gene track\n * @returns {number}\n */\n this.getTrackHeight = function () {\n return 2 * this.layout.bounding_box_padding + this.layout.label_font_size + this.layout.label_exon_spacing + this.layout.exon_height + this.layout.track_vertical_spacing;\n };\n /**\n * A gene may have arbitrarily many transcripts, but this data layer isn't set up to render them yet.\n * Stash a transcript_idx to point to the first transcript and use that for all transcript refs.\n * @member {number}\n * @type {number}\n */\n this.transcript_idx = 0;\n /**\n * An internal counter for the number of tracks in the data layer. Used as an internal counter for looping\n * over positions / assignments\n * @protected\n * @member {number}\n */\n this.tracks = 1;\n /**\n * Store information about genes in dataset, in a hash indexed by track number: {track_number: [gene_indices]}\n * @member {Object.}\n */\n this.gene_track_index = { 1: [] };\n /**\n * Ensure that genes in overlapping chromosome regions are positioned so that parts of different genes do not\n * overlap in the view. A track is a row used to vertically separate overlapping genes.\n * @returns {LocusZoom.DataLayer}\n */\n this.assignTracks = function () {\n /**\n * Function to get the width in pixels of a label given the text and layout attributes\n * TODO: Move to outer scope?\n * @param {String} gene_name\n * @param {number|string} font_size\n * @returns {number}\n */\n this.getLabelWidth = function (gene_name, font_size) {\n try {\n var temp_text = this.svg.group.append('text').attr('x', 0).attr('y', 0).attr('class', 'lz-data_layer-genes lz-label').style('font-size', font_size).text(gene_name + '\\u2192');\n var label_width = temp_text.node().getBBox().width;\n temp_text.remove();\n return label_width;\n } catch (e) {\n return 0;\n }\n };\n // Reinitialize some metadata\n this.tracks = 1;\n this.gene_track_index = { 1: [] };\n this.data.map(function (d, g) {\n // If necessary, split combined gene id / version fields into discrete fields.\n // NOTE: this may be an issue with CSG's genes data source that may eventually be solved upstream.\n if (this.data[g].gene_id && this.data[g].gene_id.indexOf('.')) {\n var split = this.data[g].gene_id.split('.');\n this.data[g].gene_id = split[0];\n this.data[g].gene_version = split[1];\n }\n // Stash the transcript ID on the parent gene\n this.data[g].transcript_id = this.data[g].transcripts[this.transcript_idx].transcript_id;\n // Determine display range start and end, based on minimum allowable gene display width, bounded by what we can see\n // (range: values in terms of pixels on the screen)\n this.data[g].display_range = {\n start: this.parent.x_scale(Math.max(d.start, this.state.start)),\n end: this.parent.x_scale(Math.min(d.end, this.state.end))\n };\n this.data[g].display_range.label_width = this.getLabelWidth(this.data[g].gene_name, this.layout.label_font_size);\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n // Determine label text anchor (default to middle)\n this.data[g].display_range.text_anchor = 'middle';\n if (this.data[g].display_range.width < this.data[g].display_range.label_width) {\n if (d.start < this.state.start) {\n this.data[g].display_range.end = this.data[g].display_range.start + this.data[g].display_range.label_width + this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'start';\n } else if (d.end > this.state.end) {\n this.data[g].display_range.start = this.data[g].display_range.end - this.data[g].display_range.label_width - this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n var centered_margin = (this.data[g].display_range.label_width - this.data[g].display_range.width) / 2 + this.layout.label_font_size;\n if (this.data[g].display_range.start - centered_margin < this.parent.x_scale(this.state.start)) {\n this.data[g].display_range.start = this.parent.x_scale(this.state.start);\n this.data[g].display_range.end = this.data[g].display_range.start + this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'start';\n } else if (this.data[g].display_range.end + centered_margin > this.parent.x_scale(this.state.end)) {\n this.data[g].display_range.end = this.parent.x_scale(this.state.end);\n this.data[g].display_range.start = this.data[g].display_range.end - this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n this.data[g].display_range.start -= centered_margin;\n this.data[g].display_range.end += centered_margin;\n }\n }\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n }\n // Add bounding box padding to the calculated display range start, end, and width\n this.data[g].display_range.start -= this.layout.bounding_box_padding;\n this.data[g].display_range.end += this.layout.bounding_box_padding;\n this.data[g].display_range.width += 2 * this.layout.bounding_box_padding;\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[g].display_domain = {\n start: this.parent.x_scale.invert(this.data[g].display_range.start),\n end: this.parent.x_scale.invert(this.data[g].display_range.end)\n };\n this.data[g].display_domain.width = this.data[g].display_domain.end - this.data[g].display_domain.start;\n // Using display range/domain data generated above cast each gene to tracks such that none overlap\n this.data[g].track = null;\n var potential_track = 1;\n while (this.data[g].track === null) {\n var collision_on_potential_track = false;\n this.gene_track_index[potential_track].map(function (placed_gene) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_gene.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_gene.display_range.end, this.display_range.end);\n if (max_end - min_start < placed_gene.display_range.width + this.display_range.width) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[g]));\n if (!collision_on_potential_track) {\n this.data[g].track = potential_track;\n this.gene_track_index[potential_track].push(this.data[g]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.gene_track_index[potential_track] = [];\n }\n }\n }\n // Stash parent references on all genes, trascripts, and exons\n this.data[g].parent = this;\n this.data[g].transcripts.map(function (d, t) {\n this.data[g].transcripts[t].parent = this.data[g];\n this.data[g].transcripts[t].exons.map(function (d, e) {\n this.data[g].transcripts[t].exons[e].parent = this.data[g].transcripts[t];\n }.bind(this));\n }.bind(this));\n }.bind(this));\n return this;\n };\n /**\n * Main render function\n */\n this.render = function () {\n var self = this;\n this.assignTracks();\n var width, height, x, y;\n // Render gene groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-genes').data(this.data, function (d) {\n return d.gene_name;\n });\n selection.enter().append('g').attr('class', 'lz-data_layer-genes');\n selection.attr('id', function (d) {\n return this.getElementId(d);\n }.bind(this)).each(function (gene) {\n var data_layer = gene.parent;\n // Render gene bounding boxes (status nodes to show selected/highlighted)\n var bboxes = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-data_layer-genes-statusnode').data([gene], function (d) {\n return data_layer.getElementStatusNodeId(d);\n });\n bboxes.enter().append('rect').attr('class', 'lz-data_layer-genes lz-data_layer-genes-statusnode');\n bboxes.attr('id', function (d) {\n return data_layer.getElementStatusNodeId(d);\n }).attr('rx', function () {\n return data_layer.layout.bounding_box_padding;\n }).attr('ry', function () {\n return data_layer.layout.bounding_box_padding;\n });\n width = function (d) {\n return d.display_range.width;\n };\n height = function () {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function (d) {\n return d.display_range.start;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight();\n };\n if (data_layer.canTransition()) {\n bboxes.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n bboxes.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n bboxes.exit().remove();\n // Render gene boundaries\n var boundary_fill = function (d) {\n return self.resolveScalableParameter(self.layout.color, d);\n };\n var boundary_stroke = function (d) {\n return self.resolveScalableParameter(self.layout.stroke, d);\n };\n var boundaries = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-boundary').data([gene], function (d) {\n return d.gene_name + '_boundary';\n }).style({\n fill: boundary_fill,\n stroke: boundary_stroke\n });\n boundaries.enter().append('rect').attr('class', 'lz-data_layer-genes lz-boundary');\n width = function (d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function () {\n return 1; // TODO: scale dynamically?\n };\n x = function (d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight() + data_layer.layout.bounding_box_padding + data_layer.layout.label_font_size + data_layer.layout.label_exon_spacing + Math.max(data_layer.layout.exon_height, 3) / 2;\n };\n if (data_layer.canTransition()) {\n boundaries.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n boundaries.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n boundaries.exit().remove();\n // Render gene labels\n var labels = d3.select(this).selectAll('text.lz-data_layer-genes.lz-label').data([gene], function (d) {\n return d.gene_name + '_label';\n });\n labels.enter().append('text').attr('class', 'lz-data_layer-genes lz-label');\n labels.attr('text-anchor', function (d) {\n return d.display_range.text_anchor;\n }).text(function (d) {\n return d.strand === '+' ? d.gene_name + '\\u2192' : '\\u2190' + d.gene_name;\n }).style('font-size', gene.parent.layout.label_font_size);\n x = function (d) {\n if (d.display_range.text_anchor === 'middle') {\n return d.display_range.start + d.display_range.width / 2;\n } else if (d.display_range.text_anchor === 'start') {\n return d.display_range.start + data_layer.layout.bounding_box_padding;\n } else if (d.display_range.text_anchor === 'end') {\n return d.display_range.end - data_layer.layout.bounding_box_padding;\n }\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight() + data_layer.layout.bounding_box_padding + data_layer.layout.label_font_size;\n };\n if (data_layer.canTransition()) {\n labels.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('x', x).attr('y', y);\n } else {\n labels.attr('x', x).attr('y', y);\n }\n labels.exit().remove();\n // Render exon rects (first transcript only, for now)\n // Exons: by default color on gene properties for consistency with the gene boundary track- hence color uses d.parent.parent\n var exon_fill = function (d) {\n return self.resolveScalableParameter(self.layout.color, d.parent.parent);\n };\n var exon_stroke = function (d) {\n return self.resolveScalableParameter(self.layout.stroke, d.parent.parent);\n };\n var exons = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-exon').data(gene.transcripts[gene.parent.transcript_idx].exons, function (d) {\n return d.exon_id;\n });\n exons.enter().append('rect').attr('class', 'lz-data_layer-genes lz-exon');\n exons.style({\n fill: exon_fill,\n stroke: exon_stroke\n });\n width = function (d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function () {\n return data_layer.layout.exon_height;\n };\n x = function (d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function () {\n return (gene.track - 1) * data_layer.getTrackHeight() + data_layer.layout.bounding_box_padding + data_layer.layout.label_font_size + data_layer.layout.label_exon_spacing;\n };\n if (data_layer.canTransition()) {\n exons.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n exons.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n exons.exit().remove();\n // Render gene click area\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-clickarea').data([gene], function (d) {\n return d.gene_name + '_clickarea';\n });\n clickareas.enter().append('rect').attr('class', 'lz-data_layer-genes lz-clickarea');\n clickareas.attr('id', function (d) {\n return data_layer.getElementId(d) + '_clickarea';\n }).attr('rx', function () {\n return data_layer.layout.bounding_box_padding;\n }).attr('ry', function () {\n return data_layer.layout.bounding_box_padding;\n });\n width = function (d) {\n return d.display_range.width;\n };\n height = function () {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function (d) {\n return d.display_range.start;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight();\n };\n if (data_layer.canTransition()) {\n clickareas.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n // Remove old clickareas as needed\n clickareas.exit().remove();\n // Apply default event emitters to clickareas\n clickareas.on('click.event_emitter', function (element) {\n element.parent.parent.emit('element_clicked', element, true);\n });\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n });\n // Remove old elements as needed\n selection.exit().remove();\n };\n /**\n * Reimplement the positionTooltip() method to be gene-specific\n * @param {String} id\n */\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var gene_bbox_id = this.getElementStatusNodeId(tooltip.data);\n var gene_bbox = d3.select('#' + gene_bbox_id).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the gene that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var gene_center_x = (tooltip.data.display_range.start + tooltip.data.display_range.end) / 2 - this.layout.bounding_box_padding / 2;\n var offset_right = Math.max(tooltip_box.width / 2 - gene_center_x, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + gene_center_x - data_layer_width, 0);\n var left = page_origin.x + gene_center_x - tooltip_box.width / 2 - offset_left + offset_right;\n var arrow_left = tooltip_box.width / 2 - arrow_width / 2 + offset_left - offset_right;\n // Position vertically below the gene unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (gene_bbox.y + gene_bbox.height)) {\n top = page_origin.y + gene_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + gene_bbox.y + gene_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n return this;\n });\n 'use strict';\n /*********************\n Genome Legend Data Layer\n Implements a data layer that will render a genome legend\n*/\n // Build a custom data layer for a genome legend\n LocusZoom.DataLayers.add('genome_legend', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n chromosome_fill_colors: {\n light: 'rgb(155, 155, 188)',\n dark: 'rgb(95, 95, 128)'\n },\n chromosome_label_colors: {\n light: 'rgb(120, 120, 186)',\n dark: 'rgb(0, 0, 66)'\n }\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n // Implement the main render function\n this.render = function () {\n // Iterate over data to generate genome-wide start/end values for each chromosome\n var position = 0;\n this.data.forEach(function (d, i) {\n this.data[i].genome_start = position;\n this.data[i].genome_end = position + d['genome:base_pairs'];\n position += d['genome:base_pairs'];\n }.bind(this));\n var chromosomes = this.svg.group.selectAll('rect.lz-data_layer-genome_legend').data(this.data, function (d) {\n return d['genome:chr'];\n });\n // Create chromosome elements, apply class\n chromosomes.enter().append('rect').attr('class', 'lz-data_layer-genome_legend');\n // Position and fill chromosome rects\n var data_layer = this;\n var panel = this.parent;\n chromosomes.attr('fill', function (d) {\n return d['genome:chr'] % 2 ? data_layer.layout.chromosome_fill_colors.light : data_layer.layout.chromosome_fill_colors.dark;\n }).attr('x', function (d) {\n return panel.x_scale(d.genome_start);\n }).attr('y', 0).attr('width', function (d) {\n return panel.x_scale(d['genome:base_pairs']);\n }).attr('height', panel.layout.cliparea.height);\n // Remove old elements as needed\n chromosomes.exit().remove();\n // Parse current state variant into a position\n // Assumes that variant string is of the format 10:123352136_C/T or 10:123352136\n var variant_parts = /([^:]+):(\\d+)(?:_.*)?/.exec(this.state.variant);\n if (!variant_parts) {\n throw new Error('Genome legend cannot understand the specified variant position');\n }\n var chr = variant_parts[1];\n var offset = variant_parts[2];\n // TODO: How does this handle representation of X or Y chromosomes?\n position = +this.data[chr - 1].genome_start + +offset;\n // Render the position\n var region = this.svg.group.selectAll('rect.lz-data_layer-genome_legend-marker').data([{\n start: position,\n end: position + 1\n }]);\n region.enter().append('rect').attr('class', 'lz-data_layer-genome_legend-marker');\n region.transition().duration(500).style({\n 'fill': 'rgba(255, 250, 50, 0.8)',\n 'stroke': 'rgba(255, 250, 50, 0.8)',\n 'stroke-width': '3px'\n }).attr('x', function (d) {\n return panel.x_scale(d.start);\n }).attr('y', 0).attr('width', function (d) {\n return panel.x_scale(d.end - d.start);\n }).attr('height', panel.layout.cliparea.height);\n region.exit().remove();\n };\n return this;\n });\n 'use strict';\n /**\n * Intervals Data Layer\n * Implements a data layer that will render interval annotation tracks (intervals must provide start and end values)\n * @class LocusZoom.DataLayers.intervals\n * @augments LocusZoom.DataLayer\n */\n LocusZoom.DataLayers.add('intervals', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n start_field: 'start',\n end_field: 'end',\n track_split_field: 'state_id',\n track_split_order: 'DESC',\n track_split_legend_to_y_axis: 2,\n split_tracks: true,\n track_height: 15,\n track_vertical_spacing: 3,\n bounding_box_padding: 2,\n always_hide_legend: false,\n color: '#B8B8B8',\n fill_opacity: 1\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n /**\n * To define shared highlighting on the track split field define the status node id override\n * to generate an ID common to the track when we're actively splitting data out to separate tracks\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function (element) {\n if (this.layout.split_tracks) {\n return (this.getBaseId() + '-statusnode-' + element[this.layout.track_split_field]).replace(/[:.[\\],]/g, '_');\n }\n return this.getElementId(element) + '-statusnode';\n }.bind(this);\n // Helper function to sum layout values to derive total height for a single interval track\n this.getTrackHeight = function () {\n return this.layout.track_height + this.layout.track_vertical_spacing + 2 * this.layout.bounding_box_padding;\n };\n this.tracks = 1;\n this.previous_tracks = 1;\n // track-number-indexed object with arrays of interval indexes in the dataset\n this.interval_track_index = { 1: [] };\n // After we've loaded interval data interpret it to assign\n // each to a track so that they do not overlap in the view\n this.assignTracks = function () {\n // Reinitialize some metadata\n this.previous_tracks = this.tracks;\n this.tracks = 0;\n this.interval_track_index = { 1: [] };\n this.track_split_field_index = {};\n // If splitting tracks by a field's value then do a first pass determine\n // a value/track mapping that preserves the order of possible values\n if (this.layout.track_split_field && this.layout.split_tracks) {\n this.data.map(function (d) {\n this.track_split_field_index[d[this.layout.track_split_field]] = null;\n }.bind(this));\n var index = Object.keys(this.track_split_field_index);\n if (this.layout.track_split_order === 'DESC') {\n index.reverse();\n }\n index.forEach(function (val) {\n this.track_split_field_index[val] = this.tracks + 1;\n this.interval_track_index[this.tracks + 1] = [];\n this.tracks++;\n }.bind(this));\n }\n this.data.map(function (d, i) {\n // Stash a parent reference on the interval\n this.data[i].parent = this;\n // Determine display range start and end, based on minimum allowable interval display width,\n // bounded by what we can see (range: values in terms of pixels on the screen)\n this.data[i].display_range = {\n start: this.parent.x_scale(Math.max(d[this.layout.start_field], this.state.start)),\n end: this.parent.x_scale(Math.min(d[this.layout.end_field], this.state.end))\n };\n this.data[i].display_range.width = this.data[i].display_range.end - this.data[i].display_range.start;\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[i].display_domain = {\n start: this.parent.x_scale.invert(this.data[i].display_range.start),\n end: this.parent.x_scale.invert(this.data[i].display_range.end)\n };\n this.data[i].display_domain.width = this.data[i].display_domain.end - this.data[i].display_domain.start;\n // If splitting to tracks based on the value of the designated track split field\n // then don't bother with collision detection (intervals will be grouped on tracks\n // solely by the value of track_split_field)\n if (this.layout.track_split_field && this.layout.split_tracks) {\n var val = this.data[i][this.layout.track_split_field];\n this.data[i].track = this.track_split_field_index[val];\n this.interval_track_index[this.data[i].track].push(i);\n } else {\n // If not splitting to tracks based on a field value then do so based on collision\n // detection (as how it's done for genes). Use display range/domain data generated\n // above and cast each interval to tracks such that none overlap\n this.tracks = 1;\n this.data[i].track = null;\n var potential_track = 1;\n while (this.data[i].track === null) {\n var collision_on_potential_track = false;\n this.interval_track_index[potential_track].map(function (placed_interval) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_interval.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_interval.display_range.end, this.display_range.end);\n if (max_end - min_start < placed_interval.display_range.width + this.display_range.width) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[i]));\n if (!collision_on_potential_track) {\n this.data[i].track = potential_track;\n this.interval_track_index[potential_track].push(this.data[i]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.interval_track_index[potential_track] = [];\n }\n }\n }\n }\n }.bind(this));\n return this;\n };\n // Implement the main render function\n this.render = function () {\n this.assignTracks();\n // Remove any shared highlight nodes and re-render them if we're splitting on tracks\n // At most there will only be dozen or so nodes here (one per track) and each time\n // we render data we may have new tracks, so wiping/redrawing all is reasonable.\n this.svg.group.selectAll('.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-shared').remove();\n Object.keys(this.track_split_field_index).forEach(function (key) {\n // Make a psuedo-element so that we can generate an id for the shared node\n var psuedoElement = {};\n psuedoElement[this.layout.track_split_field] = key;\n // Insert the shared node\n var sharedstatusnode_style = { display: this.layout.split_tracks ? null : 'none' };\n this.svg.group.insert('rect', ':first-child').attr('id', this.getElementStatusNodeId(psuedoElement)).attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-shared').attr('rx', this.layout.bounding_box_padding).attr('ry', this.layout.bounding_box_padding).attr('width', this.parent.layout.cliparea.width).attr('height', this.getTrackHeight() - this.layout.track_vertical_spacing).attr('x', 0).attr('y', (this.track_split_field_index[key] - 1) * this.getTrackHeight()).style(sharedstatusnode_style);\n }.bind(this));\n var width, height, x, y, fill, fill_opacity;\n // Render interval groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-intervals').data(this.data, function (d) {\n return d[this.layout.id_field];\n }.bind(this));\n selection.enter().append('g').attr('class', 'lz-data_layer-intervals');\n selection.attr('id', function (d) {\n return this.getElementId(d);\n }.bind(this)).each(function (interval) {\n var data_layer = interval.parent;\n // Render interval status nodes (displayed behind intervals to show highlight\n // without needing to modify interval display element(s))\n var statusnode_style = { display: data_layer.layout.split_tracks ? 'none' : null };\n var statusnodes = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-statusnode-discrete').data([interval], function (d) {\n return data_layer.getElementId(d) + '-statusnode';\n });\n statusnodes.enter().insert('rect', ':first-child').attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-statusnode-discrete');\n statusnodes.attr('id', function (d) {\n return data_layer.getElementId(d) + '-statusnode';\n }).attr('rx', function () {\n return data_layer.layout.bounding_box_padding;\n }).attr('ry', function () {\n return data_layer.layout.bounding_box_padding;\n }).style(statusnode_style);\n width = function (d) {\n return d.display_range.width + 2 * data_layer.layout.bounding_box_padding;\n };\n height = function () {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function (d) {\n return d.display_range.start - data_layer.layout.bounding_box_padding;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight();\n };\n if (data_layer.canTransition()) {\n statusnodes.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n statusnodes.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n statusnodes.exit().remove();\n // Render primary interval rects\n var rects = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-interval_rect').data([interval], function (d) {\n return d[data_layer.layout.id_field] + '_interval_rect';\n });\n rects.enter().append('rect').attr('class', 'lz-data_layer-intervals lz-interval_rect');\n height = data_layer.layout.track_height;\n width = function (d) {\n return d.display_range.width;\n };\n x = function (d) {\n return d.display_range.start;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight() + data_layer.layout.bounding_box_padding;\n };\n fill = function (d) {\n return data_layer.resolveScalableParameter(data_layer.layout.color, d);\n };\n fill_opacity = function (d) {\n return data_layer.resolveScalableParameter(data_layer.layout.fill_opacity, d);\n };\n if (data_layer.canTransition()) {\n rects.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y).attr('fill', fill).attr('fill-opacity', fill_opacity);\n } else {\n rects.attr('width', width).attr('height', height).attr('x', x).attr('y', y).attr('fill', fill).attr('fill-opacity', fill_opacity);\n }\n rects.exit().remove();\n // Render interval click areas\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-clickarea').data([interval], function (d) {\n return d.interval_name + '_clickarea';\n });\n clickareas.enter().append('rect').attr('class', 'lz-data_layer-intervals lz-clickarea');\n clickareas.attr('id', function (d) {\n return data_layer.getElementId(d) + '_clickarea';\n }).attr('rx', function () {\n return data_layer.layout.bounding_box_padding;\n }).attr('ry', function () {\n return data_layer.layout.bounding_box_padding;\n });\n width = function (d) {\n return d.display_range.width;\n };\n height = function () {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function (d) {\n return d.display_range.start;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight();\n };\n if (data_layer.canTransition()) {\n clickareas.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n // Remove old clickareas as needed\n clickareas.exit().remove();\n // Apply default event emitters to clickareas\n clickareas.on('click', function (element_data) {\n element_data.parent.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n });\n // Remove old elements as needed\n selection.exit().remove();\n // Update the legend axis if the number of ticks changed\n if (this.previous_tracks !== this.tracks) {\n this.updateSplitTrackAxis();\n }\n return this;\n };\n // Reimplement the positionTooltip() method to be interval-specific\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var interval_bbox = d3.select('#' + this.getElementStatusNodeId(tooltip.data)).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the interval that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var interval_center_x = (tooltip.data.display_range.start + tooltip.data.display_range.end) / 2 - this.layout.bounding_box_padding / 2;\n var offset_right = Math.max(tooltip_box.width / 2 - interval_center_x, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + interval_center_x - data_layer_width, 0);\n var left = page_origin.x + interval_center_x - tooltip_box.width / 2 - offset_left + offset_right;\n var arrow_left = tooltip_box.width / 2 - arrow_width / 2 + offset_left - offset_right;\n // Position vertically below the interval unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (interval_bbox.y + interval_bbox.height)) {\n top = page_origin.y + interval_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + interval_bbox.y + interval_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n // Redraw split track axis or hide it, and show/hide the legend, as determined\n // by current layout parameters and data\n this.updateSplitTrackAxis = function () {\n var legend_axis = this.layout.track_split_legend_to_y_axis ? 'y' + this.layout.track_split_legend_to_y_axis : false;\n if (this.layout.split_tracks) {\n var tracks = +this.tracks || 0;\n var track_height = +this.layout.track_height || 0;\n var track_spacing = 2 * (+this.layout.bounding_box_padding || 0) + (+this.layout.track_vertical_spacing || 0);\n var target_height = tracks * track_height + (tracks - 1) * track_spacing;\n this.parent.scaleHeightToData(target_height);\n if (legend_axis && this.parent.legend) {\n this.parent.legend.hide();\n this.parent.layout.axes[legend_axis] = {\n render: true,\n ticks: [],\n range: {\n start: target_height - this.layout.track_height / 2,\n end: this.layout.track_height / 2\n }\n };\n this.layout.legend.forEach(function (element) {\n var key = element[this.layout.track_split_field];\n var track = this.track_split_field_index[key];\n if (track) {\n if (this.layout.track_split_order === 'DESC') {\n track = Math.abs(track - tracks - 1);\n }\n this.parent.layout.axes[legend_axis].ticks.push({\n y: track,\n text: element.label\n });\n }\n }.bind(this));\n this.layout.y_axis = {\n axis: this.layout.track_split_legend_to_y_axis,\n floor: 1,\n ceiling: tracks\n };\n this.parent.render();\n }\n this.parent_plot.positionPanels();\n } else {\n if (legend_axis && this.parent.legend) {\n if (!this.layout.always_hide_legend) {\n this.parent.legend.show();\n }\n this.parent.layout.axes[legend_axis] = { render: false };\n this.parent.render();\n }\n }\n return this;\n };\n // Method to not only toggle the split tracks boolean but also update\n // necessary display values to animate a complete merge/split\n this.toggleSplitTracks = function () {\n this.layout.split_tracks = !this.layout.split_tracks;\n if (this.parent.legend && !this.layout.always_hide_legend) {\n this.parent.layout.margin.bottom = 5 + (this.layout.split_tracks ? 0 : this.parent.legend.layout.height + 5);\n }\n this.render();\n this.updateSplitTrackAxis();\n return this;\n };\n return this;\n });\n 'use strict';\n /*********************\n * Line Data Layer\n * Implements a standard line plot, representing either a trace or a filled curve.\n * @class\n * @augments LocusZoom.DataLayer\n*/\n LocusZoom.DataLayers.add('line', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n /** @member {Object} */\n this.DefaultLayout = {\n style: {\n fill: 'none',\n 'stroke-width': '2px'\n },\n interpolate: 'linear',\n x_axis: { field: 'x' },\n y_axis: {\n field: 'y',\n axis: 1\n },\n hitarea_width: 5\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Var for storing mouse events for use in tool tip positioning\n /** @member {String} */\n this.mouse_event = null;\n /**\n * Var for storing the generated line function itself\n * @member {d3.svg.line}\n * */\n this.line = null;\n /**\n * The timeout identifier returned by setTimeout\n * @member {Number}\n */\n this.tooltip_timeout = null;\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n /**\n * Helper function to get display and data objects representing\n * the x/y coordinates of the current mouse event with respect to the line in terms of the display\n * and the interpolated values of the x/y fields with respect to the line\n * @returns {{display: {x: *, y: null}, data: {}, slope: null}}\n */\n this.getMouseDisplayAndData = function () {\n var ret = {\n display: {\n x: d3.mouse(this.mouse_event)[0],\n y: null\n },\n data: {},\n slope: null\n };\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n ret.data[x_field] = this.parent[x_scale].invert(ret.display.x);\n var bisect = d3.bisector(function (datum) {\n return +datum[x_field];\n }).left;\n var index = bisect(this.data, ret.data[x_field]) - 1;\n var startDatum = this.data[index];\n var endDatum = this.data[index + 1];\n var interpolate = d3.interpolateNumber(+startDatum[y_field], +endDatum[y_field]);\n var range = +endDatum[x_field] - +startDatum[x_field];\n ret.data[y_field] = interpolate(ret.data[x_field] % range / range);\n ret.display.y = this.parent[y_scale](ret.data[y_field]);\n if (this.layout.tooltip.x_precision) {\n ret.data[x_field] = ret.data[x_field].toPrecision(this.layout.tooltip.x_precision);\n }\n if (this.layout.tooltip.y_precision) {\n ret.data[y_field] = ret.data[y_field].toPrecision(this.layout.tooltip.y_precision);\n }\n ret.slope = (this.parent[y_scale](endDatum[y_field]) - this.parent[y_scale](startDatum[y_field])) / (this.parent[x_scale](endDatum[x_field]) - this.parent[x_scale](startDatum[x_field]));\n return ret;\n };\n /**\n * Reimplement the positionTooltip() method to be line-specific\n * @param {String} id Identify the tooltip to be positioned\n */\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var arrow_width = 7;\n // as defined in the default stylesheet\n var border_radius = 6;\n // as defined in the default stylesheet\n var stroke_width = parseFloat(this.layout.style['stroke-width']) || 1;\n var page_origin = this.getPageOrigin();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n var top, left, arrow_top, arrow_left, arrow_type;\n // Determine x/y coordinates for display and data\n var dd = this.getMouseDisplayAndData();\n // If the absolute value of the slope of the line at this point is above 1 (including Infinity)\n // then position the tool tip left/right. Otherwise position top/bottom.\n if (Math.abs(dd.slope) > 1) {\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (dd.display.x <= this.parent.layout.width / 2) {\n left = page_origin.x + dd.display.x + stroke_width + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + dd.display.x - tooltip_box.width - stroke_width - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n if (dd.display.y - tooltip_box.height / 2 <= 0) {\n // Too close to the top, push it down\n top = page_origin.y + dd.display.y - 1.5 * arrow_width - border_radius;\n arrow_top = border_radius;\n } else if (dd.display.y + tooltip_box.height / 2 >= data_layer_height) {\n // Too close to the bottom, pull it up\n top = page_origin.y + dd.display.y + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - 2 * arrow_width - border_radius;\n } else {\n // vertically centered\n top = page_origin.y + dd.display.y - tooltip_box.height / 2;\n arrow_top = tooltip_box.height / 2 - arrow_width;\n }\n } else {\n // Position horizontally: attempt to center on the mouse's x coordinate\n // pad to either side if bumping up against the edge of the data layer\n var offset_right = Math.max(tooltip_box.width / 2 - dd.display.x, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + dd.display.x - data_layer_width, 0);\n left = page_origin.x + dd.display.x - tooltip_box.width / 2 - offset_left + offset_right;\n var min_arrow_left = arrow_width / 2;\n var max_arrow_left = tooltip_box.width - 2.5 * arrow_width;\n arrow_left = tooltip_box.width / 2 - arrow_width + offset_left - offset_right;\n arrow_left = Math.min(Math.max(arrow_left, min_arrow_left), max_arrow_left);\n // Position vertically above the line unless there's insufficient space\n if (tooltip_box.height + stroke_width + arrow_width > dd.display.y) {\n top = page_origin.y + dd.display.y + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n } else {\n top = page_origin.y + dd.display.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n }\n }\n // Apply positions to the main div\n tooltip.selector.style({\n left: left + 'px',\n top: top + 'px'\n });\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style({\n 'left': arrow_left + 'px',\n top: arrow_top + 'px'\n });\n };\n /**\n * Implement the main render function\n */\n this.render = function () {\n // Several vars needed to be in scope\n var data_layer = this;\n var panel = this.parent;\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n // Join data to the line selection\n var selection = this.svg.group.selectAll('path.lz-data_layer-line').data([this.data]);\n // Create path element, apply class\n this.path = selection.enter().append('path').attr('class', 'lz-data_layer-line');\n // Generate the line\n if (this.layout.style.fill && this.layout.style.fill !== 'none') {\n // Filled curve: define the line as a filled boundary\n this.line = d3.svg.area().x(function (d) {\n return parseFloat(panel[x_scale](d[x_field]));\n }).y0(function (d) {\n return parseFloat(panel[y_scale](0));\n }).y1(function (d) {\n return parseFloat(panel[y_scale](d[y_field]));\n });\n } else {\n // Basic line\n this.line = d3.svg.line().x(function (d) {\n return parseFloat(panel[x_scale](d[x_field]));\n }).y(function (d) {\n return parseFloat(panel[y_scale](d[y_field]));\n }).interpolate(this.layout.interpolate);\n }\n // Apply line and style\n if (this.canTransition()) {\n selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('d', this.line).style(this.layout.style);\n } else {\n selection.attr('d', this.line).style(this.layout.style);\n }\n // Apply tooltip, etc\n if (this.layout.tooltip) {\n // Generate an overlaying transparent \"hit area\" line for more intuitive mouse events\n var hitarea_width = parseFloat(this.layout.hitarea_width).toString() + 'px';\n var hitarea = this.svg.group.selectAll('path.lz-data_layer-line-hitarea').data([this.data]);\n hitarea.enter().append('path').attr('class', 'lz-data_layer-line-hitarea').style('stroke-width', hitarea_width);\n var hitarea_line = d3.svg.line().x(function (d) {\n return parseFloat(panel[x_scale](d[x_field]));\n }).y(function (d) {\n return parseFloat(panel[y_scale](d[y_field]));\n }).interpolate(this.layout.interpolate);\n hitarea.attr('d', hitarea_line).on('mouseover', function () {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.createTooltip(dd.data);\n }).on('mousemove', function () {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.updateTooltip(dd.data);\n data_layer.positionTooltip(data_layer.getElementId());\n }).on('mouseout', function () {\n data_layer.tooltip_timeout = setTimeout(function () {\n data_layer.mouse_event = null;\n data_layer.destroyTooltip(data_layer.getElementId());\n }, 300);\n });\n hitarea.exit().remove();\n }\n // Remove old elements as needed\n selection.exit().remove();\n };\n /**\n * Redefine setElementStatus family of methods as line data layers will only ever have a single path element\n * @param {String} status A member of `LocusZoom.DataLayer.Statuses.adjectives`\n * @param {String|Object} element\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\n this.setElementStatus = function (status, element, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setElementStatusByFilters = function (status, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setAllElementStatus = function (status, toggle) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') {\n return this;\n }\n if (typeof toggle == 'undefined') {\n toggle = true;\n }\n // Update global status flag\n this.global_statuses[status] = toggle;\n // Apply class to path based on global status flags\n var path_class = 'lz-data_layer-line';\n Object.keys(this.global_statuses).forEach(function (global_status) {\n if (this.global_statuses[global_status]) {\n path_class += ' lz-data_layer-line-' + global_status;\n }\n }.bind(this));\n this.path.attr('class', path_class);\n // Trigger layout changed event hook\n this.parent.emit('layout_changed', true);\n return this;\n };\n return this;\n });\n /***************************\n * Orthogonal Line Data Layer\n * Implements a horizontal or vertical line given an orientation and an offset in the layout\n * Does not require a data source\n * @class\n * @augments LocusZoom.DataLayer\n*/\n LocusZoom.DataLayers.add('orthogonal_line', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n style: {\n 'stroke': '#D3D3D3',\n 'stroke-width': '3px',\n 'stroke-dasharray': '10px 10px'\n },\n orientation: 'horizontal',\n x_axis: {\n axis: 1,\n decoupled: true\n },\n y_axis: {\n axis: 1,\n decoupled: true\n },\n offset: 0\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Require that orientation be \"horizontal\" or \"vertical\" only\n if ([\n 'horizontal',\n 'vertical'\n ].indexOf(layout.orientation) === -1) {\n layout.orientation = 'horizontal';\n }\n // Vars for storing the data generated line\n /** @member {Array} */\n this.data = [];\n /** @member {d3.svg.line} */\n this.line = null;\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n /**\n * Implement the main render function\n */\n this.render = function () {\n // Several vars needed to be in scope\n var panel = this.parent;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var x_extent = 'x_extent';\n var y_extent = 'y' + this.layout.y_axis.axis + '_extent';\n var x_range = 'x_range';\n // Generate data using extents depending on orientation\n if (this.layout.orientation === 'horizontal') {\n this.data = [\n {\n x: panel[x_extent][0],\n y: this.layout.offset\n },\n {\n x: panel[x_extent][1],\n y: this.layout.offset\n }\n ];\n } else if (this.layout.orientation === 'vertical') {\n this.data = [\n {\n x: this.layout.offset,\n y: panel[y_extent][0]\n },\n {\n x: this.layout.offset,\n y: panel[y_extent][1]\n }\n ];\n } else {\n throw new Error('Unrecognized vertical line type. Must be \"vertical\" or \"horizontal\"');\n }\n // Join data to the line selection\n var selection = this.svg.group.selectAll('path.lz-data_layer-line').data([this.data]);\n // Create path element, apply class\n this.path = selection.enter().append('path').attr('class', 'lz-data_layer-line');\n // In some cases, a vertical line may overlay a track that has no inherent y-values (extent)\n // When that happens, provide a default height based on the current panel dimensions (accounting\n // for any resizing that happened after the panel was created)\n var default_y = [\n panel.layout.cliparea.height,\n 0\n ];\n // Generate the line\n this.line = d3.svg.line().x(function (d, i) {\n var x = parseFloat(panel[x_scale](d['x']));\n return isNaN(x) ? panel[x_range][i] : x;\n }).y(function (d, i) {\n var y = parseFloat(panel[y_scale](d['y']));\n return isNaN(y) ? default_y[i] : y;\n }).interpolate('linear');\n // Apply line and style\n if (this.canTransition()) {\n selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('d', this.line).style(this.layout.style);\n } else {\n selection.attr('d', this.line).style(this.layout.style);\n }\n // Remove old elements as needed\n selection.exit().remove();\n };\n return this;\n });\n 'use strict';\n /**\n * Scatter Data Layer\n * Implements a standard scatter plot\n * @class LocusZoom.DataLayers.scatter\n */\n LocusZoom.DataLayers.add('scatter', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'circle',\n tooltip_positioning: 'horizontal',\n color: '#888888',\n fill_opacity: 1,\n y_axis: { axis: 1 },\n id_field: 'id'\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Extra default for layout spacing\n // Not in default layout since that would make the label attribute always present\n if (layout.label && isNaN(layout.label.spacing)) {\n layout.label.spacing = 4;\n }\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n // Reimplement the positionTooltip() method to be scatter-specific\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var offset = Math.sqrt(point_size / Math.PI);\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var border_radius = 6;\n // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n if (this.layout.tooltip_positioning === 'vertical') {\n // Position horizontally centered above the point\n var offset_right = Math.max(tooltip_box.width / 2 - x_center, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - tooltip_box.width / 2 - offset_left + offset_right;\n arrow_left = tooltip_box.width / 2 - arrow_width / 2 + offset_left - offset_right - offset;\n // Position vertically above the point unless there's insufficient space, then go below\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (y_center + offset)) {\n top = page_origin.y + y_center - (offset + tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + y_center + offset + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n } else {\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n if (y_center - tooltip_box.height / 2 <= 0) {\n // Too close to the top, push it down\n top = page_origin.y + y_center - 1.5 * arrow_width - border_radius;\n arrow_top = border_radius;\n } else if (y_center + tooltip_box.height / 2 >= data_layer_height) {\n // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - 2 * arrow_width - border_radius;\n } else {\n // vertically centered\n top = page_origin.y + y_center - tooltip_box.height / 2;\n arrow_top = tooltip_box.height / 2 - arrow_width;\n }\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n // Function to flip labels from being anchored at the start of the text to the end\n // Both to keep labels from running outside the data layer and also as a first\n // pass on recursive separation\n this.flip_labels = function () {\n var data_layer = this;\n var point_size = data_layer.resolveScalableParameter(data_layer.layout.point_size, {});\n var spacing = data_layer.layout.label.spacing;\n var handle_lines = Boolean(data_layer.layout.label.lines);\n var min_x = 2 * spacing;\n var max_x = data_layer.parent.layout.width - data_layer.parent.layout.margin.left - data_layer.parent.layout.margin.right - 2 * spacing;\n var flip = function (dn, dnl) {\n var dnx = +dn.attr('x');\n var text_swing = 2 * spacing + 2 * Math.sqrt(point_size);\n if (handle_lines) {\n var dnlx2 = +dnl.attr('x2');\n var line_swing = spacing + 2 * Math.sqrt(point_size);\n }\n if (dn.style('text-anchor') === 'start') {\n dn.style('text-anchor', 'end');\n dn.attr('x', dnx - text_swing);\n if (handle_lines) {\n dnl.attr('x2', dnlx2 - line_swing);\n }\n } else {\n dn.style('text-anchor', 'start');\n dn.attr('x', dnx + text_swing);\n if (handle_lines) {\n dnl.attr('x2', dnlx2 + line_swing);\n }\n }\n };\n // Flip any going over the right edge from the right side to the left side\n // (all labels start on the right side)\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n if (dax + abound.width + spacing > max_x) {\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n flip(da, dal);\n }\n });\n // Second pass to flip any others that haven't flipped yet if they collide with another label\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n if (da.style('text-anchor') === 'end') {\n return;\n }\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n data_layer.label_texts.each(function () {\n var b = this;\n var db = d3.select(b);\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + 2 * spacing && abound.left + abound.width + 2 * spacing > bbound.left && abound.top < bbound.top + bbound.height + 2 * spacing && abound.height + abound.top + 2 * spacing > bbound.top;\n if (collision) {\n flip(da, dal);\n // Double check that this flip didn't push the label past min_x. If it did, immediately flip back.\n dax = +da.attr('x');\n if (dax - abound.width - spacing < min_x) {\n flip(da, dal);\n }\n }\n return;\n });\n });\n };\n // Recursive function to space labels apart immediately after initial render\n // Adapted from thudfactor's fiddle here: https://jsfiddle.net/thudfactor/HdwTH/\n // TODO: Make labels also aware of data elements\n this.separate_labels = function () {\n this.seperate_iterations++;\n var data_layer = this;\n var alpha = 0.5;\n if (!this.layout.label) {\n // Guard against layout changing in the midst of iterative rerender\n return;\n }\n var spacing = this.layout.label.spacing;\n var again = false;\n data_layer.label_texts.each(function () {\n var a = this;\n var da = d3.select(a);\n var y1 = da.attr('y');\n data_layer.label_texts.each(function () {\n var b = this;\n // a & b are the same element and don't collide.\n if (a === b) {\n return;\n }\n var db = d3.select(b);\n // a & b are on opposite sides of the chart and\n // don't collide\n if (da.attr('text-anchor') !== db.attr('text-anchor')) {\n return;\n }\n // Determine if the bounding rects for the two text elements collide\n var abound = da.node().getBoundingClientRect();\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + 2 * spacing && abound.left + abound.width + 2 * spacing > bbound.left && abound.top < bbound.top + bbound.height + 2 * spacing && abound.height + abound.top + 2 * spacing > bbound.top;\n if (!collision) {\n return;\n }\n again = true;\n // If the labels collide, we'll push each\n // of the two labels up and down a little bit.\n var y2 = db.attr('y');\n var sign = abound.top < bbound.top ? 1 : -1;\n var adjust = sign * alpha;\n var new_a_y = +y1 - adjust;\n var new_b_y = +y2 + adjust;\n // Keep new values from extending outside the data layer\n var min_y = 2 * spacing;\n var max_y = data_layer.parent.layout.height - data_layer.parent.layout.margin.top - data_layer.parent.layout.margin.bottom - 2 * spacing;\n var delta;\n if (new_a_y - abound.height / 2 < min_y) {\n delta = +y1 - new_a_y;\n new_a_y = +y1;\n new_b_y += delta;\n } else if (new_b_y - bbound.height / 2 < min_y) {\n delta = +y2 - new_b_y;\n new_b_y = +y2;\n new_a_y += delta;\n }\n if (new_a_y + abound.height / 2 > max_y) {\n delta = new_a_y - +y1;\n new_a_y = +y1;\n new_b_y -= delta;\n } else if (new_b_y + bbound.height / 2 > max_y) {\n delta = new_b_y - +y2;\n new_b_y = +y2;\n new_a_y -= delta;\n }\n da.attr('y', new_a_y);\n db.attr('y', new_b_y);\n });\n });\n if (again) {\n // Adjust lines to follow the labels\n if (data_layer.layout.label.lines) {\n var label_elements = data_layer.label_texts[0];\n data_layer.label_lines.attr('y2', function (d, i) {\n var label_line = d3.select(label_elements[i]);\n return label_line.attr('y');\n });\n }\n // After ~150 iterations we're probably beyond diminising returns, so stop recursing\n if (this.seperate_iterations < 150) {\n setTimeout(function () {\n this.separate_labels();\n }.bind(this), 1);\n }\n }\n };\n // Implement the main render function\n this.render = function () {\n var data_layer = this;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n if (this.layout.label) {\n // Apply filters to generate a filtered data set\n var filtered_data = this.data.filter(function (d) {\n if (!data_layer.layout.label.filters) {\n return true;\n } else {\n // Start by assuming a match, run through all filters to test if not a match on any one\n var match = true;\n data_layer.layout.label.filters.forEach(function (filter) {\n var field_value = new LocusZoom.Data.Field(filter.field).resolve(d);\n if ([\n '!=',\n '='\n ].indexOf(filter.operator) === -1 && isNaN(field_value)) {\n // If the filter can only be used with numbers, then the value must be numeric.\n match = false;\n } else {\n switch (filter.operator) {\n case '<':\n if (!(field_value < filter.value)) {\n match = false;\n }\n break;\n case '<=':\n if (!(field_value <= filter.value)) {\n match = false;\n }\n break;\n case '>':\n if (!(field_value > filter.value)) {\n match = false;\n }\n break;\n case '>=':\n if (!(field_value >= filter.value)) {\n match = false;\n }\n break;\n case '=':\n if (!(field_value === filter.value)) {\n match = false;\n }\n break;\n case '!=':\n // Deliberately allow weak comparisons to test for \"anything with a value present\" (null or undefined)\n // eslint-disable-next-line eqeqeq\n if (field_value == filter.value) {\n match = false;\n }\n break;\n default:\n // If we got here the operator is not valid, so the filter should fail\n match = false;\n break;\n }\n }\n });\n return match;\n }\n });\n // Render label groups\n var self = this;\n this.label_groups = this.svg.group.selectAll('g.lz-data_layer-' + this.layout.type + '-label').data(filtered_data, function (d) {\n return d[self.layout.id_field] + '_label';\n });\n this.label_groups.enter().append('g').attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n // Render label texts\n if (this.label_texts) {\n this.label_texts.remove();\n }\n this.label_texts = this.label_groups.append('text').attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_texts.text(function (d) {\n return LocusZoom.parseFields(d, data_layer.layout.label.text || '');\n }).style(data_layer.layout.label.style || {}).attr({\n 'x': function (d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]) + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d)) + data_layer.layout.label.spacing;\n if (isNaN(x)) {\n x = -1000;\n }\n return x;\n },\n 'y': function (d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) {\n y = -1000;\n }\n return y;\n },\n 'text-anchor': function () {\n return 'start';\n }\n });\n // Render label lines\n if (data_layer.layout.label.lines) {\n if (this.label_lines) {\n this.label_lines.remove();\n }\n this.label_lines = this.label_groups.append('line').attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_lines.style(data_layer.layout.label.lines.style || {}).attr({\n 'x1': function (d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]);\n if (isNaN(x)) {\n x = -1000;\n }\n return x;\n },\n 'y1': function (d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) {\n y = -1000;\n }\n return y;\n },\n 'x2': function (d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]) + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d)) + data_layer.layout.label.spacing / 2;\n if (isNaN(x)) {\n x = -1000;\n }\n return x;\n },\n 'y2': function (d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) {\n y = -1000;\n }\n return y;\n }\n });\n }\n // Remove labels when they're no longer in the filtered data set\n this.label_groups.exit().remove();\n } else {\n // If the layout definition has changed (& no longer specifies labels), strip any previously rendered\n if (this.label_groups) {\n this.label_groups.remove();\n }\n if (this.label_lines) {\n this.label_lines.remove();\n }\n }\n // Generate main scatter data elements\n var selection = this.svg.group.selectAll('path.lz-data_layer-' + this.layout.type).data(this.data, function (d) {\n return d[this.layout.id_field];\n }.bind(this));\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n selection.enter().append('path').attr('class', 'lz-data_layer-' + this.layout.type).attr('id', function (d) {\n return this.getElementId(d);\n }.bind(this)).attr('transform', 'translate(0,' + initial_y + ')');\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function (d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) {\n x = -1000;\n }\n if (isNaN(y)) {\n y = -1000;\n }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var fill = function (d) {\n return this.resolveScalableParameter(this.layout.color, d);\n }.bind(this);\n var fill_opacity = function (d) {\n return this.resolveScalableParameter(this.layout.fill_opacity, d);\n }.bind(this);\n var shape = d3.svg.symbol().size(function (d) {\n return this.resolveScalableParameter(this.layout.point_size, d);\n }.bind(this)).type(function (d) {\n return this.resolveScalableParameter(this.layout.point_shape, d);\n }.bind(this));\n // Apply position and color, using a transition if necessary\n if (this.canTransition()) {\n selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('transform', transform).attr('fill', fill).attr('fill-opacity', fill_opacity).attr('d', shape);\n } else {\n selection.attr('transform', transform).attr('fill', fill).attr('fill-opacity', fill_opacity).attr('d', shape);\n }\n // Remove old elements as needed\n selection.exit().remove();\n // Apply default event emitters to selection\n selection.on('click.event_emitter', function (element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n // Apply mouse behaviors\n this.applyBehaviors(selection);\n // Apply method to keep labels from overlapping each other\n if (this.layout.label) {\n this.flip_labels();\n this.seperate_iterations = 0;\n this.separate_labels();\n // Apply default event emitters to selection\n this.label_texts.on('click.event_emitter', function (element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n // Extend mouse behaviors to labels\n this.applyBehaviors(this.label_texts);\n }\n };\n // Method to set a passed element as the LD reference in the plot-level state\n this.makeLDReference = function (element) {\n var ref = null;\n if (typeof element == 'undefined') {\n throw new Error('makeLDReference requires one argument of any type');\n } else if (typeof element == 'object') {\n if (this.layout.id_field && typeof element[this.layout.id_field] != 'undefined') {\n ref = element[this.layout.id_field].toString();\n } else if (typeof element['id'] != 'undefined') {\n ref = element['id'].toString();\n } else {\n ref = element.toString();\n }\n } else {\n ref = element.toString();\n }\n this.parent_plot.applyState({ ldrefvar: ref });\n };\n return this;\n });\n /**\n * A scatter plot in which the x-axis represents categories, rather than individual positions.\n * For example, this can be used by PheWAS plots to show related groups. This plot allows the categories to be\n * determined dynamically when data is first loaded.\n *\n * @class LocusZoom.DataLayers.category_scatter\n * @augments LocusZoom.DataLayers.scatter\n */\n LocusZoom.DataLayers.extend('scatter', 'category_scatter', {\n /**\n * This plot layer makes certain assumptions about the data passed in. Transform the raw array of records from\n * the datasource to prepare it for plotting, as follows:\n * 1. The scatter plot assumes that all records are given in sequence (pre-grouped by `category_field`)\n * 2. It assumes that all records have an x coordinate for individual plotting\n * @private\n */\n _prepareData: function () {\n var xField = this.layout.x_axis.field || 'x';\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n // Sort the data so that things in the same category are adjacent (case-insensitive by specified field)\n var sourceData = this.data.sort(function (a, b) {\n var ak = a[category_field];\n var bk = b[category_field];\n var av = typeof ak === 'string' ? ak.toLowerCase() : ak;\n var bv = typeof bk === 'string' ? bk.toLowerCase() : bk;\n return av === bv ? 0 : av < bv ? -1 : 1;\n });\n sourceData.forEach(function (d, i) {\n // Implementation detail: Scatter plot requires specifying an x-axis value, and most datasources do not\n // specify plotting positions. If a point is missing this field, fill in a synthetic value.\n d[xField] = d[xField] || i;\n });\n return sourceData;\n },\n /**\n * Identify the unique categories on the plot, and update the layout with an appropriate color scheme.\n * Also identify the min and max x value associated with the category, which will be used to generate ticks\n * @private\n * @returns {Object.} Series of entries used to build category name ticks {category_name: [min_x, max_x]}\n */\n _generateCategoryBounds: function () {\n // TODO: API may return null values in category_field; should we add placeholder category label?\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n var xField = this.layout.x_axis.field || 'x';\n var uniqueCategories = {};\n this.data.forEach(function (item) {\n var category = item[category_field];\n var x = item[xField];\n var bounds = uniqueCategories[category] || [\n x,\n x\n ];\n uniqueCategories[category] = [\n Math.min(bounds[0], x),\n Math.max(bounds[1], x)\n ];\n });\n var categoryNames = Object.keys(uniqueCategories);\n this._setDynamicColorScheme(categoryNames);\n return uniqueCategories;\n },\n /**\n * This layer relies on defining its own category-based color scheme. Find the correct color config object to\n * be modified.\n * @param [from_source]\n * @returns {Object} A mutable reference to the layout configuration object\n * @private\n */\n _getColorScale: function (from_source) {\n from_source = from_source || this.layout;\n // If the layout does not use a supported coloring scheme, or is already complete, this method should do nothing\n // For legacy reasons, layouts can specify color as an object (only one way to set color), as opposed to the\n // preferred mechanism of array (multiple coloring options)\n var color_params = from_source.color || [];\n // Object or scalar, no other options allowed\n if (Array.isArray(color_params)) {\n color_params = color_params.find(function (item) {\n return item.scale_function === 'categorical_bin';\n });\n }\n if (!color_params || color_params.scale_function !== 'categorical_bin') {\n throw new Error('This layer requires that color options be provided as a `categorical_bin`');\n }\n return color_params;\n },\n /**\n * Automatically define a color scheme for the layer based on data returned from the server.\n * If part of the color scheme has been specified, it will fill in remaining missing information.\n *\n * There are three scenarios:\n * 1. The layout does not specify either category names or (color) values. Dynamically build both based on\n * the data and update the layout.\n * 2. The layout specifies colors, but not categories. Use that exact color information provided, and dynamically\n * determine what categories are present in the data. (cycle through the available colors, reusing if there\n * are a lot of categories)\n * 3. The layout specifies exactly what colors and categories to use (and they match the data!). This is useful to\n * specify an explicit mapping between color scheme and category names, when you want to be sure that the\n * plot matches a standard color scheme.\n * (If the layout specifies categories that do not match the data, the user specified categories will be ignored)\n *\n * This method will only act if the layout defines a `categorical_bin` scale function for coloring. It may be\n * overridden in a subclass to suit other types of coloring methods.\n *\n * @param {String[]} categoryNames\n * @private\n */\n _setDynamicColorScheme: function (categoryNames) {\n var colorParams = this._getColorScale(this.layout).parameters;\n var baseParams = this._getColorScale(this._base_layout).parameters;\n if (baseParams.categories.length && baseParams.values.length) {\n // If there are preset category/color combos, make sure that they apply to the actual dataset\n var parameters_categories_hash = {};\n baseParams.categories.forEach(function (category) {\n parameters_categories_hash[category] = 1;\n });\n if (categoryNames.every(function (name) {\n return parameters_categories_hash.hasOwnProperty(name);\n })) {\n // The layout doesn't have to specify categories in order, but make sure they are all there\n colorParams.categories = baseParams.categories;\n } else {\n colorParams.categories = categoryNames;\n }\n } else {\n colorParams.categories = categoryNames;\n }\n // Prefer user-specified colors if provided. Make sure that there are enough colors for all the categories.\n var colors;\n if (baseParams.values.length) {\n colors = baseParams.values;\n } else {\n var color_scale = categoryNames.length <= 10 ? d3.scale.category10 : d3.scale.category20;\n colors = color_scale().range();\n }\n while (colors.length < categoryNames.length) {\n colors = colors.concat(colors);\n }\n colors = colors.slice(0, categoryNames.length);\n // List of hex values, should be of same length as categories array\n colorParams.values = colors;\n },\n /**\n *\n * @param dimension\n * @param {Object} [config] Parameters that customize how ticks are calculated (not style)\n * @param {('left'|'center'|'right')} [config.position='left'] Align ticks with the center or edge of category\n * @returns {Array}\n */\n getTicks: function (dimension, config) {\n // Overrides parent method\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier');\n }\n var position = config.position || 'left';\n if ([\n 'left',\n 'center',\n 'right'\n ].indexOf(position) === -1) {\n throw new Error('Invalid tick position');\n }\n var categoryBounds = this._categories;\n if (!categoryBounds || !Object.keys(categoryBounds).length) {\n return [];\n }\n if (dimension === 'y') {\n return [];\n }\n if (dimension === 'x') {\n // If colors have been defined by this layer, use them to make tick colors match scatterplot point colors\n var colors = this._getColorScale(this.layout);\n var knownCategories = colors.parameters.categories || [];\n var knownColors = colors.parameters.values || [];\n return Object.keys(categoryBounds).map(function (category, index) {\n var bounds = categoryBounds[category];\n var xPos;\n switch (position) {\n case 'left':\n xPos = bounds[0];\n break;\n case 'center':\n // Center tick under one or many elements as appropriate\n var diff = bounds[1] - bounds[0];\n xPos = bounds[0] + (diff !== 0 ? diff : bounds[0]) / 2;\n break;\n case 'right':\n xPos = bounds[1];\n break;\n }\n return {\n x: xPos,\n text: category,\n style: { 'fill': knownColors[knownCategories.indexOf(category)] || '#000000' }\n };\n });\n }\n },\n applyCustomDataMethods: function () {\n this.data = this._prepareData();\n /**\n * Define category names and extents (boundaries) for plotting. TODO: properties in constructor\n * @member {Object.} Category names and extents, in the form {category_name: [min_x, max_x]}\n */\n this._categories = this._generateCategoryBounds();\n return this;\n }\n });\n /* global LocusZoom */\n 'use strict';\n /**\n *\n * LocusZoom has various singleton objects that are used for registering functions or classes.\n * These objects provide safe, standard methods to redefine or delete existing functions/classes\n * as well as define new custom functions/classes to be used in a plot.\n *\n * @namespace Singletons\n */\n /*\n * The Collection of \"Known\" Data Sources. This registry is used internally by the `DataSources` class\n * @class\n * @static\n */\n LocusZoom.KnownDataSources = function () {\n /** @lends LocusZoom.KnownDataSources */\n var obj = {};\n /* @member {function[]} */\n var sources = [];\n var findSourceByName = function (x) {\n for (var i = 0; i < sources.length; i++) {\n if (!sources[i].SOURCE_NAME) {\n throw new Error('KnownDataSources at position ' + i + ' does not have a \\'SOURCE_NAME\\' static property');\n }\n if (sources[i].SOURCE_NAME === x) {\n return sources[i];\n }\n }\n return null;\n };\n /**\n * Identify the datasource associated with a given name\n * @param {String} name\n * @returns {function} The constructor for the data source; will usually extend `Data.Source`\n */\n obj.get = function (name) {\n return findSourceByName(name);\n };\n /**\n * Register a data source constructor so that it may be located by name\n * @param {function} source A constructor function for a data source; will usually extend `Data.Source`,\n * and should have a `SOURCE_NAME` property\n */\n obj.add = function (source) {\n if (!source.SOURCE_NAME) {\n console.warn('Data source added does not have a SOURCE_NAME');\n }\n sources.push(source);\n };\n /**\n * Create a custom source type that extends the behavior of an existing source, and registers that\n * source by the provided name\n * @param {String} parent_name The name of a previously registered data source type to use as a template\n * @param {String} source_name The new name to use when registering this data source\n * @param {Object} overrides An object of additional properties and methods to add/override behavior\n * @returns {LocusZoom.Data.Source} The newly defined class for this source\n */\n obj.extend = function (parent_name, source_name, overrides) {\n var parent = findSourceByName(parent_name);\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered data source');\n }\n if (!source_name) {\n throw new Error('Must provide a name for the new data source');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n child.SOURCE_NAME = source_name;\n sources.push(child);\n return child;\n };\n /** @deprecated */\n obj.push = function (source) {\n console.warn('Warning: KnownDataSources.push() is deprecated. Use .add() instead');\n obj.add(source);\n };\n /**\n * List the names of all registered datasources\n * @returns {String[]}\n */\n obj.list = function () {\n return sources.map(function (x) {\n return x.SOURCE_NAME;\n });\n };\n /**\n * Create a datasource instance\n * @param {String} name The name of the desired datasource to instantiate (must be defined in the registry)\n * @returns {LocusZoom.Data.Source}\n */\n obj.create = function (name) {\n //create new object (pass additional parameters to constructor)\n var newObj = findSourceByName(name);\n if (newObj) {\n var params = arguments;\n params[0] = null;\n return new (Function.prototype.bind.apply(newObj, params))();\n } else {\n throw new Error('Unable to find data source for name: ' + name);\n }\n };\n /**\n * Get the array of all registered constructors\n * Generally only used for unit tests internally\n * @private\n * @returns {function[]}\n */\n obj.getAll = function () {\n return sources;\n };\n /**\n * Register an entire collection of data sources\n * Generally only used for unit tests internally\n * @private\n * @param {function[]} x An array of datasource constructors\n */\n obj.setAll = function (x) {\n sources = x;\n };\n /**\n * Unregister all known data sources\n * Generally only used for unit tests internally\n * @private\n */\n obj.clear = function () {\n sources = [];\n };\n return obj;\n }();\n /**************************\n * Transformation Functions\n *\n * Singleton for formatting or transforming a single input, for instance turning raw p values into negative log10 form\n * Transformation functions are chainable with a pipe on a field name, like so: \"pvalue|neglog10\"\n *\n * NOTE: Because these functions are chainable the FUNCTION is returned by get(), not the result of that function.\n *\n * All transformation functions must accept an object of parameters and a value to process.\n * @class\n */\n LocusZoom.TransformationFunctions = function () {\n /** @lends LocusZoom.TransformationFunctions */\n var obj = {};\n var transformations = {};\n var getTrans = function (name) {\n if (!name) {\n return null;\n }\n var fun = transformations[name];\n if (fun) {\n return fun;\n } else {\n throw new Error('transformation ' + name + ' not found');\n }\n };\n //a single transformation with any parameters\n //(parameters not currently supported)\n var parseTrans = function (name) {\n return getTrans(name);\n };\n //a \"raw\" transformation string with a leading pipe\n //and one or more transformations\n var parseTransString = function (x) {\n var funs = [];\n var re = /\\|([^|]+)/g;\n var result;\n while ((result = re.exec(x)) !== null) {\n funs.push(result[1]);\n }\n if (funs.length === 1) {\n return parseTrans(funs[0]);\n } else if (funs.length > 1) {\n return function (x) {\n var val = x;\n for (var i = 0; i < funs.length; i++) {\n val = parseTrans(funs[i])(val);\n }\n return val;\n };\n }\n return null;\n };\n /**\n * Retrieve a transformation function by name\n * @param {String} name The name of the transformation function to retrieve. May optionally be prefixed with a\n * pipe (`|`) when chaining multiple transformation functions.\n * @returns {function} The constructor for the transformation function\n */\n obj.get = function (name) {\n if (name && name.substring(0, 1) === '|') {\n return parseTransString(name);\n } else {\n return parseTrans(name);\n }\n };\n /**\n * Internal logic that registers a transformation function\n * @protected\n * @param {String} name\n * @param {function} fn\n */\n obj.set = function (name, fn) {\n if (name.substring(0, 1) === '|') {\n throw new Error('transformation name should not start with a pipe');\n } else {\n if (fn) {\n transformations[name] = fn;\n } else {\n delete transformations[name];\n }\n }\n };\n /**\n * Register a transformation function\n * @param {String} name\n * @param {function} fn A transformation function (should accept one argument with the value)\n */\n obj.add = function (name, fn) {\n if (transformations[name]) {\n throw new Error('transformation already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n /**\n * List the names of all registered transformation functions\n * @returns {String[]}\n */\n obj.list = function () {\n return Object.keys(transformations);\n };\n return obj;\n }();\n /**\n * Return the -log (base 10)\n * @function neglog10\n */\n LocusZoom.TransformationFunctions.add('neglog10', function (x) {\n if (isNaN(x) || x <= 0) {\n return null;\n }\n return -Math.log(x) / Math.LN10;\n });\n /**\n * Convert a number from logarithm to scientific notation. Useful for, eg, a datasource that returns -log(p) by default\n * @function logtoscinotation\n */\n LocusZoom.TransformationFunctions.add('logtoscinotation', function (x) {\n if (isNaN(x)) {\n return 'NaN';\n }\n if (x === 0) {\n return '1';\n }\n var exp = Math.ceil(x);\n var diff = exp - x;\n var base = Math.pow(10, diff);\n if (exp === 1) {\n return (base / 10).toFixed(4);\n } else if (exp === 2) {\n return (base / 100).toFixed(3);\n } else {\n return base.toFixed(2) + ' \\xD7 10^-' + exp;\n }\n });\n /**\n * Represent a number in scientific notation\n * @function scinotation\n * @param {Number} x\n * @returns {String}\n */\n LocusZoom.TransformationFunctions.add('scinotation', function (x) {\n if (isNaN(x)) {\n return 'NaN';\n }\n if (x === 0) {\n return '0';\n }\n var abs = Math.abs(x);\n var log;\n if (abs > 1) {\n log = Math.ceil(Math.log(abs) / Math.LN10);\n } else {\n // 0...1\n log = Math.floor(Math.log(abs) / Math.LN10);\n }\n if (Math.abs(log) <= 3) {\n return x.toFixed(3);\n } else {\n return x.toExponential(2).replace('+', '').replace('e', ' \\xD7 10^');\n }\n });\n /**\n * URL-encode the provided text, eg for constructing hyperlinks\n * @function urlencode\n * @param {String} str\n */\n LocusZoom.TransformationFunctions.add('urlencode', function (str) {\n return encodeURIComponent(str);\n });\n /**\n * HTML-escape user entered values for use in constructed HTML fragments\n *\n * For example, this filter can be used on tooltips with custom HTML display\n * @function htmlescape\n * @param {String} str HTML-escape the provided value\n */\n LocusZoom.TransformationFunctions.add('htmlescape', function (str) {\n if (!str) {\n return '';\n }\n str = str + '';\n return str.replace(/['\"<>&`]/g, function (s) {\n switch (s) {\n case '\\'':\n return ''';\n case '\"':\n return '"';\n case '<':\n return '<';\n case '>':\n return '>';\n case '&':\n return '&';\n case '`':\n return '`';\n }\n });\n });\n /**\n * Singleton for accessing/storing functions that will convert arbitrary data points to values in a given scale\n * Useful for anything that needs to scale discretely with data (e.g. color, point size, etc.)\n *\n * A Scale Function can be thought of as a modifier to a layout directive that adds extra logic to how a piece of data\n * can be resolved to a value.\n *\n * All scale functions must accept an object of parameters and a value to process.\n * @class\n * @static\n */\n LocusZoom.ScaleFunctions = function () {\n /** @lends LocusZoom.ScaleFunctions */\n var obj = {};\n var functions = {};\n /**\n * Find a scale function and return it. If parameters and values are passed, calls the function directly; otherwise\n * returns a callable.\n * @param {String} name\n * @param {Object} [parameters] Configuration parameters specific to the specified scale function\n * @param {*} [value] The value to operate on\n * @returns {*}\n */\n obj.get = function (name, parameters, value) {\n if (!name) {\n return null;\n } else if (functions[name]) {\n if (typeof parameters === 'undefined' && typeof value === 'undefined') {\n return functions[name];\n } else {\n return functions[name](parameters, value);\n }\n } else {\n throw new Error('scale function [' + name + '] not found');\n }\n };\n /**\n * @protected\n * @param {String} name The name of the function to set/unset\n * @param {Function} [fn] The function to register. If blank, removes this function name from the registry.\n */\n obj.set = function (name, fn) {\n if (fn) {\n functions[name] = fn;\n } else {\n delete functions[name];\n }\n };\n /**\n * Add a new scale function to the registry\n * @param {String} name The name of the scale function\n * @param {function} fn A scale function that accepts two parameters: an object of configuration and a value\n */\n obj.add = function (name, fn) {\n if (functions[name]) {\n throw new Error('scale function already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n /**\n * List the names of all registered scale functions\n * @returns {String[]}\n */\n obj.list = function () {\n return Object.keys(functions);\n };\n return obj;\n }();\n /**\n * Basic conditional function to evaluate the value of the input field and return based on equality.\n * @param {Object} parameters\n * @param {*} parameters.field_value The value against which to test the input value.\n * @param {*} parameters.then The value to return if the input value matches the field value\n * @param {*} parameters.else The value to return if the input value does not match the field value. Optional. If not\n * defined this scale function will return null (or value of null_value parameter, if defined) when input value fails\n * to match field_value.\n * @param {*} input value\n */\n LocusZoom.ScaleFunctions.add('if', function (parameters, input) {\n if (typeof input == 'undefined' || parameters.field_value !== input) {\n if (typeof parameters.else != 'undefined') {\n return parameters.else;\n } else {\n return null;\n }\n } else {\n return parameters.then;\n }\n });\n /**\n * Function to sort numerical values into bins based on numerical break points. Will only operate on numbers and\n * return null (or value of null_value parameter, if defined) if provided a non-numeric input value. Parameters:\n * @function numerical_bin\n * @param {Object} parameters\n * @param {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter. If the input value is greater than or equal to break n and less than\n * or equal to break n+1 (or break n+1 doesn't exist) then returned value is the nth entry in the values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against break points. Must be of\n * equal length to breaks parameter. Each entry n represents the value to return if the input value is greater than\n * or equal to break n and less than or equal to break n+1 (or break n+1 doesn't exist).\n * @param {*} null_value\n * @param {*} input value\n * @returns\n */\n LocusZoom.ScaleFunctions.add('numerical_bin', function (parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n if (typeof input == 'undefined' || input === null || isNaN(+input)) {\n return parameters.null_value ? parameters.null_value : null;\n }\n var threshold = breaks.reduce(function (prev, curr) {\n if (+input < prev || +input >= prev && +input < curr) {\n return prev;\n } else {\n return curr;\n }\n });\n return values[breaks.indexOf(threshold)];\n });\n /**\n * Function to sort values of any type into bins based on direct equality testing with a list of categories.\n * Will return null if provided an input value that does not match to a listed category.\n * @function categorical_bin\n * @param {Object} parameters\n * @param {Array} parameters.categories Array of values against which to evaluate the input value. Must be of equal\n * length to values parameter. If the input value is equal to category n then returned value is the nth entry in the\n * values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against categories. Must be of equal\n * length to categories parameter. Each entry n represents the value to return if the input value is equal to the nth\n * value in the categories parameter.\n * @param {*} parameters.null_value Value to return if the input value fails to match to any categories. Optional.\n */\n LocusZoom.ScaleFunctions.add('categorical_bin', function (parameters, value) {\n if (typeof value == 'undefined' || parameters.categories.indexOf(value) === -1) {\n return parameters.null_value ? parameters.null_value : null;\n } else {\n return parameters.values[parameters.categories.indexOf(value)];\n }\n });\n /**\n * Function for continuous interpolation of numerical values along a gradient with arbitrarily many break points.\n * @function interpolate\n * @parameters {Object} parameters\n * @parameters {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter and contain at least two elements. Input value will be evaluated for\n * relative position between two break points n and n+1 and the returned value will be interpolated at a relative\n * position between values n and n+1.\n * @parameters {*[]} parameters.values Array of values to interpolate and return given evaluations against break\n * points. Must be of equal length to breaks parameter and contain at least two elements. Each entry n represents\n * the value to return if the input value matches the nth entry in breaks exactly. Note that this scale function\n * uses d3.interpolate to provide for effective interpolation of many different value types, including numbers,\n * colors, shapes, etc.\n * @parameters {*} parameters.null_value\n */\n LocusZoom.ScaleFunctions.add('interpolate', function (parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n var nullval = parameters.null_value ? parameters.null_value : null;\n if (breaks.length < 2 || breaks.length !== values.length) {\n return nullval;\n }\n if (typeof input == 'undefined' || input === null || isNaN(+input)) {\n return nullval;\n }\n if (+input <= parameters.breaks[0]) {\n return values[0];\n } else if (+input >= parameters.breaks[parameters.breaks.length - 1]) {\n return values[breaks.length - 1];\n } else {\n var upper_idx = null;\n breaks.forEach(function (brk, idx) {\n if (!idx) {\n return;\n }\n if (breaks[idx - 1] <= +input && breaks[idx] >= +input) {\n upper_idx = idx;\n }\n });\n if (upper_idx === null) {\n return nullval;\n }\n var normalized_input = (+input - breaks[upper_idx - 1]) / (breaks[upper_idx] - breaks[upper_idx - 1]);\n if (!isFinite(normalized_input)) {\n return nullval;\n }\n return d3.interpolate(values[upper_idx - 1], values[upper_idx])(normalized_input);\n }\n });\n /* global LocusZoom */\n 'use strict';\n /**\n * A Dashboard is an HTML element used for presenting arbitrary user interface components. Dashboards are anchored\n * to either the entire Plot or to individual Panels.\n *\n * Each dashboard is an HTML-based (read: not SVG) collection of components used to display information or provide\n * user interface. Dashboards can exist on entire plots, where their visibility is permanent and vertically adjacent\n * to the plot, or on individual panels, where their visibility is tied to a behavior (e.g. a mouseover) and is as\n * an overlay.\n * @class\n */\n LocusZoom.Dashboard = function (parent) {\n // parent must be a locuszoom plot or panel\n if (!(parent instanceof LocusZoom.Plot) && !(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create dashboard, parent must be a locuszoom plot or panel');\n }\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.dashboard';\n /** @member {('plot'|'panel')} */\n this.type = this.parent instanceof LocusZoom.Plot ? 'plot' : 'panel';\n /** @member {LocusZoom.Plot} */\n this.parent_plot = this.type === 'plot' ? this.parent : this.parent.parent;\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {LocusZoom.Dashboard.Component[]} */\n this.components = [];\n /**\n * The timer identifier as returned by setTimeout\n * @member {Number}\n */\n this.hide_timeout = null;\n /**\n * Whether to hide the dashboard. Can be overridden by a child component. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n // TODO: Return value from constructor function?\n return this.initialize();\n };\n /**\n * Prepare the dashboard for first use: generate all component instances for this dashboard, based on the provided\n * layout of the parent. Connects event listeners and shows/hides as appropriate.\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.initialize = function () {\n // Parse layout to generate component instances\n if (Array.isArray(this.parent.layout.dashboard.components)) {\n this.parent.layout.dashboard.components.forEach(function (layout) {\n try {\n var component = LocusZoom.Dashboard.Components.get(layout.type, layout, this);\n this.components.push(component);\n } catch (e) {\n console.warn(e);\n }\n }.bind(this));\n }\n // Add mouseover event handlers to show/hide panel dashboard\n if (this.type === 'panel') {\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseover.' + this.id, function () {\n clearTimeout(this.hide_timeout);\n if (!this.selector || this.selector.style('visibility') === 'hidden') {\n this.show();\n }\n }.bind(this));\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseout.' + this.id, function () {\n clearTimeout(this.hide_timeout);\n this.hide_timeout = setTimeout(function () {\n this.hide();\n }.bind(this), 300);\n }.bind(this));\n }\n return this;\n };\n /**\n * Whether to persist the dashboard. Returns true if at least one component should persist, or if the panel is engaged\n * in an active drag event.\n * @returns {boolean}\n */\n LocusZoom.Dashboard.prototype.shouldPersist = function () {\n if (this.persist) {\n return true;\n }\n var persist = false;\n // Persist if at least one component should also persist\n this.components.forEach(function (component) {\n persist = persist || component.shouldPersist();\n });\n // Persist if in a parent drag event\n persist = persist || (this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.dragging);\n return !!persist;\n };\n /**\n * Make the dashboard appear. If it doesn't exist yet create it, including creating/positioning all components within,\n * and make sure it is set to be visible.\n */\n LocusZoom.Dashboard.prototype.show = function () {\n if (!this.selector) {\n switch (this.type) {\n case 'plot':\n this.selector = d3.select(this.parent.svg.node().parentNode).insert('div', ':first-child');\n break;\n case 'panel':\n this.selector = d3.select(this.parent.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip, .lz-dashboard-menu, .lz-curtain').classed('lz-panel-dashboard', true);\n break;\n }\n this.selector.classed('lz-dashboard', true).classed('lz-' + this.type + '-dashboard', true).attr('id', this.id);\n }\n this.components.forEach(function (component) {\n component.show();\n });\n this.selector.style({ visibility: 'visible' });\n return this.update();\n };\n /**\n * Update the dashboard and rerender all child components. This can be called whenever plot state changes.\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.update = function () {\n if (!this.selector) {\n return this;\n }\n this.components.forEach(function (component) {\n component.update();\n });\n return this.position();\n };\n /**\n * Position the dashboard (and child components) within the panel\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.position = function () {\n if (!this.selector) {\n return this;\n }\n // Position the dashboard itself (panel only)\n if (this.type === 'panel') {\n var page_origin = this.parent.getPageOrigin();\n var top = (page_origin.y + 3.5).toString() + 'px';\n var left = page_origin.x.toString() + 'px';\n var width = (this.parent.layout.width - 4).toString() + 'px';\n this.selector.style({\n position: 'absolute',\n top: top,\n left: left,\n width: width\n });\n }\n // Recursively position components\n this.components.forEach(function (component) {\n component.position();\n });\n return this;\n };\n /**\n * Hide the dashboard (make invisible but do not destroy). Will do nothing if `shouldPersist` returns true.\n *\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.hide = function () {\n if (!this.selector || this.shouldPersist()) {\n return this;\n }\n this.components.forEach(function (component) {\n component.hide();\n });\n this.selector.style({ visibility: 'hidden' });\n return this;\n };\n /**\n * Completely remove dashboard and all child components. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.destroy = function (force) {\n if (typeof force == 'undefined') {\n force = false;\n }\n if (!this.selector) {\n return this;\n }\n if (this.shouldPersist() && !force) {\n return this;\n }\n this.components.forEach(function (component) {\n component.destroy(true);\n });\n this.components = [];\n this.selector.remove();\n this.selector = null;\n return this;\n };\n /**\n *\n * A dashboard component is an empty div rendered on a dashboard that can display custom\n * html of user interface elements. LocusZoom.Dashboard.Components is a singleton used to\n * define and manage an extendable collection of dashboard components.\n * (e.g. by LocusZoom.Dashboard.Components.add())\n * @class\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @param {('left'|'right')} [layout.position='left'] Whether to float the component left or right.\n * @param {('start'|'middle'|'end')} [layout.group_position] Buttons can optionally be gathered into a visually\n * distinctive group whose elements are closer together. If a button is identified as the start or end of a group,\n * it will be drawn with rounded corners and an extra margin of spacing from any button not part of the group.\n * For example, the region_nav_plot dashboard is a defined as a group.\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple'} [layout.color='gray'] Color scheme for the\n * component. Applies to buttons and menus.\n * @param {LocusZoom.Dashboard} parent The dashboard that contains this component\n*/\n LocusZoom.Dashboard.Component = function (layout, parent) {\n /** @member {Object} */\n this.layout = layout || {};\n if (!this.layout.color) {\n this.layout.color = 'gray';\n }\n /** @member {LocusZoom.Dashboard|*} */\n this.parent = parent || null;\n /**\n * Some dashboards are attached to a panel, rather than directly to a plot\n * @member {LocusZoom.Panel|null}\n */\n this.parent_panel = null;\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n /**\n * This is a reference to either the panel or the plot, depending on what the dashboard is\n * tied to. Useful when absolutely positioning dashboard components relative to their SVG anchor.\n * @member {LocusZoom.Plot|LocusZoom.Panel}\n */\n this.parent_svg = null;\n if (this.parent instanceof LocusZoom.Dashboard) {\n // TODO: when is the immediate parent *not* a dashboard?\n if (this.parent.type === 'panel') {\n this.parent_panel = this.parent.parent;\n this.parent_plot = this.parent.parent.parent;\n this.parent_svg = this.parent_panel;\n } else {\n this.parent_plot = this.parent.parent;\n this.parent_svg = this.parent_plot;\n }\n }\n /** @member {d3.selection} */\n this.selector = null;\n /**\n * If this is an interactive component, it will contain a button or menu instance that handles the interactivity.\n * There is a 1-to-1 relationship of dashboard component to button\n * @member {null|LocusZoom.Dashboard.Component.Button}\n */\n this.button = null;\n /**\n * If any single component is marked persistent, it will bubble up to prevent automatic hide behavior on a\n * component's parent dashboard. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n if (!this.layout.position) {\n this.layout.position = 'left';\n }\n // TODO: Return value in constructor\n return this;\n };\n /**\n * Perform all rendering of component, including toggling visibility to true. Will initialize and create SVG element\n * if necessary, as well as updating with new data and performing layout actions.\n */\n LocusZoom.Dashboard.Component.prototype.show = function () {\n if (!this.parent || !this.parent.selector) {\n return;\n }\n if (!this.selector) {\n var group_position = [\n 'start',\n 'middle',\n 'end'\n ].indexOf(this.layout.group_position) !== -1 ? ' lz-dashboard-group-' + this.layout.group_position : '';\n this.selector = this.parent.selector.append('div').attr('class', 'lz-dashboard-' + this.layout.position + group_position);\n if (this.layout.style) {\n this.selector.style(this.layout.style);\n }\n if (typeof this.initialize == 'function') {\n this.initialize();\n }\n }\n if (this.button && this.button.status === 'highlighted') {\n this.button.menu.show();\n }\n this.selector.style({ visibility: 'visible' });\n this.update();\n return this.position();\n };\n /**\n * Update the dashboard component with any new data or plot state as appropriate. This method performs all\n * necessary rendering steps.\n */\n LocusZoom.Dashboard.Component.prototype.update = function () {\n };\n /**\n * Place the component correctly in the plot\n * @returns {LocusZoom.Dashboard.Component}\n */\n LocusZoom.Dashboard.Component.prototype.position = function () {\n if (this.button) {\n this.button.menu.position();\n }\n return this;\n };\n /**\n * Determine whether the component should persist (will bubble up to parent dashboard)\n * @returns {boolean}\n */\n LocusZoom.Dashboard.Component.prototype.shouldPersist = function () {\n if (this.persist) {\n return true;\n }\n if (this.button && this.button.persist) {\n return true;\n }\n return false;\n };\n /**\n * Toggle visibility to hidden, unless marked as persistent\n * @returns {LocusZoom.Dashboard.Component}\n */\n LocusZoom.Dashboard.Component.prototype.hide = function () {\n if (!this.selector || this.shouldPersist()) {\n return this;\n }\n if (this.button) {\n this.button.menu.hide();\n }\n this.selector.style({ visibility: 'hidden' });\n return this;\n };\n /**\n * Completely remove component and button. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.Component.prototype.destroy = function (force) {\n if (typeof force == 'undefined') {\n force = false;\n }\n if (!this.selector) {\n return this;\n }\n if (this.shouldPersist() && !force) {\n return this;\n }\n if (this.button && this.button.menu) {\n this.button.menu.destroy();\n }\n this.selector.remove();\n this.selector = null;\n this.button = null;\n return this;\n };\n /**\n * Singleton registry of all known components\n * @class\n * @static\n */\n LocusZoom.Dashboard.Components = function () {\n /** @lends LocusZoom.Dashboard.Components */\n var obj = {};\n var components = {};\n /**\n * Create a new component instance by name\n * @param {String} name The string identifier of the desired component\n * @param {Object} layout The layout to use to create the component\n * @param {LocusZoom.Dashboard} parent The containing dashboard to use when creating the component\n * @returns {LocusZoom.Dashboard.Component}\n */\n obj.get = function (name, layout, parent) {\n if (!name) {\n return null;\n } else if (components[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for dashboard component [' + name + ']');\n } else {\n return new components[name](layout, parent);\n }\n } else {\n throw new Error('dashboard component [' + name + '] not found');\n }\n };\n /**\n * Add a new component constructor to the registry and ensure that it extends the correct parent class\n * @protected\n * @param name\n * @param component\n */\n obj.set = function (name, component) {\n if (component) {\n if (typeof component != 'function') {\n throw new Error('unable to set dashboard component [' + name + '], argument provided is not a function');\n } else {\n components[name] = component;\n components[name].prototype = new LocusZoom.Dashboard.Component();\n }\n } else {\n delete components[name];\n }\n };\n /**\n * Register a new component constructor by name\n * @param {String} name\n * @param {function} component The component constructor\n */\n obj.add = function (name, component) {\n if (components[name]) {\n throw new Error('dashboard component already exists with name: ' + name);\n } else {\n obj.set(name, component);\n }\n };\n /**\n * List the names of all registered components\n * @returns {String[]}\n */\n obj.list = function () {\n return Object.keys(components);\n };\n return obj;\n }();\n /**\n * Plots and panels may have a \"dashboard\" element suited for showing HTML components that may be interactive.\n * When components need to incorporate a generic button, or additionally a button that generates a menu, this\n * class provides much of the necessary framework.\n * @class\n * @param {LocusZoom.Dashboard.Component} parent\n */\n LocusZoom.Dashboard.Component.Button = function (parent) {\n if (!(parent instanceof LocusZoom.Dashboard.Component)) {\n throw new Error('Unable to create dashboard component button, invalid parent');\n }\n /** @member {LocusZoom.Dashboard.Component} */\n this.parent = parent;\n /** @member {LocusZoom.Dashboard.Panel} */\n this.parent_panel = this.parent.parent_panel;\n /** @member {LocusZoom.Dashboard.Plot} */\n this.parent_plot = this.parent.parent_plot;\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent_svg = this.parent.parent_svg;\n /** @member {LocusZoom.Dashboard|null|*} */\n this.parent_dashboard = this.parent.parent;\n /** @member {d3.selection} */\n this.selector = null;\n /**\n * Tag to use for the button (default: a)\n * @member {String}\n */\n this.tag = 'a';\n /**\n * TODO This method does not appear to be used anywhere\n * @param {String} tag\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTag = function (tag) {\n if (typeof tag != 'undefined') {\n this.tag = tag.toString();\n }\n return this;\n };\n /**\n * HTML for the button to show.\n * @protected\n * @member {String}\n */\n this.html = '';\n /**\n * Specify the HTML content of this button.\n * WARNING: The string provided will be inserted into the document as raw markup; XSS mitigation is the\n * responsibility of each button implementation.\n * @param {String} html\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setHtml = function (html) {\n if (typeof html != 'undefined') {\n this.html = html.toString();\n }\n return this;\n };\n /**\n * @deprecated since 0.5.6; use setHtml instead\n */\n this.setText = this.setHtml;\n /**\n * Mouseover title text for the button to show\n * @protected\n * @member {String}\n */\n this.title = '';\n /**\n * Set the mouseover title text for the button (if any)\n * @param {String} title Simple text to display\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTitle = function (title) {\n if (typeof title != 'undefined') {\n this.title = title.toString();\n }\n return this;\n };\n /**\n * Color of the button\n * @member {String}\n */\n this.color = 'gray';\n /**\n * Set the color associated with this button\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple')} color Any selection not in the preset list\n * will be replaced with gray.\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setColor = function (color) {\n if (typeof color != 'undefined') {\n if ([\n 'gray',\n 'red',\n 'orange',\n 'yellow',\n 'green',\n 'blue',\n 'purple'\n ].indexOf(color) !== -1) {\n this.color = color;\n } else {\n this.color = 'gray';\n }\n }\n return this;\n };\n /**\n * Hash of arbitrary button styles to apply as {name: value} entries\n * @protected\n * @member {Object}\n */\n this.style = {};\n /**\n * Set a collection of custom styles to be used by the button\n * @param {Object} style Hash of {name:value} entries\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setStyle = function (style) {\n if (typeof style != 'undefined') {\n this.style = style;\n }\n return this;\n };\n //\n /**\n * Method to generate a CSS class string\n * @returns {string}\n */\n this.getClass = function () {\n var group_position = [\n 'start',\n 'middle',\n 'end'\n ].indexOf(this.parent.layout.group_position) !== -1 ? ' lz-dashboard-button-group-' + this.parent.layout.group_position : '';\n return 'lz-dashboard-button lz-dashboard-button-' + this.color + (this.status ? '-' + this.status : '') + group_position;\n };\n // Permanence\n /**\n * Track internal state on whether to keep showing the button/ menu contents at the moment\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n /**\n * Configuration when defining a button: track whether this component should be allowed to keep open\n * menu/button contents in response to certain events\n * @protected\n * @member {Boolean}\n */\n this.permanent = false;\n /**\n * Allow code to change whether the button is allowed to be `permanent`\n * @param {boolean} bool\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setPermanent = function (bool) {\n if (typeof bool == 'undefined') {\n bool = true;\n } else {\n bool = Boolean(bool);\n }\n this.permanent = bool;\n if (this.permanent) {\n this.persist = true;\n }\n return this;\n };\n /**\n * Determine whether the button/menu contents should persist in response to a specific event\n * @returns {Boolean}\n */\n this.shouldPersist = function () {\n return this.permanent || this.persist;\n };\n /**\n * Button status (highlighted / disabled/ etc)\n * @protected\n * @member {String}\n */\n this.status = '';\n /**\n * Change button state\n * @param {('highlighted'|'disabled'|'')} status\n */\n this.setStatus = function (status) {\n if (typeof status != 'undefined' && [\n '',\n 'highlighted',\n 'disabled'\n ].indexOf(status) !== -1) {\n this.status = status;\n }\n return this.update();\n };\n /**\n * Toggle whether the button is highlighted\n * @param {boolean} bool If provided, explicitly set highlighted state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.highlight = function (bool) {\n if (typeof bool == 'undefined') {\n bool = true;\n } else {\n bool = Boolean(bool);\n }\n if (bool) {\n return this.setStatus('highlighted');\n } else if (this.status === 'highlighted') {\n return this.setStatus('');\n }\n return this;\n };\n /**\n * Toggle whether the button is disabled\n * @param {boolean} bool If provided, explicitly set disabled state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.disable = function (bool) {\n if (typeof bool == 'undefined') {\n bool = true;\n } else {\n bool = Boolean(bool);\n }\n if (bool) {\n return this.setStatus('disabled');\n } else if (this.status === 'disabled') {\n return this.setStatus('');\n }\n return this;\n };\n // Mouse events\n /** @member {function} */\n this.onmouseover = function () {\n };\n this.setOnMouseover = function (onmouseover) {\n if (typeof onmouseover == 'function') {\n this.onmouseover = onmouseover;\n } else {\n this.onmouseover = function () {\n };\n }\n return this;\n };\n /** @member {function} */\n this.onmouseout = function () {\n };\n this.setOnMouseout = function (onmouseout) {\n if (typeof onmouseout == 'function') {\n this.onmouseout = onmouseout;\n } else {\n this.onmouseout = function () {\n };\n }\n return this;\n };\n /** @member {function} */\n this.onclick = function () {\n };\n this.setOnclick = function (onclick) {\n if (typeof onclick == 'function') {\n this.onclick = onclick;\n } else {\n this.onclick = function () {\n };\n }\n return this;\n };\n // Primary behavior functions\n /**\n * Show the button, including creating DOM elements if necessary for first render\n */\n this.show = function () {\n if (!this.parent) {\n return;\n }\n if (!this.selector) {\n this.selector = this.parent.selector.append(this.tag).attr('class', this.getClass());\n }\n return this.update();\n };\n /**\n * Hook for any actions or state cleanup to be performed before rerendering\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.preUpdate = function () {\n return this;\n };\n /**\n * Update button state and contents, and fully rerender\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.update = function () {\n if (!this.selector) {\n return this;\n }\n this.preUpdate();\n this.selector.attr('class', this.getClass()).attr('title', this.title).style(this.style).on('mouseover', this.status === 'disabled' ? null : this.onmouseover).on('mouseout', this.status === 'disabled' ? null : this.onmouseout).on('click', this.status === 'disabled' ? null : this.onclick).html(this.html);\n this.menu.update();\n this.postUpdate();\n return this;\n };\n /**\n * Hook for any behavior to be added/changed after the button has been re-rendered\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.postUpdate = function () {\n return this;\n };\n /**\n * Hide the button by removing it from the DOM (may be overridden by current persistence setting)\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.hide = function () {\n if (this.selector && !this.shouldPersist()) {\n this.selector.remove();\n this.selector = null;\n }\n return this;\n };\n /**\n * Button Menu Object\n * The menu is an HTML overlay that can appear below a button. It can contain arbitrary HTML and\n * has logic to be automatically positioned and sized to behave more or less like a dropdown menu.\n * @member {Object}\n */\n this.menu = {\n outer_selector: null,\n inner_selector: null,\n scroll_position: 0,\n hidden: true,\n /**\n * Show the button menu, including setting up any DOM elements needed for first rendering\n */\n show: function () {\n if (!this.menu.outer_selector) {\n this.menu.outer_selector = d3.select(this.parent_plot.svg.node().parentNode).append('div').attr('class', 'lz-dashboard-menu lz-dashboard-menu-' + this.color).attr('id', this.parent_svg.getBaseId() + '.dashboard.menu');\n this.menu.inner_selector = this.menu.outer_selector.append('div').attr('class', 'lz-dashboard-menu-content');\n this.menu.inner_selector.on('scroll', function () {\n this.menu.scroll_position = this.menu.inner_selector.node().scrollTop;\n }.bind(this));\n }\n this.menu.outer_selector.style({ visibility: 'visible' });\n this.menu.hidden = false;\n return this.menu.update();\n }.bind(this),\n /**\n * Update the rendering of the menu\n */\n update: function () {\n if (!this.menu.outer_selector) {\n return this.menu;\n }\n this.menu.populate();\n // This function is stubbed for all buttons by default and custom implemented in component definition\n if (this.menu.inner_selector) {\n this.menu.inner_selector.node().scrollTop = this.menu.scroll_position;\n }\n return this.menu.position();\n }.bind(this),\n position: function () {\n if (!this.menu.outer_selector) {\n return this.menu;\n }\n // Unset any explicitly defined outer selector height so that menus dynamically shrink if content is removed\n this.menu.outer_selector.style({ height: null });\n var padding = 3;\n var scrollbar_padding = 20;\n var menu_height_padding = 14;\n // 14: 2x 6px padding, 2x 1px border\n var page_origin = this.parent_svg.getPageOrigin();\n var page_scroll_top = document.documentElement.scrollTop || document.body.scrollTop;\n var container_offset = this.parent_plot.getContainerOffset();\n var dashboard_client_rect = this.parent_dashboard.selector.node().getBoundingClientRect();\n var button_client_rect = this.selector.node().getBoundingClientRect();\n var menu_client_rect = this.menu.outer_selector.node().getBoundingClientRect();\n var total_content_height = this.menu.inner_selector.node().scrollHeight;\n var top = 0;\n var left = 0;\n if (this.parent_dashboard.type === 'panel') {\n top = page_origin.y + dashboard_client_rect.height + 2 * padding;\n left = Math.max(page_origin.x + this.parent_svg.layout.width - menu_client_rect.width - padding, page_origin.x + padding);\n } else {\n top = button_client_rect.bottom + page_scroll_top + padding - container_offset.top;\n left = Math.max(button_client_rect.left + button_client_rect.width - menu_client_rect.width - container_offset.left, page_origin.x + padding);\n }\n var base_max_width = Math.max(this.parent_svg.layout.width - 2 * padding - scrollbar_padding, scrollbar_padding);\n var container_max_width = base_max_width;\n var content_max_width = base_max_width - 4 * padding;\n var base_max_height = Math.max(this.parent_svg.layout.height - 10 * padding - menu_height_padding, menu_height_padding);\n var height = Math.min(total_content_height, base_max_height);\n var max_height = base_max_height;\n this.menu.outer_selector.style({\n 'top': top.toString() + 'px',\n 'left': left.toString() + 'px',\n 'max-width': container_max_width.toString() + 'px',\n 'max-height': max_height.toString() + 'px',\n 'height': height.toString() + 'px'\n });\n this.menu.inner_selector.style({ 'max-width': content_max_width.toString() + 'px' });\n this.menu.inner_selector.node().scrollTop = this.menu.scroll_position;\n return this.menu;\n }.bind(this),\n hide: function () {\n if (!this.menu.outer_selector) {\n return this.menu;\n }\n this.menu.outer_selector.style({ visibility: 'hidden' });\n this.menu.hidden = true;\n return this.menu;\n }.bind(this),\n destroy: function () {\n if (!this.menu.outer_selector) {\n return this.menu;\n }\n this.menu.inner_selector.remove();\n this.menu.outer_selector.remove();\n this.menu.inner_selector = null;\n this.menu.outer_selector = null;\n return this.menu;\n }.bind(this),\n /**\n * Internal method definition\n * By convention populate() does nothing and should be reimplemented with each dashboard button definition\n * Reimplement by way of Dashboard.Component.Button.menu.setPopulate to define the populate method and hook\n * up standard menu click-toggle behavior prototype.\n * @protected\n */\n populate: function () {\n }.bind(this),\n /**\n * Define how the menu is populated with items, and set up click and display properties as appropriate\n * @public\n */\n setPopulate: function (menu_populate_function) {\n if (typeof menu_populate_function == 'function') {\n this.menu.populate = menu_populate_function;\n this.setOnclick(function () {\n if (this.menu.hidden) {\n this.menu.show();\n this.highlight().update();\n this.persist = true;\n } else {\n this.menu.hide();\n this.highlight(false).update();\n if (!this.permanent) {\n this.persist = false;\n }\n }\n }.bind(this));\n } else {\n this.setOnclick();\n }\n return this;\n }.bind(this)\n };\n };\n /**\n * Renders arbitrary text with title formatting\n * @class LocusZoom.Dashboard.Components.title\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.title Text to render\n */\n LocusZoom.Dashboard.Components.add('title', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.show = function () {\n this.div_selector = this.parent.selector.append('div').attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position);\n this.title_selector = this.div_selector.append('h3');\n return this.update();\n };\n this.update = function () {\n var title = layout.title.toString();\n if (this.layout.subtitle) {\n title += ' ' + this.layout.subtitle + '';\n }\n this.title_selector.html(title);\n return this;\n };\n });\n /**\n * Renders text to display the current dimensions of the plot. Automatically updated as plot dimensions change\n * @class LocusZoom.Dashboard.Components.dimensions\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('dimensions', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n var display_width = this.parent_plot.layout.width.toString().indexOf('.') === -1 ? this.parent_plot.layout.width : this.parent_plot.layout.width.toFixed(2);\n var display_height = this.parent_plot.layout.height.toString().indexOf('.') === -1 ? this.parent_plot.layout.height : this.parent_plot.layout.height.toFixed(2);\n this.selector.html(display_width + 'px \\xD7 ' + display_height + 'px');\n if (layout.class) {\n this.selector.attr('class', layout.class);\n }\n if (layout.style) {\n this.selector.style(layout.style);\n }\n return this;\n };\n });\n /**\n * Display the current scale of the genome region displayed in the plot, as defined by the difference between\n * `state.end` and `state.start`.\n * @class LocusZoom.Dashboard.Components.region_scale\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('region_scale', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (!isNaN(this.parent_plot.state.start) && !isNaN(this.parent_plot.state.end) && this.parent_plot.state.start !== null && this.parent_plot.state.end !== null) {\n this.selector.style('display', null);\n this.selector.html(LocusZoom.positionIntToString(this.parent_plot.state.end - this.parent_plot.state.start, null, true));\n } else {\n this.selector.style('display', 'none');\n }\n if (layout.class) {\n this.selector.attr('class', layout.class);\n }\n if (layout.style) {\n this.selector.style(layout.style);\n }\n return this;\n };\n });\n /**\n * Button to export current plot to an SVG image\n * @class LocusZoom.Dashboard.Components.download\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Download Image\"]\n * @param {string} [layout.button_title=\"Download image of the current plot as locuszoom.svg\"]\n */\n LocusZoom.Dashboard.Components.add('download', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html || 'Download Image').setTitle(layout.button_title || 'Download image of the current plot as locuszoom.svg').setOnMouseover(function () {\n this.button.selector.classed('lz-dashboard-button-gray-disabled', true).html('Preparing Image');\n this.generateBase64SVG().then(function (url) {\n var old = this.button.selector.attr('href');\n if (old) {\n URL.revokeObjectURL(old);\n }\n // Clean up old url instance to prevent memory leaks\n this.button.selector.attr('href', url).classed('lz-dashboard-button-gray-disabled', false).classed('lz-dashboard-button-gray-highlighted', true).html(layout.button_html || 'Download Image');\n }.bind(this));\n }.bind(this)).setOnMouseout(function () {\n this.button.selector.classed('lz-dashboard-button-gray-highlighted', false);\n }.bind(this));\n this.button.show();\n this.button.selector.attr('href-lang', 'image/svg+xml').attr('download', layout.filename || 'locuszoom.svg');\n return this;\n };\n this.css_string = '';\n for (var stylesheet in Object.keys(document.styleSheets)) {\n if (document.styleSheets[stylesheet].href !== null && document.styleSheets[stylesheet].href.indexOf('locuszoom.css') !== -1) {\n // TODO: \"Download image\" button will render the image incorrectly if the stylesheet has been renamed or concatenated\n LocusZoom.createCORSPromise('GET', document.styleSheets[stylesheet].href).then(function (response) {\n this.css_string = response.replace(/[\\r\\n]/g, ' ').replace(/\\s+/g, ' ');\n if (this.css_string.indexOf('/* ! LocusZoom HTML Styles */')) {\n this.css_string = this.css_string.substring(0, this.css_string.indexOf('/* ! LocusZoom HTML Styles */'));\n }\n }.bind(this));\n break;\n }\n }\n this.generateBase64SVG = function () {\n return new Promise(function (resolve, reject) {\n // Insert a hidden div, clone the node into that so we can modify it with d3\n var container = this.parent.selector.append('div').style('display', 'none').html(this.parent_plot.svg.node().outerHTML);\n // Remove unnecessary elements\n container.selectAll('g.lz-curtain').remove();\n container.selectAll('g.lz-mouse_guide').remove();\n // Convert units on axis tick dy attributes from ems to pixels\n container.selectAll('g.tick text').each(function () {\n var dy = +d3.select(this).attr('dy').substring(-2).slice(0, -2) * 10;\n d3.select(this).attr('dy', dy);\n });\n // Pull the svg into a string and add the contents of the locuszoom stylesheet\n // Don't add this with d3 because it will escape the CDATA declaration incorrectly\n var initial_html = d3.select(container.select('svg').node().parentNode).html();\n var style_def = '';\n var insert_at = initial_html.indexOf('>') + 1;\n initial_html = initial_html.slice(0, insert_at) + style_def + initial_html.slice(insert_at);\n // Delete the container node\n container.remove();\n // Create an object URL based on the rendered markup\n var content = new Blob([initial_html], { type: 'image/svg+xml' });\n resolve(URL.createObjectURL(content));\n }.bind(this));\n };\n });\n /**\n * Button to remove panel from plot.\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.remove_panel\n * @augments LocusZoom.Dashboard.Component\n * @param {Boolean} [layout.suppress_confirm=false] If true, removes the panel without prompting user for confirmation\n */\n LocusZoom.Dashboard.Components.add('remove_panel', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml('\\xD7').setTitle('Remove panel').setOnclick(function () {\n if (!layout.suppress_confirm && !confirm('Are you sure you want to remove this panel? This cannot be undone!')) {\n return false;\n }\n var panel = this.parent_panel;\n panel.dashboard.hide(true);\n d3.select(panel.parent.svg.node().parentNode).on('mouseover.' + panel.getBaseId() + '.dashboard', null);\n d3.select(panel.parent.svg.node().parentNode).on('mouseout.' + panel.getBaseId() + '.dashboard', null);\n return panel.parent.removePanel(panel.id);\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Button to move panel up relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_up\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('move_panel_up', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n var is_at_top = this.parent_panel.layout.y_index === 0;\n this.button.disable(is_at_top);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml('\\u25B4').setTitle('Move panel up').setOnclick(function () {\n this.parent_panel.moveUp();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n });\n /**\n * Button to move panel down relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_down\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('move_panel_down', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n var is_at_bottom = this.parent_panel.layout.y_index === this.parent_plot.panel_ids_by_y_index.length - 1;\n this.button.disable(is_at_bottom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml('\\u25BE').setTitle('Move panel down').setOnclick(function () {\n this.parent_panel.moveDown();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n });\n /**\n * Button to shift plot region forwards or back by a `step` increment provided in the layout\n * @class LocusZoom.Dashboard.Components.shift_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=50000] The stepsize to change the region by\n * @param {string} [layout.button_html]\n * @param {string} [layout.button_title]\n */\n LocusZoom.Dashboard.Components.add('shift_region', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function () {\n };\n console.warn('Unable to add shift_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) {\n layout.step = 50000;\n }\n if (typeof layout.button_html !== 'string') {\n layout.button_html = layout.step > 0 ? '>' : '<';\n }\n if (typeof layout.button_title !== 'string') {\n layout.button_title = 'Shift region by ' + (layout.step > 0 ? '+' : '-') + LocusZoom.positionIntToString(Math.abs(layout.step), null, true);\n }\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start + layout.step, 1),\n end: this.parent_plot.state.end + layout.step\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Zoom in or out on the plot, centered on the middle of the plot region, by the specified amount\n * @class LocusZoom.Dashboard.Components.zoom_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=0.2] The amount to zoom in by (where 1 indicates 100%)\n */\n LocusZoom.Dashboard.Components.add('zoom_region', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function () {\n };\n console.warn('Unable to add zoom_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) {\n layout.step = 0.2;\n }\n if (typeof layout.button_html != 'string') {\n layout.button_html = layout.step > 0 ? 'z\\u2013' : 'z+';\n }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Zoom region ' + (layout.step > 0 ? 'out' : 'in') + ' by ' + (Math.abs(layout.step) * 100).toFixed(1) + '%';\n }\n this.update = function () {\n if (this.button) {\n var can_zoom = true;\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n if (layout.step > 0 && !isNaN(this.parent_plot.layout.max_region_scale) && current_region_scale >= this.parent_plot.layout.max_region_scale) {\n can_zoom = false;\n }\n if (layout.step < 0 && !isNaN(this.parent_plot.layout.min_region_scale) && current_region_scale <= this.parent_plot.layout.min_region_scale) {\n can_zoom = false;\n }\n this.button.disable(!can_zoom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n var zoom_factor = 1 + layout.step;\n var new_region_scale = current_region_scale * zoom_factor;\n if (!isNaN(this.parent_plot.layout.max_region_scale)) {\n new_region_scale = Math.min(new_region_scale, this.parent_plot.layout.max_region_scale);\n }\n if (!isNaN(this.parent_plot.layout.min_region_scale)) {\n new_region_scale = Math.max(new_region_scale, this.parent_plot.layout.min_region_scale);\n }\n var delta = Math.floor((new_region_scale - current_region_scale) / 2);\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start - delta, 1),\n end: this.parent_plot.state.end + delta\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Renders button with arbitrary text that, when clicked, shows a dropdown containing arbitrary HTML\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @class LocusZoom.Dashboard.Components.menu\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n * @param {string} layout.menu_html The HTML content of the dropdown menu\n */\n LocusZoom.Dashboard.Components.add('menu', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title);\n this.button.menu.setPopulate(function () {\n this.button.menu.inner_selector.html(layout.menu_html);\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Special button/menu to allow model building by tracking individual covariants. Will track a list of covariate\n * objects and store them in the special `model.covariates` field of plot `state`.\n * @class LocusZoom.Dashboard.Components.covariates_model\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n */\n LocusZoom.Dashboard.Components.add('covariates_model', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.initialize = function () {\n // Initialize state.model.covariates\n this.parent_plot.state.model = this.parent_plot.state.model || {};\n this.parent_plot.state.model.covariates = this.parent_plot.state.model.covariates || [];\n // Create an object at the plot level for easy access to interface methods in custom client-side JS\n /**\n * When a covariates model dashboard element is present, create (one) object at the plot level that exposes\n * component data and state for custom interactions with other plot elements.\n * @class LocusZoom.Plot.CovariatesModel\n */\n this.parent_plot.CovariatesModel = {\n /** @member {LocusZoom.Dashboard.Component.Button} */\n button: this,\n /**\n * Add an element to the model and show a representation of it in the dashboard component menu. If the\n * element is already part of the model, do nothing (to avoid adding duplicates).\n * When plot state is changed, this will automatically trigger requests for new data accordingly.\n * @param {string|object} element_reference Can be any value that can be put through JSON.stringify()\n * to create a serialized representation of itself.\n */\n add: function (element_reference) {\n var element = JSON.parse(JSON.stringify(element_reference));\n if (typeof element_reference == 'object' && typeof element.html != 'string') {\n element.html = typeof element_reference.toHTML == 'function' ? element_reference.toHTML() : element_reference.toString();\n }\n // Check if the element is already in the model covariates array and return if it is.\n for (var i = 0; i < this.state.model.covariates.length; i++) {\n if (JSON.stringify(this.state.model.covariates[i]) === JSON.stringify(element)) {\n return this;\n }\n }\n this.state.model.covariates.push(element);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Remove an element from `state.model.covariates` (and from the dashboard component menu's\n * representation of the state model). When plot state is changed, this will automatically trigger\n * requests for new data accordingly.\n * @param {number} idx Array index of the element, in the `state.model.covariates array`.\n */\n removeByIdx: function (idx) {\n if (typeof this.state.model.covariates[idx] == 'undefined') {\n throw new Error('Unable to remove model covariate, invalid index: ' + idx.toString());\n }\n this.state.model.covariates.splice(idx, 1);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Empty the `state.model.covariates` array (and dashboard component menu representation thereof) of all\n * elements. When plot state is changed, this will automatically trigger requests for new data accordingly\n */\n removeAll: function () {\n this.state.model.covariates = [];\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Manually trigger the update methods on the dashboard component's button and menu elements to force\n * display of most up-to-date content. Can be used to force the dashboard to reflect changes made, eg if\n * modifying `state.model.covariates` directly instead of via `plot.CovariatesModel`\n */\n updateComponent: function () {\n this.button.update();\n this.button.menu.update();\n }.bind(this)\n };\n }.bind(this);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n this.button.menu.populate();\n }.bind(this));\n this.button.menu.setPopulate(function () {\n var selector = this.button.menu.inner_selector;\n selector.html('');\n // General model HTML representation\n if (typeof this.parent_plot.state.model.html != 'undefined') {\n selector.append('div').html(this.parent_plot.state.model.html);\n }\n // Model covariates table\n if (!this.parent_plot.state.model.covariates.length) {\n selector.append('i').html('no covariates in model');\n } else {\n selector.append('h5').html('Model Covariates (' + this.parent_plot.state.model.covariates.length + ')');\n var table = selector.append('table');\n this.parent_plot.state.model.covariates.forEach(function (covariate, idx) {\n var html = typeof covariate == 'object' && typeof covariate.html == 'string' ? covariate.html : covariate.toString();\n var row = table.append('tr');\n row.append('td').append('button').attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color).style({ 'margin-left': '0em' }).on('click', function () {\n this.parent_plot.CovariatesModel.removeByIdx(idx);\n }.bind(this)).html('\\xD7');\n row.append('td').html(html);\n }.bind(this));\n selector.append('button').attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color).style({ 'margin-left': '4px' }).html('\\xD7 Remove All Covariates').on('click', function () {\n this.parent_plot.CovariatesModel.removeAll();\n }.bind(this));\n }\n }.bind(this));\n this.button.preUpdate = function () {\n var html = 'Model';\n if (this.parent_plot.state.model.covariates.length) {\n var cov = this.parent_plot.state.model.covariates.length > 1 ? 'covariates' : 'covariate';\n html += ' (' + this.parent_plot.state.model.covariates.length + ' ' + cov + ')';\n }\n this.button.setHtml(html).disable(false);\n }.bind(this);\n this.button.show();\n return this;\n };\n });\n /**\n * Button to toggle split tracks\n * @class LocusZoom.Dashboard.Components.toggle_split_tracks\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('toggle_split_tracks', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (!layout.data_layer_id) {\n layout.data_layer_id = 'intervals';\n }\n if (!this.parent_panel.data_layers[layout.data_layer_id]) {\n throw new Error('Dashboard toggle split tracks component missing valid data layer ID');\n }\n this.update = function () {\n var data_layer = this.parent_panel.data_layers[layout.data_layer_id];\n var html = data_layer.layout.split_tracks ? 'Merge Tracks' : 'Split Tracks';\n if (this.button) {\n this.button.setHtml(html);\n this.button.show();\n this.parent.position();\n return this;\n } else {\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(html).setTitle('Toggle whether tracks are split apart or merged together').setOnclick(function () {\n data_layer.toggleSplitTracks();\n if (this.scale_timeout) {\n clearTimeout(this.scale_timeout);\n }\n var timeout = data_layer.layout.transition ? +data_layer.layout.transition.duration || 0 : 0;\n this.scale_timeout = setTimeout(function () {\n this.parent_panel.scaleHeightToData();\n this.parent_plot.positionPanels();\n }.bind(this), timeout);\n this.update();\n }.bind(this));\n return this.update();\n }\n };\n });\n /**\n * Button to resize panel height to fit available data (eg when showing a list of tracks)\n * @class LocusZoom.Dashboard.Components.resize_to_data\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Resize to Data\"]\n * @param {string} [layout.button_title]\n */\n LocusZoom.Dashboard.Components.add('resize_to_data', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html || 'Resize to Data').setTitle(layout.button_title || 'Automatically resize this panel to show all data available').setOnclick(function () {\n this.parent_panel.scaleHeightToData();\n this.update();\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Button to toggle legend\n * @class LocusZoom.Dashboard.Components.toggle_legend\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('toggle_legend', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n var html = this.parent_panel.legend.layout.hidden ? 'Show Legend' : 'Hide Legend';\n if (this.button) {\n this.button.setHtml(html).show();\n this.parent.position();\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setTitle('Show or hide the legend for this panel').setOnclick(function () {\n this.parent_panel.legend.layout.hidden = !this.parent_panel.legend.layout.hidden;\n this.parent_panel.legend.render();\n this.update();\n }.bind(this));\n return this.update();\n };\n });\n /**\n * Menu for manipulating multiple data layers in a single panel: show/hide, change order, etc.\n * @class LocusZoom.Dashboard.Components.data_layers\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('data_layers', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (typeof layout.button_html != 'string') {\n layout.button_html = 'Data Layers';\n }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Manipulate Data Layers (sort, dim, show/hide, etc.)';\n }\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n this.button.menu.populate();\n }.bind(this));\n this.button.menu.setPopulate(function () {\n this.button.menu.inner_selector.html('');\n var table = this.button.menu.inner_selector.append('table');\n this.parent_panel.data_layer_ids_by_z_index.slice().reverse().forEach(function (id, idx) {\n var data_layer = this.parent_panel.data_layers[id];\n var name = typeof data_layer.layout.name != 'string' ? data_layer.id : data_layer.layout.name;\n var row = table.append('tr');\n // Layer name\n row.append('td').html(name);\n // Status toggle buttons\n layout.statuses.forEach(function (status_adj) {\n var status_idx = LocusZoom.DataLayer.Statuses.adjectives.indexOf(status_adj);\n var status_verb = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n var html, onclick, highlight;\n if (data_layer.global_statuses[status_adj]) {\n html = LocusZoom.DataLayer.Statuses.menu_antiverbs[status_idx];\n onclick = 'un' + status_verb + 'AllElements';\n highlight = '-highlighted';\n } else {\n html = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n onclick = status_verb + 'AllElements';\n highlight = '';\n }\n row.append('td').append('a').attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color + highlight).style({ 'margin-left': '0em' }).on('click', function () {\n data_layer[onclick]();\n this.button.menu.populate();\n }.bind(this)).html(html);\n }.bind(this));\n // Sort layer buttons\n var at_top = idx === 0;\n var at_bottom = idx === this.parent_panel.data_layer_ids_by_z_index.length - 1;\n var td = row.append('td');\n td.append('a').attr('class', 'lz-dashboard-button lz-dashboard-button-group-start lz-dashboard-button-' + this.layout.color + (at_bottom ? '-disabled' : '')).style({ 'margin-left': '0em' }).on('click', function () {\n data_layer.moveDown();\n this.button.menu.populate();\n }.bind(this)).html('\\u25BE').attr('title', 'Move layer down (further back)');\n td.append('a').attr('class', 'lz-dashboard-button lz-dashboard-button-group-middle lz-dashboard-button-' + this.layout.color + (at_top ? '-disabled' : '')).style({ 'margin-left': '0em' }).on('click', function () {\n data_layer.moveUp();\n this.button.menu.populate();\n }.bind(this)).html('\\u25B4').attr('title', 'Move layer up (further front)');\n td.append('a').attr('class', 'lz-dashboard-button lz-dashboard-button-group-end lz-dashboard-button-red').style({ 'margin-left': '0em' }).on('click', function () {\n if (confirm('Are you sure you want to remove the ' + name + ' layer? This cannot be undone!')) {\n data_layer.parent.removeDataLayer(id);\n }\n return this.button.menu.populate();\n }.bind(this)).html('\\xD7').attr('title', 'Remove layer');\n }.bind(this));\n return this;\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Dropdown menu allowing the user to choose between different display options for a single specific data layer\n * within a panel.\n *\n * This allows controlling how points on a datalayer can be displayed- any display options supported via the layout for the target datalayer. This includes point\n * size/shape, coloring, etc.\n *\n * This button intentionally limits display options it can control to those available on common plot types.\n * Although the list of options it sets can be overridden (to control very special custom plot types), this\n * capability should be used sparingly if at all.\n *\n * @class LocusZoom.Dashboard.Components.display_options\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Display options...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Control how plot items are displayed\"] Hover text for the toolbar button\n * @param {string} layout.layer_name Specify the datalayer that this button should affect\n * @param {string} [layout.default_config_display_name] Store the default configuration for this datalayer\n * configuration, and show a button to revert to the \"default\" (listing the human-readable display name provided)\n * @param {Array} [layout.fields_whitelist='see code'] The list of presentation fields that this button can control.\n * This can be overridden if this button needs to be used on a custom layer type with special options.\n * @typedef {{display_name: string, display: Object}} DisplayOptionsButtonConfigField\n * @param {DisplayOptionsButtonConfigField[]} layout.options Specify a label and set of layout directives associated\n * with this `display` option. Display field should include all changes to datalayer presentation options.\n */\n LocusZoom.Dashboard.Components.add('display_options', function (layout) {\n if (typeof layout.button_html != 'string') {\n layout.button_html = 'Display options...';\n }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Control how plot items are displayed';\n }\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n // List of layout fields that this button is allowed to control. This ensures that we don't override any other\n // information (like plot height etc) while changing point rendering\n var allowed_fields = layout.fields_whitelist || [\n 'color',\n 'fill_opacity',\n 'label',\n 'legend',\n 'point_shape',\n 'point_size',\n 'tooltip',\n 'tooltip_positioning'\n ];\n var dataLayer = this.parent_panel.data_layers[layout.layer_name];\n if (!dataLayer) {\n throw new Error('Display options could not locate the specified layer_name: \\'' + layout.layer_name + '\\'');\n }\n var dataLayerLayout = dataLayer.layout;\n // Store default configuration for the layer as a clean deep copy, so we may revert later\n var defaultConfig = {};\n allowed_fields.forEach(function (name) {\n var configSlot = dataLayerLayout[name];\n if (configSlot !== undefined) {\n defaultConfig[name] = JSON.parse(JSON.stringify(configSlot));\n }\n });\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n this._selected_item = 'default';\n // Define the button + menu that provides the real functionality for this dashboard component\n var self = this;\n this.button = new LocusZoom.Dashboard.Component.Button(self).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 10000).toString();\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n var menuLayout = self.layout;\n var renderRow = function (display_name, display_options, row_id) {\n // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td').append('input').attr({\n id: radioId,\n type: 'radio',\n name: 'display-option-' + uniqueID,\n value: row_id\n }).style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n.property('checked', row_id === self._selected_item).on('click', function () {\n // If an option is not specified in these display options, use the original defaults\n allowed_fields.forEach(function (field_name) {\n dataLayer.layout[field_name] = display_options[field_name] || defaultConfig[field_name];\n });\n self._selected_item = row_id;\n self.parent_panel.render();\n var legend = self.parent_panel.legend;\n if (legend) {\n legend.render();\n }\n });\n row.append('td').append('label').style('font-weight', 'normal').attr('for', radioId).text(display_name);\n };\n // Render the \"display options\" menu: default and special custom options\n var defaultName = menuLayout.default_config_display_name || 'Default style';\n renderRow(defaultName, defaultConfig, 'default');\n menuLayout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.display, index);\n });\n return self;\n });\n this.update = function () {\n this.button.show();\n return this;\n };\n });\n /**\n * Dropdown menu allowing the user to set the value of a specific `state_field` in plot.state\n * This is useful for things (like datasources) that allow dynamic configuration based on global information in state\n *\n * For example, the LDLZ2 data source can use it to change LD reference population (for all panels) after render\n *\n * @class LocusZoom.Dashboard.Components.set_state\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Set option...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Choose an option to customize the plot\"] Hover text for the toolbar button\n * @param {bool} [layout.show_selected=false] Whether to append the selected value to the button label\n * @param {string} [layout.state_field] The name of the field in plot.state that will be set by this button\n * @typedef {{display_name: string, value: *}} SetStateOptionsConfigField\n * @param {SetStateOptionsConfigField[]} layout.options Specify human labels and associated values for the dropdown menu\n */\n LocusZoom.Dashboard.Components.add('set_state', function (layout) {\n var self = this;\n if (typeof layout.button_html != 'string') {\n layout.button_html = 'Set option...';\n }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Choose an option to customize the plot';\n }\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (this.parent_panel) {\n throw new Error('This widget is designed to set global options, so it can only be used at the top (plot) level');\n }\n if (!layout.state_field) {\n throw new Error('Must specify the `state_field` that this widget controls');\n }\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n // The first option listed is automatically assumed to be the default, unless a value exists in plot.state\n this._selected_item = this.parent_plot.state[layout.state_field] || layout.options[0].value;\n if (!layout.options.find(function (item) {\n return item.value === self._selected_item;\n })) {\n // Check only gets run at widget creation, but generally this widget is assumed to be an exclusive list of options\n throw new Error('There is an existing state value that does not match the known values in this widget');\n }\n // Define the button + menu that provides the real functionality for this dashboard component\n this.button = new LocusZoom.Dashboard.Component.Button(self).setColor(layout.color).setHtml(layout.button_html + (layout.show_selected ? this._selected_item : '')).setTitle(layout.button_title).setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 10000).toString();\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n var renderRow = function (display_name, value, row_id) {\n // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td').append('input').attr({\n id: radioId,\n type: 'radio',\n name: 'set-state-' + uniqueID,\n value: row_id\n }).style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n.property('checked', value === self._selected_item).on('click', function () {\n var new_state = {};\n new_state[layout.state_field] = value;\n self._selected_item = value;\n self.parent_plot.applyState(new_state);\n self.button.setHtml(layout.button_html + (layout.show_selected ? self._selected_item : ''));\n });\n row.append('td').append('label').style('font-weight', 'normal').attr('for', radioId).text(display_name);\n };\n layout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.value, index);\n });\n return self;\n });\n this.update = function () {\n this.button.show();\n return this;\n };\n });\n /* global LocusZoom */\n 'use strict';\n /**\n * An SVG object used to display contextual information about a panel.\n * Panel layouts determine basic features of a legend - its position in the panel, orientation, title, etc.\n * Layouts of child data layers of the panel determine the actual content of the legend.\n *\n * @class\n * @param {LocusZoom.Panel} parent\n*/\n LocusZoom.Legend = function (parent) {\n if (!(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create legend, parent must be a locuszoom panel');\n }\n /** @member {LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.legend';\n this.parent.layout.legend = LocusZoom.Layouts.merge(this.parent.layout.legend || {}, LocusZoom.Legend.DefaultLayout);\n /** @member {Object} */\n this.layout = this.parent.layout.legend;\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {d3.selection} */\n this.background_rect = null;\n /** @member {d3.selection[]} */\n this.elements = [];\n /**\n * SVG selector for the group containing all elements in the legend\n * @protected\n * @member {d3.selection|null}\n */\n this.elements_group = null;\n /**\n * TODO: Not sure if this property is used; the external-facing methods are setting `layout.hidden` instead. Tentatively mark deprecated.\n * @deprecated\n * @protected\n * @member {Boolean}\n */\n this.hidden = false;\n // TODO Revisit constructor return value; see https://stackoverflow.com/a/3350364/1422268\n return this.render();\n };\n /**\n * The default layout used by legends (used internally)\n * @protected\n * @member {Object}\n */\n LocusZoom.Legend.DefaultLayout = {\n orientation: 'vertical',\n origin: {\n x: 0,\n y: 0\n },\n width: 10,\n height: 10,\n padding: 5,\n label_size: 12,\n hidden: false\n };\n /**\n * Render the legend in the parent panel\n */\n LocusZoom.Legend.prototype.render = function () {\n // Get a legend group selector if not yet defined\n if (!this.selector) {\n this.selector = this.parent.svg.group.append('g').attr('id', this.parent.getBaseId() + '.legend').attr('class', 'lz-legend');\n }\n // Get a legend background rect selector if not yet defined\n if (!this.background_rect) {\n this.background_rect = this.selector.append('rect').attr('width', 100).attr('height', 100).attr('class', 'lz-legend-background');\n }\n // Get a legend elements group selector if not yet defined\n if (!this.elements_group) {\n this.elements_group = this.selector.append('g');\n }\n // Remove all elements from the document and re-render from scratch\n this.elements.forEach(function (element) {\n element.remove();\n });\n this.elements = [];\n // Gather all elements from data layers in order (top to bottom) and render them\n var padding = +this.layout.padding || 1;\n var x = padding;\n var y = padding;\n var line_height = 0;\n this.parent.data_layer_ids_by_z_index.slice().reverse().forEach(function (id) {\n if (Array.isArray(this.parent.data_layers[id].layout.legend)) {\n this.parent.data_layers[id].layout.legend.forEach(function (element) {\n var selector = this.elements_group.append('g').attr('transform', 'translate(' + x + ',' + y + ')');\n var label_size = +element.label_size || +this.layout.label_size || 12;\n var label_x = 0;\n var label_y = label_size / 2 + padding / 2;\n line_height = Math.max(line_height, label_size + padding);\n // Draw the legend element symbol (line, rect, shape, etc)\n if (element.shape === 'line') {\n // Line symbol\n var length = +element.length || 16;\n var path_y = label_size / 4 + padding / 2;\n selector.append('path').attr('class', element.class || '').attr('d', 'M0,' + path_y + 'L' + length + ',' + path_y).style(element.style || {});\n label_x = length + padding;\n } else if (element.shape === 'rect') {\n // Rect symbol\n var width = +element.width || 16;\n var height = +element.height || width;\n selector.append('rect').attr('class', element.class || '').attr('width', width).attr('height', height).attr('fill', element.color || {}).style(element.style || {});\n label_x = width + padding;\n line_height = Math.max(line_height, height + padding);\n } else if (d3.svg.symbolTypes.indexOf(element.shape) !== -1) {\n // Shape symbol (circle, diamond, etc.)\n var size = +element.size || 40;\n var radius = Math.ceil(Math.sqrt(size / Math.PI));\n selector.append('path').attr('class', element.class || '').attr('d', d3.svg.symbol().size(size).type(element.shape)).attr('transform', 'translate(' + radius + ',' + (radius + padding / 2) + ')').attr('fill', element.color || {}).style(element.style || {});\n label_x = 2 * radius + padding;\n label_y = Math.max(2 * radius + padding / 2, label_y);\n line_height = Math.max(line_height, 2 * radius + padding);\n }\n // Draw the legend element label\n selector.append('text').attr('text-anchor', 'left').attr('class', 'lz-label').attr('x', label_x).attr('y', label_y).style({ 'font-size': label_size }).text(element.label);\n // Position the legend element group based on legend layout orientation\n var bcr = selector.node().getBoundingClientRect();\n if (this.layout.orientation === 'vertical') {\n y += bcr.height + padding;\n line_height = 0;\n } else {\n // Ensure this element does not exceed the panel width\n // (E.g. drop to the next line if it does, but only if it's not the only element on this line)\n var right_x = this.layout.origin.x + x + bcr.width;\n if (x > padding && right_x > this.parent.layout.width) {\n y += line_height;\n x = padding;\n selector.attr('transform', 'translate(' + x + ',' + y + ')');\n }\n x += bcr.width + 3 * padding;\n }\n // Store the element\n this.elements.push(selector);\n }.bind(this));\n }\n }.bind(this));\n // Scale the background rect to the elements in the legend\n var bcr = this.elements_group.node().getBoundingClientRect();\n this.layout.width = bcr.width + 2 * this.layout.padding;\n this.layout.height = bcr.height + 2 * this.layout.padding;\n this.background_rect.attr('width', this.layout.width).attr('height', this.layout.height);\n // Set the visibility on the legend from the \"hidden\" flag\n // TODO: `show()` and `hide()` call a full rerender; might be able to make this more lightweight?\n this.selector.style({ visibility: this.layout.hidden ? 'hidden' : 'visible' });\n // TODO: Annotate return type and make consistent\n return this.position();\n };\n /**\n * Place the legend in position relative to the panel, as specified in the layout configuration\n * @returns {LocusZoom.Legend | null}\n * TODO: should this always be chainable?\n */\n LocusZoom.Legend.prototype.position = function () {\n if (!this.selector) {\n return this;\n }\n var bcr = this.selector.node().getBoundingClientRect();\n if (!isNaN(+this.layout.pad_from_bottom)) {\n this.layout.origin.y = this.parent.layout.height - bcr.height - +this.layout.pad_from_bottom;\n }\n if (!isNaN(+this.layout.pad_from_right)) {\n this.layout.origin.x = this.parent.layout.width - bcr.width - +this.layout.pad_from_right;\n }\n this.selector.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n };\n /**\n * Hide the legend (triggers a re-render)\n * @public\n */\n LocusZoom.Legend.prototype.hide = function () {\n this.layout.hidden = true;\n this.render();\n };\n /**\n * Show the legend (triggers a re-render)\n * @public\n */\n LocusZoom.Legend.prototype.show = function () {\n this.layout.hidden = false;\n this.render();\n };\n /* global LocusZoom */\n 'use strict';\n function validateBuildSource(class_name, build, source) {\n // Build OR Source, not both\n if (build && source || !(build || source)) {\n throw new Error(class_name + ' must provide a parameter specifying either \"build\" or \"source\". It should not specify both.');\n }\n // If the build isn't recognized, our APIs can't transparently select a source to match\n if (build && [\n 'GRCh37',\n 'GRCh38'\n ].indexOf(build) === -1) {\n throw new Error(class_name + ' must specify a valid genome build number');\n }\n }\n /**\n * LocusZoom functionality used for data parsing and retrieval\n * @namespace\n * @public\n */\n LocusZoom.Data = LocusZoom.Data || {};\n /**\n * Create and coordinate an ensemble of (namespaced) data source instances\n * @public\n * @class\n */\n LocusZoom.DataSources = function () {\n /** @member {Object.} */\n this.sources = {};\n };\n /** @deprecated */\n LocusZoom.DataSources.prototype.addSource = function (ns, x) {\n console.warn('Warning: .addSource() is deprecated. Use .add() instead');\n return this.add(ns, x);\n };\n /**\n * Add a (namespaced) datasource to the plot\n * @public\n * @param {String} ns A namespace used for fields from this data source\n * @param {LocusZoom.Data.Source|Array|null} x An instantiated datasource, or an array of arguments that can be used to\n * create a known datasource type.\n */\n LocusZoom.DataSources.prototype.add = function (ns, x) {\n // FIXME: Some existing sites create sources with arbitrary names. This leads to subtle breakage\n // of namespaced fields in layouts. To avoid breaking existing usages outright, issue a deprecation warning.\n if (ns.match(/[^A-Za-z0-9_]/)) {\n console.warn('Deprecation warning: source name \\'' + ns + '\\' should contain only alphanumeric characters or underscores. Use of other characters may break layouts, and will be disallowed in the future.');\n }\n return this.set(ns, x);\n };\n /** @protected */\n LocusZoom.DataSources.prototype.set = function (ns, x) {\n if (Array.isArray(x)) {\n // If passed array of source name and options, make the source\n var dsobj = LocusZoom.KnownDataSources.create.apply(null, x);\n // Each datasource in the chain should be aware of its assigned namespace\n dsobj.source_id = ns;\n this.sources[ns] = dsobj;\n } else {\n // If passed the already-created source object\n if (x !== null) {\n x.source_id = ns;\n this.sources[ns] = x;\n } else {\n delete this.sources[ns];\n }\n }\n return this;\n };\n /** @deprecated */\n LocusZoom.DataSources.prototype.getSource = function (ns) {\n console.warn('Warning: .getSource() is deprecated. Use .get() instead');\n return this.get(ns);\n };\n /**\n * Return the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n * @returns {LocusZoom.Data.Source}\n */\n LocusZoom.DataSources.prototype.get = function (ns) {\n return this.sources[ns];\n };\n /** @deprecated */\n LocusZoom.DataSources.prototype.removeSource = function (ns) {\n console.warn('Warning: .removeSource() is deprecated. Use .remove() instead');\n return this.remove(ns);\n };\n /**\n * Remove the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n */\n LocusZoom.DataSources.prototype.remove = function (ns) {\n return this.set(ns, null);\n };\n /**\n * Populate a list of datasources specified as a JSON object\n * @public\n * @param {String|Object} x An object or JSON representation containing {ns: configArray} entries\n * @returns {LocusZoom.DataSources}\n */\n LocusZoom.DataSources.prototype.fromJSON = function (x) {\n if (typeof x === 'string') {\n x = JSON.parse(x);\n }\n var ds = this;\n Object.keys(x).forEach(function (ns) {\n ds.set(ns, x[ns]);\n });\n return ds;\n };\n /**\n * Return the names of all currently recognized datasources\n * @public\n * @returns {Array}\n */\n LocusZoom.DataSources.prototype.keys = function () {\n return Object.keys(this.sources);\n };\n /**\n * Datasources can be instantiated from a JSON object instead of code. This represents existing sources in that format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n * @public\n */\n LocusZoom.DataSources.prototype.toJSON = function () {\n return this.sources;\n };\n /**\n * Represents an addressable unit of data from a namespaced datasource, subject to specified value transformations.\n *\n * When used by a data layer, fields will automatically be re-fetched from the appropriate data source whenever the\n * state of a plot fetches, eg pan or zoom operations that would affect what data is displayed.\n *\n * @public\n * @class\n * @param {String} field A string representing the namespace of the datasource, the name of the desired field to fetch\n * from that datasource, and arbitrarily many transformations to apply to the value. The namespace and\n * transformation(s) are optional and information is delimited according to the general syntax\n * `[namespace:]name[|transformation][|transformation]`. For example, `association:pvalue|neglog10`\n */\n LocusZoom.Data.Field = function (field) {\n var parts = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/.exec(field);\n /** @member {String} */\n this.full_name = field;\n /** @member {String} */\n this.namespace = parts[1] || null;\n /** @member {String} */\n this.name = parts[2] || null;\n /** @member {Array} */\n this.transformations = [];\n if (typeof parts[3] == 'string' && parts[3].length > 1) {\n this.transformations = parts[3].substring(1).split('|');\n this.transformations.forEach(function (transform, i) {\n this.transformations[i] = LocusZoom.TransformationFunctions.get(transform);\n }.bind(this));\n }\n this.applyTransformations = function (val) {\n this.transformations.forEach(function (transform) {\n val = transform(val);\n });\n return val;\n };\n // Resolve the field for a given data element.\n // First look for a full match with transformations already applied by the data requester.\n // Otherwise prefer a namespace match and fall back to just a name match, applying transformations on the fly.\n this.resolve = function (d) {\n if (typeof d[this.full_name] == 'undefined') {\n var val = null;\n if (typeof d[this.namespace + ':' + this.name] != 'undefined') {\n val = d[this.namespace + ':' + this.name];\n } else if (typeof d[this.name] != 'undefined') {\n val = d[this.name];\n }\n d[this.full_name] = this.applyTransformations(val);\n }\n return d[this.full_name];\n };\n };\n /**\n * The Requester manages fetching of data across multiple data sources. It is used internally by LocusZoom data layers.\n * It passes state information and ensures that data is formatted in the manner expected by the plot.\n *\n * It is also responsible for constructing a \"chain\" of dependent requests, by requesting each datasource\n * sequentially in the order specified in the datalayer `fields` array. Data sources are only chained within a\n * data layer, and only if that layer requests more than one kind of data source.\n * @param {LocusZoom.DataSources} sources An object of {ns: LocusZoom.Data.Source} instances\n * @class\n */\n LocusZoom.Data.Requester = function (sources) {\n function split_requests(fields) {\n // Given a fields array, return an object specifying what datasource names the data layer should make requests\n // to, and how to handle the returned data\n var requests = {};\n // Regular expression finds namespace:field|trans\n var re = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/;\n fields.forEach(function (raw) {\n var parts = re.exec(raw);\n var ns = parts[1] || 'base';\n var field = parts[2];\n var trans = LocusZoom.TransformationFunctions.get(parts[3]);\n if (typeof requests[ns] == 'undefined') {\n requests[ns] = {\n outnames: [],\n fields: [],\n trans: []\n };\n }\n requests[ns].outnames.push(raw);\n requests[ns].fields.push(field);\n requests[ns].trans.push(trans);\n });\n return requests;\n }\n /**\n * Fetch data, and create a chain that only connects two data sources if they depend on each other\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields The list of data fields specified in the `layout` for a specific data layer\n * @returns {Promise}\n */\n this.getData = function (state, fields) {\n var requests = split_requests(fields);\n // Create an array of functions that, when called, will trigger the request to the specified datasource\n var request_handles = Object.keys(requests).map(function (key) {\n if (!sources.get(key)) {\n throw new Error('Datasource for namespace ' + key + ' not found');\n }\n return sources.get(key).getData(state, requests[key].fields, requests[key].outnames, requests[key].trans);\n });\n //assume the fields are requested in dependent order\n //TODO: better manage dependencies\n var ret = Promise.resolve({\n header: {},\n body: [],\n discrete: {}\n });\n for (var i = 0; i < request_handles.length; i++) {\n // If a single datalayer uses multiple sources, perform the next request when the previous one completes\n ret = ret.then(request_handles[i]);\n }\n return ret;\n };\n };\n /**\n * Base class for LocusZoom data sources\n * This can be extended with .extend() to create custom data sources\n * @class\n * @public\n */\n LocusZoom.Data.Source = function () {\n /**\n * Whether this source should enable caching\n * @member {Boolean}\n */\n this.enableCache = true;\n /**\n * Whether this data source type is dependent on previous requests- for example, the LD source cannot annotate\n * association data if no data was found for that region.\n * @member {boolean}\n */\n this.dependentSource = false;\n };\n /**\n * A default constructor that can be used when creating new data sources\n * @param {String|Object} init Basic configuration- either a url, or a config object\n * @param {String} [init.url] The datasource URL\n * @param {String} [init.params] Initial config params for the datasource\n */\n LocusZoom.Data.Source.prototype.parseInit = function (init) {\n if (typeof init === 'string') {\n /** @member {String} */\n this.url = init;\n /** @member {String} */\n this.params = {};\n } else {\n this.url = init.url;\n this.params = init.params || {};\n }\n if (!this.url) {\n throw new Error('Source not initialized with required URL');\n }\n };\n /**\n * A unique identifier that indicates whether cached data is valid for this request\n * @protected\n * @param state\n * @param chain\n * @param fields\n * @returns {String|undefined}\n */\n LocusZoom.Data.Source.prototype.getCacheKey = function (state, chain, fields) {\n return this.getURL && this.getURL(state, chain, fields);\n };\n /**\n * Stub: build the URL for any requests made by this source.\n */\n LocusZoom.Data.Source.prototype.getURL = function (state, chain, fields) {\n return this.url;\n };\n /**\n * Perform a network request to fetch data for this source\n * @protected\n * @param {Object} state The state of the parent plot\n * @param chain\n * @param fields\n * @returns {Promise}\n */\n LocusZoom.Data.Source.prototype.fetchRequest = function (state, chain, fields) {\n var url = this.getURL(state, chain, fields);\n return LocusZoom.createCORSPromise('GET', url);\n };\n /**\n * Gets the data for just this source, typically via a network request (caching where possible)\n * @protected\n */\n LocusZoom.Data.Source.prototype.getRequest = function (state, chain, fields) {\n var req;\n var cacheKey = this.getCacheKey(state, chain, fields);\n if (this.enableCache && typeof cacheKey !== 'undefined' && cacheKey === this._cachedKey) {\n req = Promise.resolve(this._cachedResponse); // Resolve to the value of the current promise\n } else {\n req = this.fetchRequest(state, chain, fields);\n if (this.enableCache) {\n this._cachedKey = cacheKey;\n this._cachedResponse = req;\n }\n }\n return req;\n };\n /**\n * Fetch the data from the specified data source, and apply transformations requested by an external consumer.\n * This is the public-facing datasource method that will most commonly be called by external code.\n *\n * @public\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields Array of field names that the plot has requested from this data source. (without the \"namespace\" prefix)\n * @param {String[]} outnames Array describing how the output data should refer to this field. This represents the\n * originally requested field name, including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {function} A callable operation that can be used as part of the data chain\n */\n LocusZoom.Data.Source.prototype.getData = function (state, fields, outnames, trans) {\n if (this.preGetData) {\n var pre = this.preGetData(state, fields, outnames, trans);\n if (this.pre) {\n state = pre.state || state;\n fields = pre.fields || fields;\n outnames = pre.outnames || outnames;\n trans = pre.trans || trans;\n }\n }\n var self = this;\n return function (chain) {\n if (self.dependentSource && chain && chain.body && !chain.body.length) {\n // A \"dependent\" source should not attempt to fire a request if there is no data for it to act on.\n // Therefore, it should simply return the previous data chain.\n return Promise.resolve(chain);\n }\n return self.getRequest(state, chain, fields).then(function (resp) {\n return self.parseResponse(resp, chain, fields, outnames, trans);\n });\n };\n };\n /**\n * Ensure the server response is in a canonical form, an array of one object per record. [ {field: oneval} ].\n * If the server response contains columns, reformats the response from {column1: [], column2: []} to the above.\n *\n * Does not apply namespacing, transformations, or field extraction.\n *\n * May be overridden by data sources that inherently return more complex payloads, or that exist to annotate other\n * sources (eg, if the payload provides extra data rather than a series of records).\n *\n * @param {Object[]|Object} data The original parsed server response\n * @protected\n */\n LocusZoom.Data.Source.prototype.normalizeResponse = function (data) {\n if (Array.isArray(data)) {\n // Already in the desired form\n return data;\n }\n // Otherwise, assume the server response is an object representing columns of data.\n // Each array should have the same length (verify), and a given array index corresponds to a single row.\n var keys = Object.keys(data);\n var N = data[keys[0]].length;\n var sameLength = keys.every(function (key) {\n var item = data[key];\n return item.length === N;\n });\n if (!sameLength) {\n throw new Error(this.constructor.SOURCE_NAME + ' expects a response in which all arrays of data are the same length');\n }\n // Go down the rows, and create an object for each record\n var records = [];\n var fields = Object.keys(data);\n for (var i = 0; i < N; i++) {\n var record = {};\n for (var j = 0; j < fields.length; j++) {\n record[fields[j]] = data[fields[j]][i];\n }\n records.push(record);\n }\n return records;\n };\n /** @deprecated */\n LocusZoom.Data.Source.prototype.prepareData = function (records) {\n console.warn('Warning: .prepareData() is deprecated. Use .annotateData() instead');\n return this.annotateData(records);\n };\n /**\n * Hook to post-process the data returned by this source with new, additional behavior.\n * (eg cleaning up API values or performing complex calculations on the returned data)\n *\n * @param {Object[]} records The parsed data from the source (eg standardized api response)\n * @param {Object} chain The data chain object. For example, chain.headers may provide useful annotation metadata\n * @returns {Object[]|Promise} The modified set of records\n */\n LocusZoom.Data.Source.prototype.annotateData = function (records, chain) {\n // Default behavior: no transformations\n return records;\n };\n /**\n * Clean up the server records for use by datalayers: extract only certain fields, with the specified names.\n * Apply per-field transformations as appropriate.\n *\n * This hook can be overridden, eg to create a source that always returns all records and ignores the \"fields\" array.\n * This is particularly common for sources at the end of a chain- many \"dependent\" sources do not allow\n * cherry-picking individual fields, in which case by **convention** the fields array specifies \"last_source_name:all\"\n *\n * @param {Object[]} data One record object per element\n * @param {String[]} fields The names of fields to extract (as named in the source data). Eg \"afield\"\n * @param {String[]} outnames How to represent the source fields in the output. Eg \"namespace:afield|atransform\"\n * @param {function[]} trans An array of transformation functions (if any). One function per data element, or null.\n * @protected\n */\n LocusZoom.Data.Source.prototype.extractFields = function (data, fields, outnames, trans) {\n //intended for an array of objects\n // [ {\"id\":1, \"val\":5}, {\"id\":2, \"val\":10}]\n // Since a number of sources exist that do not obey this format, we will provide a convenient pass-through\n if (!Array.isArray(data)) {\n return data;\n }\n if (!data.length) {\n // Sometimes there are regions that just don't have data- this should not trigger a missing field error message!\n return data;\n }\n var fieldFound = [];\n for (var k = 0; k < fields.length; k++) {\n fieldFound[k] = 0;\n }\n var records = data.map(function (item) {\n var output_record = {};\n for (var j = 0; j < fields.length; j++) {\n var val = item[fields[j]];\n if (typeof val != 'undefined') {\n fieldFound[j] = 1;\n }\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n output_record[outnames[j]] = val;\n }\n return output_record;\n });\n fieldFound.forEach(function (v, i) {\n if (!v) {\n throw new Error('field ' + fields[i] + ' not found in response for ' + outnames[i]);\n }\n });\n return records;\n };\n /**\n * Combine records from this source with others in the chain to yield final chain body.\n * Handles merging this data with other sources (if applicable).\n *\n * @param {Object[]} data The data That would be returned from this source alone\n * @param {Object} chain The data chain built up during previous requests\n * @param {String[]} fields\n * @param {String[]} outnames\n * @return {Promise|Object[]} The new chain body\n * @protected\n */\n LocusZoom.Data.Source.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n return data;\n };\n /**\n * Coordinates the work of parsing a response and returning records. This is broken into 4 steps, which may be\n * overridden separately for fine-grained control. Each step can return either raw data or a promise.\n *\n * @public\n * @param {String|Object} resp The raw data associated with the response\n * @param {Object} chain The combined parsed response data from this and all other requests made in the chain\n * @param {String[]} fields Array of requested field names (as they would appear in the response payload)\n * @param {String[]} outnames Array of field names as they will be represented in the data returned by this source,\n * including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {Promise|{header: ({}|*), discrete: {}, body: []}} A promise that resolves to an object containing\n * request metadata (headers), the consolidated data for plotting (body), and the individual responses that would be\n * returned by each source in the chain in isolation (discrete)\n */\n LocusZoom.Data.Source.prototype.parseResponse = function (resp, chain, fields, outnames, trans) {\n var source_id = this.source_id || this.constructor.SOURCE_NAME;\n if (!chain.discrete) {\n chain.discrete = {};\n }\n if (!resp) {\n // FIXME: Hack. Certain browser issues (such as mixed content warnings) are reported as a successful promise\n // resolution, even though the request was aborted. This is difficult to reliably detect, and is most likely\n // to occur for annotation sources (such as from ExAC). If empty response is received, skip parsing and log.\n // FIXME: Throw an error after pending, eg https://github.com/konradjk/exac_browser/issues/345\n console.error('No usable response was returned for source: \\'' + source_id + '\\'. Parsing will be skipped.');\n return Promise.resolve(chain);\n }\n var json = typeof resp == 'string' ? JSON.parse(resp) : resp;\n var self = this;\n // Perform the 4 steps of parsing the payload and return a combined chain object\n return Promise.resolve(self.normalizeResponse(json.data || json)).then(function (standardized) {\n // Perform calculations on the data from just this source\n return Promise.resolve(self.annotateData(standardized, chain));\n }).then(function (data) {\n return Promise.resolve(self.extractFields(data, fields, outnames, trans));\n }).then(function (one_source_body) {\n // Store a copy of the data that would be returned by parsing this source in isolation (and taking the\n // fields array into account). This is useful when we want to re-use the source output in many ways.\n chain.discrete[source_id] = one_source_body;\n return Promise.resolve(self.combineChainBody(one_source_body, chain, fields, outnames, trans));\n }).then(function (new_body) {\n return {\n header: chain.header || {},\n discrete: chain.discrete,\n body: new_body\n };\n });\n };\n /** @deprecated */\n LocusZoom.Data.Source.prototype.parseArraysToObjects = function (data, fields, outnames, trans) {\n console.warn('Warning: .parseArraysToObjects() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n };\n /** @deprecated */\n LocusZoom.Data.Source.prototype.parseObjectsToObjects = function (data, fields, outnames, trans) {\n console.warn('Warning: .parseObjectsToObjects() is deprecated. Use .extractFields() instead');\n return this.extractFields(data, fields, outnames, trans);\n };\n /** @deprecated */\n LocusZoom.Data.Source.prototype.parseData = function (data, fields, outnames, trans) {\n console.warn('Warning: .parseData() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n };\n /**\n * Method to define new custom datasources based on a provided constructor. (does not allow registering any additional methods)\n * @public\n * @param {Function} constructorFun Constructor function that is used to create the specified class\n * @param {String} [uniqueName] The name by which the class should be listed in `KnownDataSources`\n * @param {String|Function} [base=LocusZoomData.Source] The name or constructor of a base class to use\n * @returns {*|Function}\n */\n LocusZoom.Data.Source.extend = function (constructorFun, uniqueName, base) {\n if (base) {\n if (Array.isArray(base)) {\n base = LocusZoom.KnownDataSources.create.apply(null, base);\n } else if (typeof base === 'string') {\n base = LocusZoom.KnownDataSources.get(base).prototype;\n } else if (typeof base === 'function') {\n base = base.prototype;\n }\n } else {\n base = new LocusZoom.Data.Source();\n }\n constructorFun = constructorFun || function () {\n };\n constructorFun.prototype = base;\n constructorFun.prototype.constructor = constructorFun;\n if (uniqueName) {\n /** @member {String} LocusZoom.Data.Source.SOURCENAME */\n constructorFun.SOURCE_NAME = uniqueName;\n LocusZoom.KnownDataSources.add(constructorFun);\n }\n return constructorFun;\n };\n /**\n * Datasources can be instantiated from a JSON object instead of code. This represents an existing source in that data format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n *\n * Custom sources with their own parameters may need to re-implement this method\n *\n * @public\n * @returns {Object}\n */\n LocusZoom.Data.Source.prototype.toJSON = function () {\n return [\n Object.getPrototypeOf(this).constructor.SOURCE_NAME,\n {\n url: this.url,\n params: this.params\n }\n ];\n };\n /**\n * Data Source for Association Data, as fetched from the LocusZoom API server (or compatible)\n * @class\n * @public\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.AssociationSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'AssociationLZ');\n LocusZoom.Data.AssociationSource.prototype.preGetData = function (state, fields, outnames, trans) {\n var id_field = this.params.id_field || 'id';\n [\n id_field,\n 'position'\n ].forEach(function (x) {\n if (fields.indexOf(x) === -1) {\n fields.unshift(x);\n outnames.unshift(x);\n trans.unshift(null);\n }\n });\n return {\n fields: fields,\n outnames: outnames,\n trans: trans\n };\n };\n LocusZoom.Data.AssociationSource.prototype.getURL = function (state, chain, fields) {\n var analysis = chain.header.analysis || this.params.source || this.params.analysis;\n // Old usages called this param \"analysis\"\n if (typeof analysis == 'undefined') {\n throw new Error('Association source must specify an analysis ID to plot');\n }\n return this.url + 'results/?filter=analysis in ' + analysis + ' and chromosome in \\'' + state.chr + '\\'' + ' and position ge ' + state.start + ' and position le ' + state.end;\n };\n LocusZoom.Data.AssociationSource.prototype.normalizeResponse = function (data) {\n // Some association sources do not sort their data in a predictable order, which makes it hard to reliably\n // align with other sources (such as LD). For performance reasons, sorting is an opt-in argument.\n // TODO: Consider more fine grained sorting control in the future\n data = LocusZoom.Data.Source.prototype.normalizeResponse.call(this, data);\n if (this.params && this.params.sort && data.length && data[0]['position']) {\n data.sort(function (a, b) {\n return a['position'] - b['position'];\n });\n }\n return data;\n };\n /**\n * Data Source for LD Data, as fetched from the LocusZoom API server (or compatible)\n * This source is designed to connect its results to association data, and therefore depends on association data having\n * been loaded by a previous request in the data chain.\n *\n * This source is deprecated in favor of a new, standalone LD server. For new usages, see LDLZ2.\n *\n * @class\n * @deprecated\n * @public\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.LDSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n this.dependentSource = true;\n }, 'LDLZ');\n LocusZoom.Data.LDSource.prototype.preGetData = function (state, fields) {\n if (fields.length > 1) {\n if (fields.length !== 2 || fields.indexOf('isrefvar') === -1) {\n throw new Error('LD does not know how to get all fields: ' + fields.join(', '));\n }\n }\n };\n LocusZoom.Data.LDSource.prototype.findMergeFields = function (chain) {\n // Find the fields (as provided by a previous step in the chain, like an association source) that will be needed to\n // combine LD data with existing information\n // Since LD information may be shared across multiple assoc sources with different namespaces,\n // we use regex to find columns to join on, rather than requiring exact matches\n var exactMatch = function (arr) {\n return function () {\n var regexes = arguments;\n for (var i = 0; i < regexes.length; i++) {\n var regex = regexes[i];\n var m = arr.filter(function (x) {\n return x.match(regex);\n });\n if (m.length) {\n return m[0];\n }\n }\n return null;\n };\n };\n var dataFields = {\n id: this.params.id_field,\n position: this.params.position_field,\n pvalue: this.params.pvalue_field,\n _names_: null\n };\n if (chain && chain.body && chain.body.length > 0) {\n var names = Object.keys(chain.body[0]);\n var nameMatch = exactMatch(names);\n // Internally, fields are generally prefixed with the name of the source they come from.\n // If the user provides an id_field (like `variant`), it should work across data sources( `assoc1:variant`,\n // assoc2:variant), but not match fragments of other field names (assoc1:variant_thing)\n // Note: these lookups hard-code a couple of common fields that will work based on known APIs in the wild\n var id_match = dataFields.id && nameMatch(new RegExp(dataFields.id + '\\\\b'));\n dataFields.id = id_match || nameMatch(/\\bvariant\\b/) || nameMatch(/\\bid\\b/);\n dataFields.position = dataFields.position || nameMatch(/\\bposition\\b/i, /\\bpos\\b/i);\n dataFields.pvalue = dataFields.pvalue || nameMatch(/\\bpvalue\\b/i, /\\blog_pvalue\\b/i);\n dataFields._names_ = names;\n }\n return dataFields;\n };\n LocusZoom.Data.LDSource.prototype.findRequestedFields = function (fields, outnames) {\n // Assumption: all usages of this source will only ever ask for \"isrefvar\" or \"state\". This maps to output names.\n var obj = {};\n for (var i = 0; i < fields.length; i++) {\n if (fields[i] === 'isrefvar') {\n obj.isrefvarin = fields[i];\n obj.isrefvarout = outnames && outnames[i];\n } else {\n obj.ldin = fields[i];\n obj.ldout = outnames && outnames[i];\n }\n }\n return obj;\n };\n LocusZoom.Data.LDSource.prototype.normalizeResponse = function (data) {\n return data;\n };\n /**\n * Get the LD reference variant, which by default will be the most significant hit in the assoc results\n * This will be used in making the original query to the LD server for pairwise LD information\n * @returns {*|string} The marker id (expected to be in `chr:pos_ref/alt` format) of the reference variant\n */\n LocusZoom.Data.LDSource.prototype.getRefvar = function (state, chain, fields) {\n var findExtremeValue = function (records, pval_field) {\n // Finds the most significant hit (smallest pvalue, or largest -log10p). Will try to auto-detect the appropriate comparison.\n pval_field = pval_field || 'log_pvalue';\n // The official LZ API returns log_pvalue\n var is_log = /log/.test(pval_field);\n var cmp;\n if (is_log) {\n cmp = function (a, b) {\n return a > b;\n };\n } else {\n cmp = function (a, b) {\n return a < b;\n };\n }\n var extremeVal = records[0][pval_field], extremeIdx = 0;\n for (var i = 1; i < records.length; i++) {\n if (cmp(records[i][pval_field], extremeVal)) {\n extremeVal = records[i][pval_field];\n extremeIdx = i;\n }\n }\n return extremeIdx;\n };\n var reqFields = this.findRequestedFields(fields);\n var refVar = reqFields.ldin;\n if (refVar === 'state') {\n refVar = state.ldrefvar || chain.header.ldrefvar || 'best';\n }\n if (refVar === 'best') {\n if (!chain.body) {\n throw new Error('No association data found to find best pvalue');\n }\n var keys = this.findMergeFields(chain);\n if (!keys.pvalue || !keys.id) {\n var columns = '';\n if (!keys.id) {\n columns += (columns.length ? ', ' : '') + 'id';\n }\n if (!keys.pvalue) {\n columns += (columns.length ? ', ' : '') + 'pvalue';\n }\n throw new Error('Unable to find necessary column(s) for merge: ' + columns + ' (available: ' + keys._names_ + ')');\n }\n refVar = chain.body[findExtremeValue(chain.body, keys.pvalue)][keys.id];\n }\n return refVar;\n };\n LocusZoom.Data.LDSource.prototype.getURL = function (state, chain, fields) {\n var refSource = state.ldrefsource || chain.header.ldrefsource || 1;\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n return this.url + 'results/?filter=reference eq ' + refSource + ' and chromosome2 eq \\'' + state.chr + '\\'' + ' and position2 ge ' + state.start + ' and position2 le ' + state.end + ' and variant1 eq \\'' + refVar + '\\'' + '&fields=chr,pos,rsquare';\n };\n LocusZoom.Data.LDSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n var keys = this.findMergeFields(chain);\n var reqFields = this.findRequestedFields(fields, outnames);\n if (!keys.position) {\n throw new Error('Unable to find position field for merge: ' + keys._names_);\n }\n var leftJoin = function (left, right, lfield, rfield) {\n var i = 0, j = 0;\n while (i < left.length && j < right.position2.length) {\n if (left[i][keys.position] === right.position2[j]) {\n left[i][lfield] = right[rfield][j];\n i++;\n j++;\n } else if (left[i][keys.position] < right.position2[j]) {\n i++;\n } else {\n j++;\n }\n }\n };\n var tagRefVariant = function (data, refvar, idfield, outrefname, outldname) {\n for (var i = 0; i < data.length; i++) {\n if (data[i][idfield] && data[i][idfield] === refvar) {\n data[i][outrefname] = 1;\n data[i][outldname] = 1; // For label/filter purposes, implicitly mark the ref var as LD=1 to itself\n } else {\n data[i][outrefname] = 0;\n }\n }\n };\n // LD servers vary slightly. Some report corr as \"rsquare\", others as \"correlation\"\n var corrField = data.rsquare ? 'rsquare' : 'correlation';\n leftJoin(chain.body, data, reqFields.ldout, corrField);\n if (reqFields.isrefvarin && chain.header.ldrefvar) {\n tagRefVariant(chain.body, chain.header.ldrefvar, keys.id, reqFields.isrefvarout, reqFields.ldout);\n }\n return chain.body;\n };\n /**\n * Fetch LD directly from the standalone Portal LD server\n *\n * @class\n * @public\n * @augments LocusZoom.Data.LDSource\n */\n LocusZoom.Data.LDSource2 = LocusZoom.KnownDataSources.extend('LDLZ', 'LDLZ2', {\n getURL: function (state, chain, fields) {\n // Accept the following params in this.params:\n // - method (r, rsquare, cov)\n // - source (aka panel)\n // - population (ALL, AFR, EUR, etc)\n // - build\n // The LD source/pop can be overridden from plot.state for dynamic layouts\n var build = state.genome_build || this.params.build || 'GRCh37';\n var source = state.ld_source || this.params.source || '1000G';\n var population = state.ld_pop || this.params.population || 'ALL';\n // LDServer panels will always have an ALL\n var method = this.params.method || 'rsquare';\n validateBuildSource(this.constructor.SOURCE_NAME, build, null);\n // LD doesn't need to validate `source` option\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n return [\n this.url,\n 'genome_builds/',\n build,\n '/references/',\n source,\n '/populations/',\n population,\n '/variants',\n '?correlation=',\n method,\n '&variant=',\n encodeURIComponent(refVar),\n '&chrom=',\n encodeURIComponent(state.chr),\n '&start=',\n encodeURIComponent(state.start),\n '&stop=',\n encodeURIComponent(state.end)\n ].join('');\n },\n fetchRequest: function (state, chain, fields) {\n // The API is paginated, but we need all of the data to render a plot. Depaginate and combine where appropriate.\n var url = this.getURL(state, chain, fields);\n var combined = { data: {} };\n var chainRequests = function (url) {\n return LocusZoom.createCORSPromise('GET', url).then(function (payload) {\n payload = JSON.parse(payload);\n Object.keys(payload.data).forEach(function (key) {\n combined.data[key] = (combined.data[key] || []).concat(payload.data[key]);\n });\n if (payload.next) {\n return chainRequests(payload.next);\n }\n return combined;\n });\n };\n return chainRequests(url);\n }\n });\n /**\n * Data source for GWAS catalogs of known variants\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object|String} init Configuration (URL or object)\n * @param {Object} [init.params] Optional configuration parameters\n * @param {Number} [init.params.source=2] The ID of the chosen catalog. Defaults to EBI GWAS catalog, GRCh37\n * @param {('strict'|'loose')} [init.params.match_type='strict'] Whether to match on exact variant, or just position.\n */\n LocusZoom.Data.GwasCatalog = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n this.dependentSource = true;\n }, 'GwasCatalogLZ');\n LocusZoom.Data.GwasCatalog.prototype.getURL = function (state, chain, fields) {\n // This is intended to be aligned with another source- we will assume they are always ordered by position, asc\n // (regardless of the actual match field)\n var build_option = state.genome_build || this.params.build;\n validateBuildSource(this.constructor.SOURCE_NAME, build_option, null);\n // Source can override build- not mutually exclusive\n // Most of our annotations will respect genome build before any other option.\n // But there can be more than one GWAS catalog for the same build, so an explicit config option will always take\n // precedence.\n var default_source = build_option === 'GRCh38' ? 1 : 2;\n // EBI GWAS catalog\n var source = this.params.source || default_source;\n return this.url + '?format=objects&sort=pos&filter=id eq ' + source + ' and chrom eq \\'' + state.chr + '\\'' + ' and pos ge ' + state.start + ' and pos le ' + state.end;\n };\n LocusZoom.Data.GwasCatalog.prototype.findMergeFields = function (records) {\n // Data from previous sources is already namespaced. Find the alignment field by matching.\n var knownFields = Object.keys(records);\n // Note: All API endoints involved only give results for 1 chromosome at a time; match is implied\n var posMatch = knownFields.find(function (item) {\n return item.match(/\\b(position|pos)\\b/i);\n });\n if (!posMatch) {\n throw new Error('Could not find data to align with GWAS catalog results');\n }\n return { 'pos': posMatch };\n };\n // Skip the \"individual field extraction\" step; extraction will be handled when building chain body instead\n LocusZoom.Data.GwasCatalog.prototype.extractFields = function (data, fields, outnames, trans) {\n return data;\n };\n LocusZoom.Data.GwasCatalog.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data.length) {\n return chain.body;\n }\n var decider = 'log_pvalue';\n // TODO: Better reuse options in the future\n var decider_out = outnames[fields.indexOf(decider)];\n function leftJoin(left, right, fields, outnames, trans) {\n // Add `fields` from `right` to `left`\n // Add a synthetic, un-namespaced field to all matching records\n var n_matches = left['n_catalog_matches'] || 0;\n left['n_catalog_matches'] = n_matches + 1;\n if (decider && left[decider_out] && left[decider_out] > right[decider]) {\n // There may be more than one GWAS catalog entry for the same SNP. This source is intended for a 1:1\n // annotation scenario, so for now it only joins the catalog entry that has the best -log10 pvalue\n return;\n }\n for (var j = 0; j < fields.length; j++) {\n var fn = fields[j];\n var outn = outnames[j];\n var val = right[fn];\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n left[outn] = val;\n }\n }\n var chainNames = this.findMergeFields(chain.body[0]);\n var catNames = this.findMergeFields(data[0]);\n var i = 0, j = 0;\n while (i < chain.body.length && j < data.length) {\n var left = chain.body[i];\n var right = data[j];\n if (left[chainNames.pos] === right[catNames.pos]) {\n // There may be multiple catalog entries for each matching SNP; evaluate match one at a time\n leftJoin(left, right, fields, outnames, trans);\n j += 1;\n } else if (left[chainNames.pos] < right[catNames.pos]) {\n i += 1;\n } else {\n j += 1;\n }\n }\n return chain.body;\n };\n /**\n * Data Source for Gene Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.GeneSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'GeneLZ');\n LocusZoom.Data.GeneSource.prototype.getURL = function (state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n if (build) {\n // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = build === 'GRCh38' ? 1 : 3;\n }\n return this.url + '?filter=source in ' + source + ' and chrom eq \\'' + state.chr + '\\'' + ' and start le ' + state.end + ' and end ge ' + state.start;\n };\n // Genes have a very complex internal data format. Bypass any record parsing, and provide the data layer with the\n // exact information returned by the API. (ignoring the fields array in the layout)\n LocusZoom.Data.GeneSource.prototype.normalizeResponse = function (data) {\n return data;\n };\n LocusZoom.Data.GeneSource.prototype.extractFields = function (data, fields, outnames, trans) {\n return data;\n };\n /**\n * Data Source for Gene Constraint Data, as fetched from the ExAC server (or compatible)\n *\n * FIXME: The ExAc server has been decommissioned. This source is kept here to avoid breaking existing layouts; we may\n * be able to restore this feature in the future once the gnomAD API is further developed\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n*/\n LocusZoom.Data.GeneConstraintSource = LocusZoom.Data.Source.extend(function (init) {\n console.warn('The gene constraint source depends on a server (ExAC) that is no longer active. This information may not be displayed.');\n this.parseInit(init);\n }, 'GeneConstraintLZ');\n LocusZoom.Data.GeneConstraintSource.prototype.getURL = function () {\n return this.url;\n };\n LocusZoom.Data.GeneConstraintSource.prototype.normalizeResponse = function (data) {\n return data;\n };\n LocusZoom.Data.GeneConstraintSource.prototype.getCacheKey = function (state, chain, fields) {\n return this.url + JSON.stringify(state);\n };\n LocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function (state, chain, fields) {\n var geneids = [];\n chain.body.forEach(function (gene) {\n var gene_id = gene.gene_id;\n if (gene_id.indexOf('.')) {\n gene_id = gene_id.substr(0, gene_id.indexOf('.'));\n }\n geneids.push(gene_id);\n });\n var url = this.getURL(state, chain, fields);\n var body = 'geneids=' + encodeURIComponent(JSON.stringify(geneids));\n var headers = { 'Content-Type': 'application/x-www-form-urlencoded' };\n return LocusZoom.createCORSPromise('POST', url, body, headers);\n };\n LocusZoom.Data.GeneConstraintSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data) {\n return chain;\n }\n var constraint_fields = [\n 'bp',\n 'exp_lof',\n 'exp_mis',\n 'exp_syn',\n 'lof_z',\n 'mis_z',\n 'mu_lof',\n 'mu_mis',\n 'mu_syn',\n 'n_exons',\n 'n_lof',\n 'n_mis',\n 'n_syn',\n 'pLI',\n 'syn_z'\n ];\n chain.body.forEach(function (gene, i) {\n var gene_id = gene.gene_id;\n if (gene_id.indexOf('.')) {\n gene_id = gene_id.substr(0, gene_id.indexOf('.'));\n }\n constraint_fields.forEach(function (field) {\n // Do not overwrite any fields defined in the original gene source\n if (typeof chain.body[i][field] != 'undefined') {\n return;\n }\n if (data[gene_id]) {\n var val = data[gene_id][field];\n if (typeof val == 'number' && val.toString().indexOf('.') !== -1) {\n val = parseFloat(val.toFixed(2));\n }\n chain.body[i][field] = val;\n } else {\n // If the gene did not come back in the response then set the same field with a null values\n chain.body[i][field] = null;\n }\n });\n });\n return chain.body;\n };\n /**\n * Data Source for Recombination Rate Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.RecombinationRateSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'RecombLZ');\n LocusZoom.Data.RecombinationRateSource.prototype.getURL = function (state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n if (build) {\n // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = build === 'GRCh38' ? 16 : 15;\n }\n return this.url + '?filter=id in ' + source + ' and chromosome eq \\'' + state.chr + '\\'' + ' and position le ' + state.end + ' and position ge ' + state.start;\n };\n /**\n * Data Source for Interval Annotation Data (e.g. BED Tracks), as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.IntervalSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'IntervalLZ');\n LocusZoom.Data.IntervalSource.prototype.getURL = function (state, chain, fields) {\n var source = chain.header.bedtracksource || this.params.source;\n return this.url + '?filter=id in ' + source + ' and chromosome eq \\'' + state.chr + '\\'' + ' and start le ' + state.end + ' and end ge ' + state.start;\n };\n /**\n * Data Source for static blobs of JSON Data. This does not perform additional parsing, and therefore it is the\n * responsibility of the user to pass information in a format that can be read and understood by the chosen plot.\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.StaticSource = LocusZoom.Data.Source.extend(function (data) {\n /** @member {Object} */\n this._data = data;\n }, 'StaticJSON');\n LocusZoom.Data.StaticSource.prototype.getRequest = function (state, chain, fields) {\n return Promise.resolve(this._data);\n };\n LocusZoom.Data.StaticSource.prototype.toJSON = function () {\n return [\n Object.getPrototypeOf(this).constructor.SOURCE_NAME,\n this._data\n ];\n };\n /**\n * Data source for PheWAS data\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {String[]} init.params.build This datasource expects to be provided the name of the genome build that will\n * be used to provide pheWAS results for this position. Note positions may not translate between builds.\n */\n LocusZoom.Data.PheWASSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'PheWASLZ');\n LocusZoom.Data.PheWASSource.prototype.getURL = function (state, chain, fields) {\n var build = (state.genome_build ? [state.genome_build] : null) || this.params.build;\n if (!build || !Array.isArray(build) || !build.length) {\n throw new Error([\n 'Data source',\n this.constructor.SOURCE_NAME,\n 'requires that you specify array of one or more desired genome build names'\n ].join(' '));\n }\n var url = [\n this.url,\n '?filter=variant eq \\'',\n encodeURIComponent(state.variant),\n '\\'&format=objects&',\n build.map(function (item) {\n return 'build=' + encodeURIComponent(item);\n }).join('&')\n ];\n return url.join('');\n };\n /**\n * Base class for \"connectors\"- this is meant to be subclassed, rather than used directly.\n *\n * A connector is a source that makes no server requests and caches no data of its own. Instead, it decides how to\n * combine data from other sources in the chain. Connectors are useful when we want to request (or calculate) some\n * useful piece of information once, but apply it to many different kinds of record types.\n *\n * Typically, a subclass will implement the field merging logic in `combineChainBody`.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object} init Configuration for this source\n * @param {Object} init.sources Specify how the hard-coded logic should find the data it relies on in the chain,\n * as {internal_name: chain_source_id} pairs. This allows writing a reusable connector that does not need to make\n * assumptions about what namespaces a source is using.\n * @type {*|Function}\n */\n LocusZoom.Data.ConnectorSource = LocusZoom.Data.Source.extend(function (init) {\n if (!init || !init.sources) {\n throw new Error('Connectors must specify the data they require as init.sources = {internal_name: chain_source_id}} pairs');\n }\n /**\n * Tells the connector how to find the data it relies on\n *\n * For example, a connector that applies burden test information to the genes layer might specify:\n * {gene_ns: \"gene\", aggregation_ns: \"aggregation\"}\n *\n * @member {Object}\n */\n this._source_name_mapping = init.sources;\n // Validate that this source has been told how to find the required information\n var specified_ids = Object.keys(init.sources);\n var self = this;\n this.REQUIRED_SOURCES.forEach(function (k) {\n if (specified_ids.indexOf(k) === -1) {\n throw new Error('Configuration for ' + self.constructor.SOURCE_NAME + ' must specify a source ID corresponding to ' + k);\n }\n });\n this.parseInit(init);\n }, 'ConnectorSource');\n /** @property {String[]} Specifies the sources that must be provided in the original config object */\n LocusZoom.Data.ConnectorSource.prototype.REQUIRED_SOURCES = [];\n LocusZoom.Data.ConnectorSource.prototype.parseInit = function (init) {\n };\n // Stub\n LocusZoom.Data.ConnectorSource.prototype.getRequest = function (state, chain, fields) {\n // Connectors do not request their own data by definition, but they *do* depend on other sources having been loaded\n // first. This method performs basic validation, and preserves the accumulated body from the chain so far.\n var self = this;\n Object.keys(this._source_name_mapping).forEach(function (ns) {\n var chain_source_id = self._source_name_mapping[ns];\n if (chain.discrete && !chain.discrete[chain_source_id]) {\n throw new Error(self.constructor.SOURCE_NAME + ' cannot be used before loading required data for: ' + chain_source_id);\n }\n });\n return Promise.resolve(chain.body || []);\n };\n LocusZoom.Data.ConnectorSource.prototype.parseResponse = function (data, chain, fields, outnames, trans) {\n // A connector source does not update chain.discrete, but it may use it. It bypasses data formatting\n // and field selection (both are assumed to have been done already, by the previous sources this draws from)\n // Because of how the chain works, connectors are not very good at applying new transformations or namespacing.\n // Typically connectors are called with `connector_name:all` in the fields array.\n return Promise.resolve(this.combineChainBody(data, chain, fields, outnames, trans)).then(function (new_body) {\n return {\n header: chain.header || {},\n discrete: chain.discrete || {},\n body: new_body\n };\n });\n };\n LocusZoom.Data.ConnectorSource.prototype.combineChainBody = function (records, chain) {\n // Stub method: specifies how to combine the data\n throw new Error('This method must be implemented in a subclass');\n };\n /* global LocusZoom */\n 'use strict';\n /**\n * An independent LocusZoom object that renders a unique set of data and subpanels.\n * Many such LocusZoom objects can exist simultaneously on a single page, each having its own layout.\n *\n * This creates a new plot instance, but does not immediately render it. For practical use, it may be more convenient\n * to use the `LocusZoom.populate` helper method.\n *\n * @class\n * @param {String} id The ID of the plot. Often corresponds to the ID of the container element on the page\n * where the plot is rendered..\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n*/\n LocusZoom.Plot = function (id, datasource, layout) {\n /** @member Boolean} */\n this.initialized = false;\n // TODO: This makes sense for all other locuszoom elements to have; determine whether this is interface boilerplate or something that can be removed\n this.parent_plot = this;\n /** @member {String} */\n this.id = id;\n /** @member {Element} */\n this.container = null;\n /**\n * Selector for a node that will contain the plot. (set externally by populate methods)\n * @member {d3.selection}\n */\n this.svg = null;\n /** @member {Object.} */\n this.panels = {};\n /**\n * TODO: This is currently used by external classes that manipulate the parent and may indicate room for a helper method in the api to coordinate boilerplate\n * @protected\n * @member {String[]}\n */\n this.panel_ids_by_y_index = [];\n /**\n * Notify each child panel of the plot of changes in panel ordering/ arrangement\n */\n this.applyPanelYIndexesToPanelLayouts = function () {\n this.panel_ids_by_y_index.forEach(function (pid, idx) {\n this.panels[pid].layout.y_index = idx;\n }.bind(this));\n };\n /**\n * Get the qualified ID pathname for the plot\n * @returns {String}\n */\n this.getBaseId = function () {\n return this.id;\n };\n /**\n * Track update operations (reMap) performed on all child panels, and notify the parent plot when complete\n * TODO: Reconsider whether we need to be tracking this as global state outside of context of specific operations\n * @protected\n * @member {Promise[]}\n */\n this.remap_promises = [];\n if (typeof layout == 'undefined') {\n /**\n * The layout is a serializable object used to describe the composition of the Plot\n * If no layout was passed, use the Standard Association Layout\n * Otherwise merge whatever was passed with the Default Layout\n * TODO: Review description; we *always* merge with default layout?\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge({}, LocusZoom.Layouts.get('plot', 'standard_association'));\n } else {\n this.layout = layout;\n }\n LocusZoom.Layouts.merge(this.layout, LocusZoom.Plot.DefaultLayout);\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original plot state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n /**\n * Create a shortcut to the state in the layout on the Plot. Tracking in the layout allows the plot to be created\n * with initial state/setup.\n *\n * Tracks state of the plot, eg start and end position\n * @member {Object}\n */\n this.state = this.layout.state;\n /** @member {LocusZoom.Data.Requester} */\n this.lzd = new LocusZoom.Data.Requester(datasource);\n /**\n * Window.onresize listener (responsive layouts only)\n * TODO: .on appears to return a selection, not a listener? Check logic here\n * https://github.com/d3/d3-selection/blob/00b904b9bcec4dfaf154ae0bbc777b1fc1d7bc08/test/selection/on-test.js#L11\n * @deprecated\n * @member {d3.selection}\n */\n this.window_onresize = null;\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [],\n // Select or unselect\n 'element_selection': [],\n // Element becomes active (only)\n 'match_requested': [],\n // A data layer is attempting to highlight matching points (internal use only)\n 'panel_removed': [],\n 'state_changed': [] // Only triggered when a state change causes rerender\n };\n /**\n * @callback eventCallback\n * @param {object} eventData A description of the event\n * @param {String|null} eventData.sourceID The unique identifier (eg plot or parent name) of the element that\n * triggered the event. Will be automatically filled in if not explicitly provided.\n * @param {Object|null} eventData.context Any additional information to be passed to the callback, eg the data\n * associated with a clicked plot element\n */\n /**\n * There are several events that a LocusZoom plot can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following plot-level events are currently supported:\n * - `layout_changed` - context: plot - Any aspect of the plot's layout (including dimensions or state) has changed.\n * - `data_requested` - context: plot - A request for new data from any data source used in the plot has been made.\n * - `data_rendered` - context: plot - Data from a request has been received and rendered in the plot.\n * - `element_clicked` - context: plot - A data element in any of the plot's data layers has been clicked.\n * - `element_selection` - context: plot - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `plot.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * plot itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} hook\n * @returns {function} The registered event listener\n */\n this.on = function (event, hook) {\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Plot}\n */\n this.off = function (event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n * @param {string} event A known event name\n * @param {*} eventData Data or event description that will be passed to the event listener\n * @returns {LocusZoom.Plot}\n */\n this.emit = function (event, eventData) {\n // TODO: there are small differences between the emit implementation between plots and panels. In the future,\n // DRY this code via mixins, and make sure to keep the interfaces compatible when refactoring.\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n var sourceID = this.getBaseId();\n var self = this;\n this.event_hooks[event].forEach(function (hookToRun) {\n var eventContext;\n if (eventData && eventData.sourceID) {\n // If we detect that an event originated elsewhere (via bubbling or externally), preserve the context\n // when re-emitting the event to plot-level listeners\n eventContext = eventData;\n } else {\n eventContext = {\n sourceID: sourceID,\n data: eventData || null\n };\n }\n // By default, any handlers fired here (either directly, or bubbled) will see the plot as the\n // value of `this`. If a bound function is registered as a handler, the previously bound `this` will\n // override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n return this;\n };\n /**\n * Get an object with the x and y coordinates of the plot's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the plot\n * @returns {{x: Number, y: Number, width: Number, height: Number}}\n */\n this.getPageOrigin = function () {\n var bounding_client_rect = this.svg.node().getBoundingClientRect();\n var x_offset = document.documentElement.scrollLeft || document.body.scrollLeft;\n var y_offset = document.documentElement.scrollTop || document.body.scrollTop;\n var container = this.svg.node();\n while (container.parentNode !== null) {\n container = container.parentNode;\n if (container !== document && d3.select(container).style('position') !== 'static') {\n x_offset = -1 * container.getBoundingClientRect().left;\n y_offset = -1 * container.getBoundingClientRect().top;\n break;\n }\n }\n return {\n x: x_offset + bounding_client_rect.left,\n y: y_offset + bounding_client_rect.top,\n width: bounding_client_rect.width,\n height: bounding_client_rect.height\n };\n };\n /**\n * Get the top and left offset values for the plot's container element (the div that was populated)\n * @returns {{top: number, left: number}}\n */\n this.getContainerOffset = function () {\n var offset = {\n top: 0,\n left: 0\n };\n var container = this.container.offsetParent || null;\n while (container !== null) {\n offset.top += container.offsetTop;\n offset.left += container.offsetLeft;\n container = container.offsetParent || null;\n }\n return offset;\n };\n //\n /**\n * Event information describing interaction (e.g. panning and zooming) is stored on the plot\n * TODO: Add/ document details of interaction structure as we expand\n * @member {{panel_id: String, linked_panel_ids: Array, x_linked: *, dragging: *, zooming: *}}\n * @returns {LocusZoom.Plot}\n */\n this.interaction = {};\n /**\n * Track whether the target panel can respond to mouse interaction events\n * @param {String} panel_id\n * @returns {boolean}\n */\n this.canInteract = function (panel_id) {\n panel_id = panel_id || null;\n if (panel_id) {\n return (typeof this.interaction.panel_id == 'undefined' || this.interaction.panel_id === panel_id) && !this.loading_data;\n } else {\n return !(this.interaction.dragging || this.interaction.zooming || this.loading_data);\n }\n };\n // Initialize the layout\n this.initializeLayout();\n return this;\n };\n /**\n * Default/ expected configuration parameters for basic plotting; most plots will override\n *\n * @protected\n * @static\n * @type {Object}\n */\n LocusZoom.Plot.DefaultLayout = {\n state: {},\n width: 1,\n height: 1,\n min_width: 1,\n min_height: 1,\n responsive_resize: false,\n // Allowed values: false, \"width_only\", \"both\" (synonym for true)\n aspect_ratio: 1,\n panels: [],\n dashboard: { components: [] },\n panel_boundaries: true,\n mouse_guide: true\n };\n /**\n * Helper method to sum the proportional dimensions of panels, a value that's checked often as panels are added/removed\n * @param {('Height'|'Width')} dimension\n * @returns {number}\n */\n LocusZoom.Plot.prototype.sumProportional = function (dimension) {\n if (dimension !== 'height' && dimension !== 'width') {\n throw new Error('Bad dimension value passed to LocusZoom.Plot.prototype.sumProportional');\n }\n var total = 0;\n for (var id in this.panels) {\n // Ensure every panel contributing to the sum has a non-zero proportional dimension\n if (!this.panels[id].layout['proportional_' + dimension]) {\n this.panels[id].layout['proportional_' + dimension] = 1 / Object.keys(this.panels).length;\n }\n total += this.panels[id].layout['proportional_' + dimension];\n }\n return total;\n };\n /**\n * Resize the plot to fit the bounding container\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.rescaleSVG = function () {\n var clientRect = this.svg.node().getBoundingClientRect();\n this.setDimensions(clientRect.width, clientRect.height);\n return this;\n };\n /**\n * Prepare the plot for first use by performing parameter validation, setting up panels, and calculating dimensions\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.initializeLayout = function () {\n // Sanity check layout values\n if (isNaN(this.layout.width) || this.layout.width <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.height) || this.layout.height <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.aspect_ratio) || this.layout.aspect_ratio <= 0) {\n throw new Error('Plot layout parameter `aspect_ratio` must be a positive number');\n }\n if (this.layout.responsive_resize === true) {\n // Backwards compatible support\n console.warn('LocusZoom \"responsive_resize\" specifies a deprecated value. The new value should be \"both\". Please update your layout.');\n this.layout.responsive_resize = 'both';\n }\n var RESIZE_MODES = [\n false,\n 'both',\n 'width_only'\n ];\n if (RESIZE_MODES.indexOf(this.layout.responsive_resize) === -1) {\n throw new Error('LocusZoom option \"responsive_resize\" should specify one of the following modes: ' + RESIZE_MODES.join(', '));\n }\n // If this is a responsive layout then set a namespaced/unique onresize event listener on the window\n if (this.layout.responsive_resize) {\n this.window_onresize = d3.select(window).on('resize.lz-' + this.id, function () {\n this.rescaleSVG();\n }.bind(this));\n // Forcing one additional setDimensions() call after the page is loaded clears up\n // any disagreements between the initial layout and the loaded responsive container's size\n d3.select(window).on('load.lz-' + this.id, function () {\n this.setDimensions();\n }.bind(this));\n }\n // Add panels\n this.layout.panels.forEach(function (panel_layout) {\n this.addPanel(panel_layout);\n }.bind(this));\n return this;\n };\n /**\n * Set the dimensions for a plot, and ensure that panels are sized and positioned correctly.\n *\n * If dimensions are provided, resizes each panel proportionally to match the new plot dimensions. Otherwise,\n * calculates the appropriate plot dimensions based on all panels.\n * @param {Number} [width] If provided and larger than minimum size, set plot to this width\n * @param {Number} [height] If provided and larger than minimum size, set plot to this height\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.setDimensions = function (width, height) {\n var id;\n // Update minimum allowable width and height by aggregating minimums from panels, then apply minimums to containing element.\n var min_width = parseFloat(this.layout.min_width) || 0;\n var min_height = parseFloat(this.layout.min_height) || 0;\n for (id in this.panels) {\n min_width = Math.max(min_width, this.panels[id].layout.min_width);\n if (parseFloat(this.panels[id].layout.min_height) > 0 && parseFloat(this.panels[id].layout.proportional_height) > 0) {\n min_height = Math.max(min_height, this.panels[id].layout.min_height / this.panels[id].layout.proportional_height);\n }\n }\n this.layout.min_width = Math.max(min_width, 1);\n this.layout.min_height = Math.max(min_height, 1);\n d3.select(this.svg.node().parentNode).style({\n 'min-width': this.layout.min_width + 'px',\n 'min-height': this.layout.min_height + 'px'\n });\n // If width and height arguments were passed then adjust them against plot minimums if necessary.\n // Then resize the plot and proportionally resize panels to fit inside the new plot dimensions.\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n // Override discrete values if resizing responsively\n if (this.layout.responsive_resize) {\n // All resize modes will affect width\n if (this.svg) {\n this.layout.width = Math.max(this.svg.node().parentNode.getBoundingClientRect().width, this.layout.min_width);\n }\n if (this.layout.responsive_resize === 'both') {\n // Then also change the height\n this.layout.height = this.layout.width / this.layout.aspect_ratio;\n if (this.layout.height < this.layout.min_height) {\n this.layout.height = this.layout.min_height;\n this.layout.width = this.layout.height * this.layout.aspect_ratio;\n }\n }\n }\n // Resize/reposition panels to fit, update proportional origins if necessary\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n var panel_width = this.layout.width;\n var panel_height = this.panels[panel_id].layout.proportional_height * this.layout.height;\n this.panels[panel_id].setDimensions(panel_width, panel_height);\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n this.panels[panel_id].layout.proportional_origin.y = y_offset / this.layout.height;\n y_offset += panel_height;\n this.panels[panel_id].dashboard.update();\n }.bind(this));\n } // If width and height arguments were NOT passed (and panels exist) then determine the plot dimensions\n // by making it conform to panel dimensions, assuming panels are already positioned correctly.\n else if (Object.keys(this.panels).length) {\n this.layout.width = 0;\n this.layout.height = 0;\n for (id in this.panels) {\n this.layout.width = Math.max(this.panels[id].layout.width, this.layout.width);\n this.layout.height += this.panels[id].layout.height;\n }\n this.layout.width = Math.max(this.layout.width, this.layout.min_width);\n this.layout.height = Math.max(this.layout.height, this.layout.min_height);\n }\n // Keep aspect ratio in agreement with dimensions\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n // Apply layout width and height as discrete values or viewbox values\n if (this.svg !== null) {\n if (this.layout.responsive_resize === 'both') {\n this.svg.attr('viewBox', '0 0 ' + this.layout.width + ' ' + this.layout.height).attr('preserveAspectRatio', 'xMinYMin meet');\n } else {\n this.svg.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n }\n // If the plot has been initialized then trigger some necessary render functions\n if (this.initialized) {\n this.panel_boundaries.position();\n this.dashboard.update();\n this.curtain.update();\n this.loader.update();\n }\n return this.emit('layout_changed');\n };\n /**\n * Create a new panel from a layout, and handle the work of initializing and placing the panel on the plot\n * @param {Object} layout\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Plot.prototype.addPanel = function (layout) {\n // Sanity checks\n if (typeof layout !== 'object') {\n throw new Error('Invalid panel layout passed to LocusZoom.Plot.prototype.addPanel()');\n }\n // Create the Panel and set its parent\n var panel = new LocusZoom.Panel(layout, this);\n // Store the Panel on the Plot\n this.panels[panel.id] = panel;\n // If a discrete y_index was set in the layout then adjust other panel y_index values to accommodate this one\n if (panel.layout.y_index !== null && !isNaN(panel.layout.y_index) && this.panel_ids_by_y_index.length > 0) {\n // Negative y_index values should count backwards from the end, so convert negatives to appropriate values here\n if (panel.layout.y_index < 0) {\n panel.layout.y_index = Math.max(this.panel_ids_by_y_index.length + panel.layout.y_index, 0);\n }\n this.panel_ids_by_y_index.splice(panel.layout.y_index, 0, panel.id);\n this.applyPanelYIndexesToPanelLayouts();\n } else {\n var length = this.panel_ids_by_y_index.push(panel.id);\n this.panels[panel.id].layout.y_index = length - 1;\n }\n // Determine if this panel was already in the layout.panels array.\n // If it wasn't, add it. Either way store the layout.panels array index on the panel.\n var layout_idx = null;\n this.layout.panels.forEach(function (panel_layout, idx) {\n if (panel_layout.id === panel.id) {\n layout_idx = idx;\n }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.panels.push(this.panels[panel.id].layout) - 1;\n }\n this.panels[panel.id].layout_idx = layout_idx;\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n this.positionPanels();\n // Initialize and load data into the new panel\n this.panels[panel.id].initialize();\n this.panels[panel.id].reMap();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n return this.panels[panel.id];\n };\n /**\n * Clear all state, tooltips, and other persisted data associated with one (or all) panel(s) in the plot\n *\n * This is useful when reloading an existing plot with new data, eg \"click for genome region\" links.\n * This is a utility method for custom usage. It is not fired automatically during normal rerender of existing panels\n * @param {String} [panelId] If provided, clear state for only this panel. Otherwise, clear state for all panels.\n * @param {('wipe'|'reset')} [mode='wipe'] Optionally specify how state should be cleared. `wipe` deletes all data\n * and is useful for when the panel is being removed; `reset` is best when the panel will be reused in place.\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.clearPanelData = function (panelId, mode) {\n mode = mode || 'wipe';\n // TODO: Add unit tests for this method\n var panelsList;\n if (panelId) {\n panelsList = [panelId];\n } else {\n panelsList = Object.keys(this.panels);\n }\n var self = this;\n panelsList.forEach(function (pid) {\n self.panels[pid].data_layer_ids_by_z_index.forEach(function (dlid) {\n var layer = self.panels[pid].data_layers[dlid];\n layer.destroyAllTooltips();\n delete self.layout.state[pid + '.' + dlid];\n if (mode === 'reset') {\n layer.setDefaultState();\n }\n });\n });\n return this;\n };\n /**\n * Remove the panel from the plot, and clear any state, tooltips, or other visual elements belonging to nested content\n * @param {String} id\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.removePanel = function (id) {\n if (!this.panels[id]) {\n throw new Error('Unable to remove panel, ID not found: ' + id);\n }\n // Hide all panel boundaries\n this.panel_boundaries.hide();\n // Destroy all tooltips and state vars for all data layers on the panel\n this.clearPanelData(id);\n // Remove all panel-level HTML overlay elements\n this.panels[id].loader.hide();\n this.panels[id].dashboard.destroy(true);\n this.panels[id].curtain.hide();\n // Remove the svg container for the panel if it exists\n if (this.panels[id].svg.container) {\n this.panels[id].svg.container.remove();\n }\n // Delete the panel and its presence in the plot layout and state\n this.layout.panels.splice(this.panels[id].layout_idx, 1);\n delete this.panels[id];\n delete this.layout.state[id];\n // Update layout_idx values for all remaining panels\n this.layout.panels.forEach(function (panel_layout, idx) {\n this.panels[panel_layout.id].layout_idx = idx;\n }.bind(this));\n // Remove the panel id from the y_index array\n this.panel_ids_by_y_index.splice(this.panel_ids_by_y_index.indexOf(id), 1);\n this.applyPanelYIndexesToPanelLayouts();\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n // Allow the plot to shrink when panels are removed, by forcing it to recalculate min dimensions from scratch\n this.layout.min_height = this._base_layout.min_height;\n this.layout.min_width = this._base_layout.min_width;\n this.positionPanels();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n this.emit('panel_removed', id);\n return this;\n };\n /**\n * Automatically position panels based on panel positioning rules and values.\n * Keep panels from overlapping vertically by adjusting origins, and keep the sum of proportional heights at 1.\n *\n * TODO: This logic currently only supports dynamic positioning of panels to prevent overlap in a VERTICAL orientation.\n * Some framework exists for positioning panels in horizontal orientations as well (width, proportional_width, origin.x, etc.)\n * but the logic for keeping these user-definable values straight approaches the complexity of a 2D box-packing algorithm.\n * That's complexity we don't need right now, and may not ever need, so it's on hiatus until a use case materializes.\n */\n LocusZoom.Plot.prototype.positionPanels = function () {\n var id;\n // We want to enforce that all x-linked panels have consistent horizontal margins\n // (to ensure that aligned items stay aligned despite inconsistent initial layout parameters)\n // NOTE: This assumes panels have consistent widths already. That should probably be enforced too!\n var x_linked_margins = {\n left: 0,\n right: 0\n };\n // Proportional heights for newly added panels default to null unless explicitly set, so determine appropriate\n // proportional heights for all panels with a null value from discretely set dimensions.\n // Likewise handle default nulls for proportional widths, but instead just force a value of 1 (full width)\n for (id in this.panels) {\n if (this.panels[id].layout.proportional_height === null) {\n this.panels[id].layout.proportional_height = this.panels[id].layout.height / this.layout.height;\n }\n if (this.panels[id].layout.proportional_width === null) {\n this.panels[id].layout.proportional_width = 1;\n }\n if (this.panels[id].layout.interaction.x_linked) {\n x_linked_margins.left = Math.max(x_linked_margins.left, this.panels[id].layout.margin.left);\n x_linked_margins.right = Math.max(x_linked_margins.right, this.panels[id].layout.margin.right);\n }\n }\n // Sum the proportional heights and then adjust all proportionally so that the sum is exactly 1\n var total_proportional_height = this.sumProportional('height');\n if (!total_proportional_height) {\n return this;\n }\n var proportional_adjustment = 1 / total_proportional_height;\n for (id in this.panels) {\n this.panels[id].layout.proportional_height *= proportional_adjustment;\n }\n // Update origins on all panels without changing plot-level dimensions yet\n // Also apply x-linked margins to x-linked panels, updating widths as needed\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n y_offset += this.panels[panel_id].layout.height;\n if (this.panels[panel_id].layout.interaction.x_linked) {\n var delta = Math.max(x_linked_margins.left - this.panels[panel_id].layout.margin.left, 0) + Math.max(x_linked_margins.right - this.panels[panel_id].layout.margin.right, 0);\n this.panels[panel_id].layout.width += delta;\n this.panels[panel_id].layout.margin.left = x_linked_margins.left;\n this.panels[panel_id].layout.margin.right = x_linked_margins.right;\n this.panels[panel_id].layout.cliparea.origin.x = x_linked_margins.left;\n }\n }.bind(this));\n var calculated_plot_height = y_offset;\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n this.panels[panel_id].layout.proportional_origin.y = this.panels[panel_id].layout.origin.y / calculated_plot_height;\n }.bind(this));\n // Update dimensions on the plot to accommodate repositioned panels\n this.setDimensions();\n // Set dimensions on all panels using newly set plot-level dimensions and panel-level proportional dimensions\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n this.panels[panel_id].setDimensions(this.layout.width * this.panels[panel_id].layout.proportional_width, this.layout.height * this.panels[panel_id].layout.proportional_height);\n }.bind(this));\n return this;\n };\n /**\n * Prepare the first rendering of the plot. This includes initializing the individual panels, but also creates shared\n * elements such as mouse events, panel guides/boundaries, and loader/curtain.\n *\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.initialize = function () {\n // Ensure proper responsive class is present on the containing node if called for\n if (this.layout.responsive_resize) {\n d3.select(this.container).classed('lz-container-responsive', true);\n }\n // Create an element/layer for containing mouse guides\n if (this.layout.mouse_guide) {\n var mouse_guide_svg = this.svg.append('g').attr('class', 'lz-mouse_guide').attr('id', this.id + '.mouse_guide');\n var mouse_guide_vertical_svg = mouse_guide_svg.append('rect').attr('class', 'lz-mouse_guide-vertical').attr('x', -1);\n var mouse_guide_horizontal_svg = mouse_guide_svg.append('rect').attr('class', 'lz-mouse_guide-horizontal').attr('y', -1);\n this.mouse_guide = {\n svg: mouse_guide_svg,\n vertical: mouse_guide_vertical_svg,\n horizontal: mouse_guide_horizontal_svg\n };\n }\n // Add curtain and loader prototpyes to the plot\n this.curtain = LocusZoom.generateCurtain.call(this);\n this.loader = LocusZoom.generateLoader.call(this);\n // Create the panel_boundaries object with show/position/hide methods\n this.panel_boundaries = {\n parent: this,\n hide_timeout: null,\n showing: false,\n dragging: false,\n selectors: [],\n corner_selector: null,\n show: function () {\n // Generate panel boundaries\n if (!this.showing && !this.parent.curtain.showing) {\n this.showing = true;\n // Loop through all panels to create a horizontal boundary for each\n this.parent.panel_ids_by_y_index.forEach(function (panel_id, panel_idx) {\n var selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip').attr('class', 'lz-panel-boundary').attr('title', 'Resize panel');\n selector.append('span');\n var panel_resize_drag = d3.behavior.drag();\n panel_resize_drag.on('dragstart', function () {\n this.dragging = true;\n }.bind(this));\n panel_resize_drag.on('dragend', function () {\n this.dragging = false;\n }.bind(this));\n panel_resize_drag.on('drag', function () {\n // First set the dimensions on the panel we're resizing\n var this_panel = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]];\n var original_panel_height = this_panel.layout.height;\n this_panel.setDimensions(this_panel.layout.width, this_panel.layout.height + d3.event.dy);\n var panel_height_change = this_panel.layout.height - original_panel_height;\n var new_calculated_plot_height = this.parent.layout.height + panel_height_change;\n // Next loop through all panels.\n // Update proportional dimensions for all panels including the one we've resized using discrete heights.\n // Reposition panels with a greater y-index than this panel to their appropriate new origin.\n this.parent.panel_ids_by_y_index.forEach(function (loop_panel_id, loop_panel_idx) {\n var loop_panel = this.parent.panels[this.parent.panel_ids_by_y_index[loop_panel_idx]];\n loop_panel.layout.proportional_height = loop_panel.layout.height / new_calculated_plot_height;\n if (loop_panel_idx > panel_idx) {\n loop_panel.setOrigin(loop_panel.layout.origin.x, loop_panel.layout.origin.y + panel_height_change);\n loop_panel.dashboard.position();\n }\n }.bind(this));\n // Reset dimensions on the entire plot and reposition panel boundaries\n this.parent.positionPanels();\n this.position();\n }.bind(this));\n selector.call(panel_resize_drag);\n this.parent.panel_boundaries.selectors.push(selector);\n }.bind(this));\n // Create a corner boundary / resize element on the bottom-most panel that resizes the entire plot\n var corner_selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip').attr('class', 'lz-panel-corner-boundary').attr('title', 'Resize plot');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-outer');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-inner');\n var corner_drag = d3.behavior.drag();\n corner_drag.on('dragstart', function () {\n this.dragging = true;\n }.bind(this));\n corner_drag.on('dragend', function () {\n this.dragging = false;\n }.bind(this));\n corner_drag.on('drag', function () {\n this.setDimensions(this.layout.width + d3.event.dx, this.layout.height + d3.event.dy);\n }.bind(this.parent));\n corner_selector.call(corner_drag);\n this.parent.panel_boundaries.corner_selector = corner_selector;\n }\n return this.position();\n },\n position: function () {\n if (!this.showing) {\n return this;\n }\n // Position panel boundaries\n var plot_page_origin = this.parent.getPageOrigin();\n this.selectors.forEach(function (selector, panel_idx) {\n var panel_page_origin = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].getPageOrigin();\n var left = plot_page_origin.x;\n var top = panel_page_origin.y + this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].layout.height - 12;\n var width = this.parent.layout.width - 1;\n selector.style({\n top: top + 'px',\n left: left + 'px',\n width: width + 'px'\n });\n selector.select('span').style({ width: width + 'px' });\n }.bind(this));\n // Position corner selector\n var corner_padding = 10;\n var corner_size = 16;\n this.corner_selector.style({\n top: plot_page_origin.y + this.parent.layout.height - corner_padding - corner_size + 'px',\n left: plot_page_origin.x + this.parent.layout.width - corner_padding - corner_size + 'px'\n });\n return this;\n },\n hide: function () {\n if (!this.showing) {\n return this;\n }\n this.showing = false;\n // Remove panel boundaries\n this.selectors.forEach(function (selector) {\n selector.remove();\n });\n this.selectors = [];\n // Remove corner boundary\n this.corner_selector.remove();\n this.corner_selector = null;\n return this;\n }\n };\n // Show panel boundaries stipulated by the layout (basic toggle, only show on mouse over plot)\n if (this.layout.panel_boundaries) {\n d3.select(this.svg.node().parentNode).on('mouseover.' + this.id + '.panel_boundaries', function () {\n clearTimeout(this.panel_boundaries.hide_timeout);\n this.panel_boundaries.show();\n }.bind(this));\n d3.select(this.svg.node().parentNode).on('mouseout.' + this.id + '.panel_boundaries', function () {\n this.panel_boundaries.hide_timeout = setTimeout(function () {\n this.panel_boundaries.hide();\n }.bind(this), 300);\n }.bind(this));\n }\n // Create the dashboard object and immediately show it\n this.dashboard = new LocusZoom.Dashboard(this).show();\n // Initialize all panels\n for (var id in this.panels) {\n this.panels[id].initialize();\n }\n // Define plot-level mouse events\n var namespace = '.' + this.id;\n if (this.layout.mouse_guide) {\n var mouseout_mouse_guide = function () {\n this.mouse_guide.vertical.attr('x', -1);\n this.mouse_guide.horizontal.attr('y', -1);\n }.bind(this);\n var mousemove_mouse_guide = function () {\n var coords = d3.mouse(this.svg.node());\n this.mouse_guide.vertical.attr('x', coords[0]);\n this.mouse_guide.horizontal.attr('y', coords[1]);\n }.bind(this);\n this.svg.on('mouseout' + namespace + '-mouse_guide', mouseout_mouse_guide).on('touchleave' + namespace + '-mouse_guide', mouseout_mouse_guide).on('mousemove' + namespace + '-mouse_guide', mousemove_mouse_guide);\n }\n var mouseup = function () {\n this.stopDrag();\n }.bind(this);\n var mousemove = function () {\n if (this.interaction.dragging) {\n var coords = d3.mouse(this.svg.node());\n if (d3.event) {\n d3.event.preventDefault();\n }\n this.interaction.dragging.dragged_x = coords[0] - this.interaction.dragging.start_x;\n this.interaction.dragging.dragged_y = coords[1] - this.interaction.dragging.start_y;\n this.panels[this.interaction.panel_id].render();\n this.interaction.linked_panel_ids.forEach(function (panel_id) {\n this.panels[panel_id].render();\n }.bind(this));\n }\n }.bind(this);\n this.svg.on('mouseup' + namespace, mouseup).on('touchend' + namespace, mouseup).on('mousemove' + namespace, mousemove).on('touchmove' + namespace, mousemove);\n // Add an extra namespaced mouseup handler to the containing body, if there is one\n // This helps to stop interaction events gracefully when dragging outside of the plot element\n if (!d3.select('body').empty()) {\n d3.select('body').on('mouseup' + namespace, mouseup).on('touchend' + namespace, mouseup);\n }\n this.on('match_requested', function (eventData) {\n // Layers can broadcast that a specific point has been selected, and the plot will tell every other layer\n // to look for that value. Whenever a point is de-selected, it clears the match.\n var data = eventData.data;\n var to_send = data.active ? data.value : null;\n this.applyState({ lz_match_value: to_send });\n }.bind(this));\n this.initialized = true;\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n var client_rect = this.svg.node().getBoundingClientRect();\n var width = client_rect.width ? client_rect.width : this.layout.width;\n var height = client_rect.height ? client_rect.height : this.layout.height;\n this.setDimensions(width, height);\n return this;\n };\n /**\n * Refresh (or fetch) a plot's data from sources, regardless of whether position or state has changed\n * @returns {Promise}\n */\n LocusZoom.Plot.prototype.refresh = function () {\n return this.applyState();\n };\n /**\n * A user-defined callback function that can receive (and potentially act on) new plot data.\n * @callback externalDataCallback\n * @param {Object} new_data The body resulting from a data request. This represents the same information that would be passed to\n * a data layer making an equivalent request.\n */\n /**\n * A user-defined callback function that can respond to errors received during a previous operation\n * @callback externalErrorCallback\n * @param err A representation of the error that occurred\n */\n /**\n * Allow newly fetched data to be made available outside the LocusZoom plot. For example, a callback could be\n * registered to draw an HTML table of top GWAS hits, and update that table whenever the plot region changes.\n *\n * This is a convenience method for external hooks. It registers an event listener and returns parsed data,\n * using the same fields syntax and underlying methods as data layers.\n *\n * @param {String[]} fields An array of field names and transforms, in the same syntax used by a data layer.\n * Different data sources should be prefixed by the source name.\n * @param {externalDataCallback} success_callback Used defined function that is automatically called any time that\n * new data is received by the plot.\n * @param {Object} [opts] Options\n * @param {externalErrorCallback} [opts.onerror] User defined function that is automatically called if a problem\n * occurs during the data request or subsequent callback operations\n * @param {boolean} [opts.discrete=false] Normally the callback will subscribe to the combined body from the chain,\n * which may not be in a format that matches what the external callback wants to do. If discrete=true, returns the\n * uncombined record info\n * @return {function} The newly created event listener, to allow for later cleanup/removal\n */\n LocusZoom.Plot.prototype.subscribeToData = function (fields, success_callback, opts) {\n opts = opts || {};\n // Register an event listener that is notified whenever new data has been rendered\n var error_callback = opts.onerror || function (err) {\n console.log('An error occurred while acting on an external callback', err);\n };\n var self = this;\n var listener = function () {\n try {\n self.lzd.getData(self.state, fields).then(function (new_data) {\n success_callback(opts.discrete ? new_data.discrete : new_data.body);\n }).catch(error_callback);\n } catch (error) {\n // In certain cases, errors are thrown before a promise can be generated, and LZ error display seems to rely on these errors bubbling up\n error_callback(error);\n }\n };\n this.on('data_rendered', listener);\n return listener;\n };\n /**\n * Update state values and trigger a pull for fresh data on all data sources for all data layers\n * @param state_changes\n * @returns {Promise} A promise that resolves when all data fetch and update operations are complete\n */\n LocusZoom.Plot.prototype.applyState = function (state_changes) {\n state_changes = state_changes || {};\n if (typeof state_changes != 'object') {\n throw new Error('LocusZoom.applyState only accepts an object; ' + typeof state_changes + ' given');\n }\n // First make a copy of the current (old) state to work with\n var new_state = JSON.parse(JSON.stringify(this.state));\n // Apply changes by top-level property to the new state\n for (var property in state_changes) {\n new_state[property] = state_changes[property];\n }\n // Validate the new state (may do nothing, may do a lot, depends on how the user has things set up)\n new_state = LocusZoom.validateState(new_state, this.layout);\n // Apply new state to the actual state\n for (property in new_state) {\n this.state[property] = new_state[property];\n }\n // Generate requests for all panels given new state\n this.emit('data_requested');\n this.remap_promises = [];\n this.loading_data = true;\n for (var id in this.panels) {\n this.remap_promises.push(this.panels[id].reMap());\n }\n return Promise.all(this.remap_promises).catch(function (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n this.loading_data = false;\n }.bind(this)).then(function () {\n // Update dashboard / components\n this.dashboard.update();\n // Apply panel-level state values\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n var panel = this.panels[panel_id];\n panel.dashboard.update();\n // Apply data-layer-level state values\n panel.data_layer_ids_by_z_index.forEach(function (data_layer_id) {\n var data_layer = this.data_layers[data_layer_id];\n var state_id = panel_id + '.' + data_layer_id;\n for (var property in this.state[state_id]) {\n if (!this.state[state_id].hasOwnProperty(property)) {\n continue;\n }\n if (Array.isArray(this.state[state_id][property])) {\n this.state[state_id][property].forEach(function (element_id) {\n try {\n this.setElementStatus(property, this.getElementById(element_id), true);\n } catch (e) {\n console.warn('Unable to apply state: ' + state_id + ', ' + property);\n console.error(e);\n }\n }.bind(data_layer));\n }\n }\n }.bind(panel));\n }.bind(this));\n // Emit events\n this.emit('layout_changed');\n this.emit('data_rendered');\n this.emit('state_changed', state_changes);\n this.loading_data = false;\n }.bind(this));\n };\n /**\n * Register interactions along the specified axis, provided that the target panel allows interaction.\n *\n * @param {LocusZoom.Panel} panel\n * @param {('x_tick'|'y1_tick'|'y2_tick')} method The direction (axis) along which dragging is being performed.\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.startDrag = function (panel, method) {\n panel = panel || null;\n method = method || null;\n var axis = null;\n switch (method) {\n case 'background':\n case 'x_tick':\n axis = 'x';\n break;\n case 'y1_tick':\n axis = 'y1';\n break;\n case 'y2_tick':\n axis = 'y2';\n break;\n }\n if (!(panel instanceof LocusZoom.Panel) || !axis || !this.canInteract()) {\n return this.stopDrag();\n }\n var coords = d3.mouse(this.svg.node());\n this.interaction = {\n panel_id: panel.id,\n linked_panel_ids: panel.getLinkedPanelIds(axis),\n dragging: {\n method: method,\n start_x: coords[0],\n start_y: coords[1],\n dragged_x: 0,\n dragged_y: 0,\n axis: axis\n }\n };\n this.svg.style('cursor', 'all-scroll');\n return this;\n };\n /**\n * Process drag interactions across the target panel and synchronize plot state across other panels in sync;\n * clear the event when complete\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.stopDrag = function () {\n if (!this.interaction.dragging) {\n return this;\n }\n if (typeof this.panels[this.interaction.panel_id] != 'object') {\n this.interaction = {};\n return this;\n }\n var panel = this.panels[this.interaction.panel_id];\n // Helper function to find the appropriate axis layouts on child data layers\n // Once found, apply the extent as floor/ceiling and remove all other directives\n // This forces all associated axes to conform to the extent generated by a drag action\n var overrideAxisLayout = function (axis, axis_number, extent) {\n panel.data_layer_ids_by_z_index.forEach(function (id) {\n if (panel.data_layers[id].layout[axis + '_axis'].axis === axis_number) {\n panel.data_layers[id].layout[axis + '_axis'].floor = extent[0];\n panel.data_layers[id].layout[axis + '_axis'].ceiling = extent[1];\n delete panel.data_layers[id].layout[axis + '_axis'].lower_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].upper_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].min_extent;\n delete panel.data_layers[id].layout[axis + '_axis'].ticks;\n }\n });\n };\n switch (this.interaction.dragging.method) {\n case 'background':\n case 'x_tick':\n if (this.interaction.dragging.dragged_x !== 0) {\n overrideAxisLayout('x', 1, panel.x_extent);\n this.applyState({\n start: panel.x_extent[0],\n end: panel.x_extent[1]\n });\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n if (this.interaction.dragging.dragged_y !== 0) {\n // TODO: Hardcoded assumption of only two possible axes with single-digit #s (switch/case)\n var y_axis_number = parseInt(this.interaction.dragging.method[1]);\n overrideAxisLayout('y', y_axis_number, panel['y' + y_axis_number + '_extent']);\n }\n break;\n }\n this.interaction = {};\n this.svg.style('cursor', null);\n return this;\n };\n /* global LocusZoom */\n 'use strict';\n /**\n * A panel is an abstract class representing a subdivision of the LocusZoom stage\n * to display a distinct data representation as a collection of data layers.\n * @class\n * @param {Object} layout\n * @param {LocusZoom.Plot|null} parent\n*/\n LocusZoom.Panel = function (layout, parent) {\n if (typeof layout !== 'object') {\n throw new Error('Unable to create panel, invalid layout');\n }\n /** @member {LocusZoom.Plot|null} */\n this.parent = parent || null;\n /** @member {LocusZoom.Plot|null} */\n this.parent_plot = parent;\n // Ensure a valid ID is present. If there is no valid ID then generate one\n if (typeof layout.id !== 'string' || !layout.id.length) {\n if (!this.parent) {\n layout.id = 'p' + Math.floor(Math.random() * Math.pow(10, 8));\n } else {\n var id = null;\n var generateID = function () {\n id = 'p' + Math.floor(Math.random() * Math.pow(10, 8));\n if (id == null || typeof this.parent.panels[id] != 'undefined') {\n id = generateID();\n }\n }.bind(this);\n layout.id = id;\n }\n } else if (this.parent) {\n if (typeof this.parent.panels[layout.id] !== 'undefined') {\n throw new Error('Cannot create panel with id [' + layout.id + ']; panel with that id already exists');\n }\n }\n /** @member {String} */\n this.id = layout.id;\n /** @member {Boolean} */\n this.initialized = false;\n /**\n * The index of this panel in the parent plot's `layout.panels`\n * @member {number}\n * */\n this.layout_idx = null;\n /** @member {Object} */\n this.svg = {};\n /**\n * A JSON-serializable object used to describe the composition of the Panel\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.Panel.DefaultLayout);\n // Define state parameters specific to this panel\n if (this.parent) {\n /** @member {Object} */\n this.state = this.parent.state;\n /** @member {String} */\n this.state_id = this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n } else {\n this.state = null;\n this.state_id = null;\n }\n /** @member {Object} */\n this.data_layers = {};\n /** @member {String[]} */\n this.data_layer_ids_by_z_index = [];\n /** @protected */\n this.applyDataLayerZIndexesToDataLayerLayouts = function () {\n this.data_layer_ids_by_z_index.forEach(function (dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n }.bind(this);\n /**\n * Track data requests in progress\n * @member {Promise[]}\n * @protected\n */\n this.data_promises = [];\n /** @member {d3.scale} */\n this.x_scale = null;\n /** @member {d3.scale} */\n this.y1_scale = null;\n /** @member {d3.scale} */\n this.y2_scale = null;\n /** @member {d3.extent} */\n this.x_extent = null;\n /** @member {d3.extent} */\n this.y1_extent = null;\n /** @member {d3.extent} */\n this.y2_extent = null;\n /** @member {Number[]} */\n this.x_ticks = [];\n /** @member {Number[]} */\n this.y1_ticks = [];\n /** @member {Number[]} */\n this.y2_ticks = [];\n /**\n * A timeout ID as returned by setTimeout\n * @protected\n * @member {number}\n */\n this.zoom_timeout = null;\n /** @returns {string} */\n this.getBaseId = function () {\n return this.parent.id + '.' + this.id;\n };\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [],\n 'element_selection': [],\n 'match_requested': [] // A data layer is attempting to highlight matching points (internal use only)\n };\n /**\n * There are several events that a LocusZoom panel can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following panel-level events are currently supported:\n * - `layout_changed` - context: panel - Any aspect of the panel's layout (including dimensions or state) has changed.\n * - `data_requested` - context: panel - A request for new data from any data source used in the panel has been made.\n * - `data_rendered` - context: panel - Data from a request has been received and rendered in the panel.\n * - `element_clicked` - context: panel - A data element in any of the panel's data layers has been clicked.\n * - `element_selection` - context: panel - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `panel.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * panel itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of the event (as defined in `event_hooks`)\n * @param {function} hook\n * @returns {function} The registered event listener\n */\n this.on = function (event, hook) {\n // TODO: Dry plot and panel event code into a shared mixin\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Panel}\n */\n this.off = function (event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n *\n * There is a shorter overloaded form of this method: if the event does not have any data, the second\n * argument can be a boolean to control bubbling\n *\n * @param {string} event A known event name\n * @param {*} [eventData] Data or event description that will be passed to the event listener\n * @param {boolean} [bubble=false] Whether to bubble the event to the parent\n * @returns {LocusZoom.Panel}\n */\n this.emit = function (event, eventData, bubble) {\n bubble = bubble || false;\n // TODO: DRY this with the parent plot implementation. Ensure interfaces remain compatible.\n // TODO: Improve documentation for overloaded method signature (JSDoc may have trouble here)\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n if (typeof eventData === 'boolean' && arguments.length === 2) {\n // Overloaded method signature: emit(event, bubble)\n bubble = eventData;\n eventData = null;\n }\n var sourceID = this.getBaseId();\n var self = this;\n var eventContext = {\n sourceID: sourceID,\n data: eventData || null\n };\n this.event_hooks[event].forEach(function (hookToRun) {\n // By default, any handlers fired here will see the panel as the value of `this`. If a bound function is\n // registered as a handler, the previously bound `this` will override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n if (bubble && this.parent) {\n this.parent.emit(event, eventContext);\n }\n return this;\n };\n /**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\n this.getPageOrigin = function () {\n var plot_origin = this.parent.getPageOrigin();\n return {\n x: plot_origin.x + this.layout.origin.x,\n y: plot_origin.y + this.layout.origin.y\n };\n };\n // Initialize the layout\n this.initializeLayout();\n return this;\n };\n /**\n * Default panel layout\n * @static\n * @type {Object}\n */\n LocusZoom.Panel.DefaultLayout = {\n title: {\n text: '',\n style: {},\n x: 10,\n y: 22\n },\n y_index: null,\n width: 0,\n height: 0,\n origin: {\n x: 0,\n y: null\n },\n min_width: 1,\n min_height: 1,\n proportional_width: null,\n proportional_height: null,\n proportional_origin: {\n x: 0,\n y: null\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n },\n background_click: 'clear_selections',\n dashboard: { components: [] },\n cliparea: {\n height: 0,\n width: 0,\n origin: {\n x: 0,\n y: 0\n }\n },\n axes: {\n // These are the only axes supported!!\n x: {},\n y1: {},\n y2: {}\n },\n legend: null,\n interaction: {\n drag_background_to_pan: false,\n drag_x_ticks_to_scale: false,\n drag_y1_ticks_to_scale: false,\n drag_y2_ticks_to_scale: false,\n scroll_to_zoom: false,\n x_linked: false,\n y1_linked: false,\n y2_linked: false\n },\n data_layers: []\n };\n /**\n * Prepare the panel for first use by performing parameter validation, creating axes, setting default dimensions,\n * and preparing / positioning data layers as appropriate.\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.initializeLayout = function () {\n // If the layout is missing BOTH width and proportional width then set the proportional width to 1.\n // This will default the panel to taking up the full width of the plot.\n if (this.layout.width === 0 && this.layout.proportional_width === null) {\n this.layout.proportional_width = 1;\n }\n // If the layout is missing BOTH height and proportional height then set the proportional height to\n // an equal share of the plot's current height.\n if (this.layout.height === 0 && this.layout.proportional_height === null) {\n var panel_count = Object.keys(this.parent.panels).length;\n if (panel_count > 0) {\n this.layout.proportional_height = 1 / panel_count;\n } else {\n this.layout.proportional_height = 1;\n }\n }\n // Set panel dimensions, origin, and margin\n this.setDimensions();\n this.setOrigin();\n this.setMargin();\n // Set ranges\n // TODO: Define stub values in constructor\n this.x_range = [\n 0,\n this.layout.cliparea.width\n ];\n this.y1_range = [\n this.layout.cliparea.height,\n 0\n ];\n this.y2_range = [\n this.layout.cliparea.height,\n 0\n ];\n // Initialize panel axes\n [\n 'x',\n 'y1',\n 'y2'\n ].forEach(function (axis) {\n if (!Object.keys(this.layout.axes[axis]).length || this.layout.axes[axis].render === false) {\n // The default layout sets the axis to an empty object, so set its render boolean here\n this.layout.axes[axis].render = false;\n } else {\n this.layout.axes[axis].render = true;\n this.layout.axes[axis].label = this.layout.axes[axis].label || null;\n this.layout.axes[axis].label_function = this.layout.axes[axis].label_function || null;\n }\n }.bind(this));\n // Add data layers (which define x and y extents)\n this.layout.data_layers.forEach(function (data_layer_layout) {\n this.addDataLayer(data_layer_layout);\n }.bind(this));\n return this;\n };\n /**\n * Set the dimensions for the panel. If passed with no arguments will calculate optimal size based on layout\n * directives and the available area within the plot. If passed discrete width (number) and height (number) will\n * attempt to resize the panel to them, but may be limited by minimum dimensions defined on the plot or panel.\n *\n * @public\n * @param {number} [width]\n * @param {number} [height]\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.setDimensions = function (width, height) {\n if (typeof width != 'undefined' && typeof height != 'undefined') {\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n }\n } else {\n if (this.layout.proportional_width !== null) {\n this.layout.width = Math.max(this.layout.proportional_width * this.parent.layout.width, this.layout.min_width);\n }\n if (this.layout.proportional_height !== null) {\n this.layout.height = Math.max(this.layout.proportional_height * this.parent.layout.height, this.layout.min_height);\n }\n }\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n if (this.svg.clipRect) {\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n if (this.initialized) {\n this.render();\n this.curtain.update();\n this.loader.update();\n this.dashboard.update();\n if (this.legend) {\n this.legend.position();\n }\n }\n return this;\n };\n /**\n * Set panel origin on the plot, and re-render as appropriate\n *\n * @public\n * @param {number} x\n * @param {number} y\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.setOrigin = function (x, y) {\n if (!isNaN(x) && x >= 0) {\n this.layout.origin.x = Math.max(Math.round(+x), 0);\n }\n if (!isNaN(y) && y >= 0) {\n this.layout.origin.y = Math.max(Math.round(+y), 0);\n }\n if (this.initialized) {\n this.render();\n }\n return this;\n };\n /**\n * Set margins around this panel\n * @public\n * @param {number} top\n * @param {number} right\n * @param {number} bottom\n * @param {number} left\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.setMargin = function (top, right, bottom, left) {\n var extra;\n if (!isNaN(top) && top >= 0) {\n this.layout.margin.top = Math.max(Math.round(+top), 0);\n }\n if (!isNaN(right) && right >= 0) {\n this.layout.margin.right = Math.max(Math.round(+right), 0);\n }\n if (!isNaN(bottom) && bottom >= 0) {\n this.layout.margin.bottom = Math.max(Math.round(+bottom), 0);\n }\n if (!isNaN(left) && left >= 0) {\n this.layout.margin.left = Math.max(Math.round(+left), 0);\n }\n if (this.layout.margin.top + this.layout.margin.bottom > this.layout.height) {\n extra = Math.floor((this.layout.margin.top + this.layout.margin.bottom - this.layout.height) / 2);\n this.layout.margin.top -= extra;\n this.layout.margin.bottom -= extra;\n }\n if (this.layout.margin.left + this.layout.margin.right > this.layout.width) {\n extra = Math.floor((this.layout.margin.left + this.layout.margin.right - this.layout.width) / 2);\n this.layout.margin.left -= extra;\n this.layout.margin.right -= extra;\n }\n [\n 'top',\n 'right',\n 'bottom',\n 'left'\n ].forEach(function (m) {\n this.layout.margin[m] = Math.max(this.layout.margin[m], 0);\n }.bind(this));\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n this.layout.cliparea.origin.x = this.layout.margin.left;\n this.layout.cliparea.origin.y = this.layout.margin.top;\n if (this.initialized) {\n this.render();\n }\n return this;\n };\n /**\n * Set the title for the panel. If passed an object, will merge the object with the existing layout configuration, so\n * that all or only some of the title layout object's parameters can be customized. If passed null, false, or an empty\n * string, the title DOM element will be set to display: none.\n *\n * @param {string|object|null} title The title text, or an object with additional configuration\n * @param {string} title.text Text to display. Since titles are rendered as SVG text, HTML and newlines will not be rendered.\n * @param {number} title.x X-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n * @param {number} title.y Y-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n NOTE: SVG y values go from the top down, so the SVG origin of (0,0) is in the top left corner.\n * @param {object} title.style CSS styles object to be applied to the title's DOM element.\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.setTitle = function (title) {\n if (typeof this.layout.title == 'string') {\n var text = this.layout.title;\n this.layout.title = {\n text: text,\n x: 0,\n y: 0,\n style: {}\n };\n }\n if (typeof title == 'string') {\n this.layout.title.text = title;\n } else if (typeof title == 'object' && title !== null) {\n this.layout.title = LocusZoom.Layouts.merge(title, this.layout.title);\n }\n if (this.layout.title.text.length) {\n this.title.attr('display', null).attr('x', parseFloat(this.layout.title.x)).attr('y', parseFloat(this.layout.title.y)).style(this.layout.title.style).text(this.layout.title.text);\n } else {\n this.title.attr('display', 'none');\n }\n return this;\n };\n /**\n * Prepare the first rendering of the panel. This includes drawing the individual data layers, but also creates shared\n * elements such as axes, title, and loader/curtain.\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.initialize = function () {\n // Append a container group element to house the main panel group element and the clip path\n // Position with initial layout parameters\n this.svg.container = this.parent.svg.append('g').attr('id', this.getBaseId() + '.panel_container').attr('transform', 'translate(' + (this.layout.origin.x || 0) + ',' + (this.layout.origin.y || 0) + ')');\n // Append clip path to the parent svg element, size with initial layout parameters\n var clipPath = this.svg.container.append('clipPath').attr('id', this.getBaseId() + '.clip');\n this.svg.clipRect = clipPath.append('rect').attr('width', this.layout.width).attr('height', this.layout.height);\n // Append svg group for rendering all panel child elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g').attr('id', this.getBaseId() + '.panel').attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n // Add curtain and loader prototypes to the panel\n /** @member {Object} */\n this.curtain = LocusZoom.generateCurtain.call(this);\n /** @member {Object} */\n this.loader = LocusZoom.generateLoader.call(this);\n /**\n * Create the dashboard object and hang components on it as defined by panel layout\n * @member {LocusZoom.Dashboard}\n */\n this.dashboard = new LocusZoom.Dashboard(this);\n // Inner border\n this.inner_border = this.svg.group.append('rect').attr('class', 'lz-panel-background').on('click', function () {\n if (this.layout.background_click === 'clear_selections') {\n this.clearSelections();\n }\n }.bind(this));\n // Add the title\n /** @member {Element} */\n this.title = this.svg.group.append('text').attr('class', 'lz-panel-title');\n if (typeof this.layout.title != 'undefined') {\n this.setTitle();\n }\n // Initialize Axes\n this.svg.x_axis = this.svg.group.append('g').attr('id', this.getBaseId() + '.x_axis').attr('class', 'lz-x lz-axis');\n if (this.layout.axes.x.render) {\n this.svg.x_axis_label = this.svg.x_axis.append('text').attr('class', 'lz-x lz-axis lz-label').attr('text-anchor', 'middle');\n }\n this.svg.y1_axis = this.svg.group.append('g').attr('id', this.getBaseId() + '.y1_axis').attr('class', 'lz-y lz-y1 lz-axis');\n if (this.layout.axes.y1.render) {\n this.svg.y1_axis_label = this.svg.y1_axis.append('text').attr('class', 'lz-y1 lz-axis lz-label').attr('text-anchor', 'middle');\n }\n this.svg.y2_axis = this.svg.group.append('g').attr('id', this.getBaseId() + '.y2_axis').attr('class', 'lz-y lz-y2 lz-axis');\n if (this.layout.axes.y2.render) {\n this.svg.y2_axis_label = this.svg.y2_axis.append('text').attr('class', 'lz-y2 lz-axis lz-label').attr('text-anchor', 'middle');\n }\n // Initialize child Data Layers\n this.data_layer_ids_by_z_index.forEach(function (id) {\n this.data_layers[id].initialize();\n }.bind(this));\n /**\n * Legend object, as defined by panel layout and child data layer layouts\n * @member {LocusZoom.Legend}\n * */\n this.legend = null;\n if (this.layout.legend) {\n this.legend = new LocusZoom.Legend(this);\n }\n // Establish panel background drag interaction mousedown event handler (on the panel background)\n if (this.layout.interaction.drag_background_to_pan) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var mousedown = function () {\n this.parent.startDrag(this, 'background');\n }.bind(this);\n this.svg.container.select('.lz-panel-background').on('mousedown' + namespace + '.background', mousedown).on('touchstart' + namespace + '.background', mousedown);\n }\n return this;\n };\n /**\n * Refresh the sort order of all data layers (called by data layer moveUp and moveDown methods)\n */\n LocusZoom.Panel.prototype.resortDataLayers = function () {\n var sort = [];\n this.data_layer_ids_by_z_index.forEach(function (id) {\n sort.push(this.data_layers[id].layout.z_index);\n }.bind(this));\n this.svg.group.selectAll('g.lz-data_layer-container').data(sort).sort(d3.ascending);\n this.applyDataLayerZIndexesToDataLayerLayouts();\n };\n /**\n * Get an array of panel IDs that are axis-linked to this panel\n * @param {('x'|'y1'|'y2')} axis\n * @returns {Array}\n */\n LocusZoom.Panel.prototype.getLinkedPanelIds = function (axis) {\n axis = axis || null;\n var linked_panel_ids = [];\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(axis) === -1) {\n return linked_panel_ids;\n }\n if (!this.layout.interaction[axis + '_linked']) {\n return linked_panel_ids;\n }\n this.parent.panel_ids_by_y_index.forEach(function (panel_id) {\n if (panel_id !== this.id && this.parent.panels[panel_id].layout.interaction[axis + '_linked']) {\n linked_panel_ids.push(panel_id);\n }\n }.bind(this));\n return linked_panel_ids;\n };\n /**\n * Move a panel up relative to others by y-index\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.moveUp = function () {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index - 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index - 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index - 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n };\n /**\n * Move a panel down (y-axis) relative to others in the plot\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.moveDown = function () {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index + 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index + 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index + 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n };\n /**\n * Create a new data layer from a provided layout object. Should have the keys specified in `DefaultLayout`\n * Will automatically add at the top (depth/z-index) of the panel unless explicitly directed differently\n * in the layout provided.\n * @param {object} layout\n * @returns {*}\n */\n LocusZoom.Panel.prototype.addDataLayer = function (layout) {\n // Sanity checks\n if (typeof layout !== 'object' || typeof layout.id !== 'string' || !layout.id.length) {\n throw new Error('Invalid data layer layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n if (typeof this.data_layers[layout.id] !== 'undefined') {\n throw new Error('Cannot create data_layer with id [' + layout.id + ']; data layer with that id already exists in the panel');\n }\n if (typeof layout.type !== 'string') {\n throw new Error('Invalid data layer type in layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n // If the layout defines a y axis make sure the axis number is set and is 1 or 2 (default to 1)\n if (typeof layout.y_axis == 'object' && (typeof layout.y_axis.axis == 'undefined' || [\n 1,\n 2\n ].indexOf(layout.y_axis.axis) === -1)) {\n layout.y_axis.axis = 1;\n }\n // Create the Data Layer\n var data_layer = LocusZoom.DataLayers.get(layout.type, layout, this);\n // Store the Data Layer on the Panel\n this.data_layers[data_layer.id] = data_layer;\n // If a discrete z_index was set in the layout then adjust other data layer z_index values to accommodate this one\n if (data_layer.layout.z_index !== null && !isNaN(data_layer.layout.z_index) && this.data_layer_ids_by_z_index.length > 0) {\n // Negative z_index values should count backwards from the end, so convert negatives to appropriate values here\n if (data_layer.layout.z_index < 0) {\n data_layer.layout.z_index = Math.max(this.data_layer_ids_by_z_index.length + data_layer.layout.z_index, 0);\n }\n this.data_layer_ids_by_z_index.splice(data_layer.layout.z_index, 0, data_layer.id);\n this.data_layer_ids_by_z_index.forEach(function (dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n } else {\n var length = this.data_layer_ids_by_z_index.push(data_layer.id);\n this.data_layers[data_layer.id].layout.z_index = length - 1;\n }\n // Determine if this data layer was already in the layout.data_layers array.\n // If it wasn't, add it. Either way store the layout.data_layers array index on the data_layer.\n var layout_idx = null;\n this.layout.data_layers.forEach(function (data_layer_layout, idx) {\n if (data_layer_layout.id === data_layer.id) {\n layout_idx = idx;\n }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.data_layers.push(this.data_layers[data_layer.id].layout) - 1;\n }\n this.data_layers[data_layer.id].layout_idx = layout_idx;\n return this.data_layers[data_layer.id];\n };\n /**\n * Remove a data layer by id\n * @param {string} id\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.removeDataLayer = function (id) {\n if (!this.data_layers[id]) {\n throw new Error('Unable to remove data layer, ID not found: ' + id);\n }\n // Destroy all tooltips for the data layer\n this.data_layers[id].destroyAllTooltips();\n // Remove the svg container for the data layer if it exists\n if (this.data_layers[id].svg.container) {\n this.data_layers[id].svg.container.remove();\n }\n // Delete the data layer and its presence in the panel layout and state\n this.layout.data_layers.splice(this.data_layers[id].layout_idx, 1);\n delete this.state[this.data_layers[id].state_id];\n delete this.data_layers[id];\n // Remove the data_layer id from the z_index array\n this.data_layer_ids_by_z_index.splice(this.data_layer_ids_by_z_index.indexOf(id), 1);\n // Update layout_idx and layout.z_index values for all remaining data_layers\n this.applyDataLayerZIndexesToDataLayerLayouts();\n this.layout.data_layers.forEach(function (data_layer_layout, idx) {\n this.data_layers[data_layer_layout.id].layout_idx = idx;\n }.bind(this));\n return this;\n };\n /**\n * Clear all selections on all data layers\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.clearSelections = function () {\n this.data_layer_ids_by_z_index.forEach(function (id) {\n this.data_layers[id].setAllElementStatus('selected', false);\n }.bind(this));\n return this;\n };\n /**\n * When the parent plot changes state, adjust the panel accordingly. For example, this may include fetching new data\n * from the API as the viewing region changes\n * @returns {Promise}\n */\n LocusZoom.Panel.prototype.reMap = function () {\n this.emit('data_requested');\n this.data_promises = [];\n // Remove any previous error messages before attempting to load new data\n this.curtain.hide();\n // Trigger reMap on each Data Layer\n for (var id in this.data_layers) {\n try {\n this.data_promises.push(this.data_layers[id].reMap());\n } catch (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }\n }\n // When all finished trigger a render\n return Promise.all(this.data_promises).then(function () {\n this.initialized = true;\n this.render();\n this.emit('layout_changed', true);\n this.emit('data_rendered');\n }.bind(this)).catch(function (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }.bind(this));\n };\n /**\n * Iterate over data layers to generate panel axis extents\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.generateExtents = function () {\n // Reset extents\n [\n 'x',\n 'y1',\n 'y2'\n ].forEach(function (axis) {\n this[axis + '_extent'] = null;\n }.bind(this));\n // Loop through the data layers\n for (var id in this.data_layers) {\n var data_layer = this.data_layers[id];\n // If defined and not decoupled, merge the x extent of the data layer with the panel's x extent\n if (data_layer.layout.x_axis && !data_layer.layout.x_axis.decoupled) {\n this.x_extent = d3.extent((this.x_extent || []).concat(data_layer.getAxisExtent('x')));\n }\n // If defined and not decoupled, merge the y extent of the data layer with the panel's appropriate y extent\n if (data_layer.layout.y_axis && !data_layer.layout.y_axis.decoupled) {\n var y_axis = 'y' + data_layer.layout.y_axis.axis;\n this[y_axis + '_extent'] = d3.extent((this[y_axis + '_extent'] || []).concat(data_layer.getAxisExtent('y')));\n }\n }\n // Override x_extent from state if explicitly defined to do so\n if (this.layout.axes.x && this.layout.axes.x.extent === 'state') {\n this.x_extent = [\n this.state.start,\n this.state.end\n ];\n }\n return this;\n };\n /**\n * Generate an array of ticks for an axis. These ticks are generated in one of three ways (highest wins):\n * 1. An array of specific tick marks\n * 2. Query each data layer for what ticks are appropriate, and allow a panel-level tick configuration parameter\n * object to override the layer's default presentation settings\n * 3. Generate generic tick marks based on the extent of the data\n * @param {('x'|'y1'|'y2')} axis The string identifier of the axis\n * @returns {Number[]|Object[]} TODO: number format?\n * An array of numbers: interpreted as an array of axis value offsets for positioning.\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\n LocusZoom.Panel.prototype.generateTicks = function (axis) {\n // Parse an explicit 'ticks' attribute in the axis layout\n if (this.layout.axes[axis].ticks) {\n var layout = this.layout.axes[axis];\n var baseTickConfig = layout.ticks;\n if (Array.isArray(baseTickConfig)) {\n // Array of specific ticks hard-coded into a panel will override any ticks that an individual layer might specify\n return baseTickConfig;\n }\n if (typeof baseTickConfig === 'object') {\n // If the layout specifies base configuration for ticks- but without specific positions- then ask each\n // data layer to report the tick marks that it thinks it needs\n // TODO: Few layers currently need to specify custom ticks (which is ok!). But if it becomes common, consider adding mechanisms to deduplicate ticks across layers\n var self = this;\n // Pass any layer-specific customizations for how ticks are calculated. (styles are overridden separately)\n var config = { position: baseTickConfig.position };\n var combinedTicks = this.data_layer_ids_by_z_index.reduce(function (acc, data_layer_id) {\n var nextLayer = self.data_layers[data_layer_id];\n return acc.concat(nextLayer.getTicks(axis, config));\n }, []);\n return combinedTicks.map(function (item) {\n // The layer makes suggestions, but tick configuration params specified on the panel take precedence\n var itemConfig = {};\n itemConfig = LocusZoom.Layouts.merge(itemConfig, baseTickConfig);\n return LocusZoom.Layouts.merge(itemConfig, item);\n });\n }\n }\n // If no other configuration is provided, attempt to generate ticks from the extent\n if (this[axis + '_extent']) {\n return LocusZoom.prettyTicks(this[axis + '_extent'], 'both');\n }\n return [];\n };\n /**\n * Update rendering of this panel whenever an event triggers a redraw. Assumes that the panel has already been\n * prepared the first time via `initialize`\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.render = function () {\n // Position the panel container\n this.svg.container.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n // Set size on the clip rect\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n // Set and position the inner border, style if necessary\n this.inner_border.attr('x', this.layout.margin.left).attr('y', this.layout.margin.top).attr('width', this.layout.width - (this.layout.margin.left + this.layout.margin.right)).attr('height', this.layout.height - (this.layout.margin.top + this.layout.margin.bottom));\n if (this.layout.inner_border) {\n this.inner_border.style({\n 'stroke-width': 1,\n 'stroke': this.layout.inner_border\n });\n }\n // Set/update panel title if necessary\n this.setTitle();\n // Regenerate all extents\n this.generateExtents();\n // Helper function to constrain any procedurally generated vectors (e.g. ranges, extents)\n // Constraints applied here keep vectors from going to infinity or beyond a definable power of ten\n var constrain = function (value, limit_exponent) {\n var neg_min = Math.pow(-10, limit_exponent);\n var neg_max = Math.pow(-10, -limit_exponent);\n var pos_min = Math.pow(10, -limit_exponent);\n var pos_max = Math.pow(10, limit_exponent);\n if (value === Infinity) {\n value = pos_max;\n }\n if (value === -Infinity) {\n value = neg_min;\n }\n if (value === 0) {\n value = pos_min;\n }\n if (value > 0) {\n value = Math.max(Math.min(value, pos_max), pos_min);\n }\n if (value < 0) {\n value = Math.max(Math.min(value, neg_max), neg_min);\n }\n return value;\n };\n // Define default and shifted ranges for all axes\n var ranges = {};\n if (this.x_extent) {\n var base_x_range = {\n start: 0,\n end: this.layout.cliparea.width\n };\n if (this.layout.axes.x.range) {\n base_x_range.start = this.layout.axes.x.range.start || base_x_range.start;\n base_x_range.end = this.layout.axes.x.range.end || base_x_range.end;\n }\n ranges.x = [\n base_x_range.start,\n base_x_range.end\n ];\n ranges.x_shifted = [\n base_x_range.start,\n base_x_range.end\n ];\n }\n if (this.y1_extent) {\n var base_y1_range = {\n start: this.layout.cliparea.height,\n end: 0\n };\n if (this.layout.axes.y1.range) {\n base_y1_range.start = this.layout.axes.y1.range.start || base_y1_range.start;\n base_y1_range.end = this.layout.axes.y1.range.end || base_y1_range.end;\n }\n ranges.y1 = [\n base_y1_range.start,\n base_y1_range.end\n ];\n ranges.y1_shifted = [\n base_y1_range.start,\n base_y1_range.end\n ];\n }\n if (this.y2_extent) {\n var base_y2_range = {\n start: this.layout.cliparea.height,\n end: 0\n };\n if (this.layout.axes.y2.range) {\n base_y2_range.start = this.layout.axes.y2.range.start || base_y2_range.start;\n base_y2_range.end = this.layout.axes.y2.range.end || base_y2_range.end;\n }\n ranges.y2 = [\n base_y2_range.start,\n base_y2_range.end\n ];\n ranges.y2_shifted = [\n base_y2_range.start,\n base_y2_range.end\n ];\n }\n // Shift ranges based on any drag or zoom interactions currently underway\n if (this.parent.interaction.panel_id && (this.parent.interaction.panel_id === this.id || this.parent.interaction.linked_panel_ids.indexOf(this.id) !== -1)) {\n var anchor, scalar = null;\n if (this.parent.interaction.zooming && typeof this.x_scale == 'function') {\n var current_extent_size = Math.abs(this.x_extent[1] - this.x_extent[0]);\n var current_scaled_extent_size = Math.round(this.x_scale.invert(ranges.x_shifted[1])) - Math.round(this.x_scale.invert(ranges.x_shifted[0]));\n var zoom_factor = this.parent.interaction.zooming.scale;\n var potential_extent_size = Math.floor(current_scaled_extent_size * (1 / zoom_factor));\n if (zoom_factor < 1 && !isNaN(this.parent.layout.max_region_scale)) {\n zoom_factor = 1 / (Math.min(potential_extent_size, this.parent.layout.max_region_scale) / current_scaled_extent_size);\n } else if (zoom_factor > 1 && !isNaN(this.parent.layout.min_region_scale)) {\n zoom_factor = 1 / (Math.max(potential_extent_size, this.parent.layout.min_region_scale) / current_scaled_extent_size);\n }\n var new_extent_size = Math.floor(current_extent_size * zoom_factor);\n anchor = this.parent.interaction.zooming.center - this.layout.margin.left - this.layout.origin.x;\n var offset_ratio = anchor / this.layout.cliparea.width;\n var new_x_extent_start = Math.max(Math.floor(this.x_scale.invert(ranges.x_shifted[0]) - (new_extent_size - current_scaled_extent_size) * offset_ratio), 1);\n ranges.x_shifted = [\n this.x_scale(new_x_extent_start),\n this.x_scale(new_x_extent_start + new_extent_size)\n ];\n } else if (this.parent.interaction.dragging) {\n switch (this.parent.interaction.dragging.method) {\n case 'background':\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n break;\n case 'x_tick':\n if (d3.event && d3.event.shiftKey) {\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n } else {\n anchor = this.parent.interaction.dragging.start_x - this.layout.margin.left - this.layout.origin.x;\n scalar = constrain(anchor / (anchor + this.parent.interaction.dragging.dragged_x), 3);\n ranges.x_shifted[0] = 0;\n ranges.x_shifted[1] = Math.max(this.layout.cliparea.width * (1 / scalar), 1);\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n var y_shifted = 'y' + this.parent.interaction.dragging.method[1] + '_shifted';\n if (d3.event && d3.event.shiftKey) {\n ranges[y_shifted][0] = this.layout.cliparea.height + this.parent.interaction.dragging.dragged_y;\n ranges[y_shifted][1] = +this.parent.interaction.dragging.dragged_y;\n } else {\n anchor = this.layout.cliparea.height - (this.parent.interaction.dragging.start_y - this.layout.margin.top - this.layout.origin.y);\n scalar = constrain(anchor / (anchor - this.parent.interaction.dragging.dragged_y), 3);\n ranges[y_shifted][0] = this.layout.cliparea.height;\n ranges[y_shifted][1] = this.layout.cliparea.height - this.layout.cliparea.height * (1 / scalar);\n }\n }\n }\n }\n // Generate scales and ticks for all axes, then render them\n [\n 'x',\n 'y1',\n 'y2'\n ].forEach(function (axis) {\n if (!this[axis + '_extent']) {\n return;\n }\n // Base Scale\n this[axis + '_scale'] = d3.scale.linear().domain(this[axis + '_extent']).range(ranges[axis + '_shifted']);\n // Shift the extent\n this[axis + '_extent'] = [\n this[axis + '_scale'].invert(ranges[axis][0]),\n this[axis + '_scale'].invert(ranges[axis][1])\n ];\n // Finalize Scale\n this[axis + '_scale'] = d3.scale.linear().domain(this[axis + '_extent']).range(ranges[axis]);\n // Render axis (and generate ticks as needed)\n this.renderAxis(axis);\n }.bind(this));\n // Establish mousewheel zoom event handers on the panel (namespacing not passed through by d3, so not used here)\n if (this.layout.interaction.scroll_to_zoom) {\n var zoom_handler = function () {\n // Look for a shift key press while scrolling to execute.\n // If not present, gracefully raise a notification and allow conventional scrolling\n if (!d3.event.shiftKey) {\n if (this.parent.canInteract(this.id)) {\n this.loader.show('Press [SHIFT] while scrolling to zoom').hide(1000);\n }\n return;\n }\n d3.event.preventDefault();\n if (!this.parent.canInteract(this.id)) {\n return;\n }\n var coords = d3.mouse(this.svg.container.node());\n var delta = Math.max(-1, Math.min(1, d3.event.wheelDelta || -d3.event.detail || -d3.event.deltaY));\n if (delta === 0) {\n return;\n }\n this.parent.interaction = {\n panel_id: this.id,\n linked_panel_ids: this.getLinkedPanelIds('x'),\n zooming: {\n scale: delta < 1 ? 0.9 : 1.1,\n center: coords[0]\n }\n };\n this.render();\n this.parent.interaction.linked_panel_ids.forEach(function (panel_id) {\n this.parent.panels[panel_id].render();\n }.bind(this));\n if (this.zoom_timeout !== null) {\n clearTimeout(this.zoom_timeout);\n }\n this.zoom_timeout = setTimeout(function () {\n this.parent.interaction = {};\n this.parent.applyState({\n start: this.x_extent[0],\n end: this.x_extent[1]\n });\n }.bind(this), 500);\n }.bind(this);\n this.zoom_listener = d3.behavior.zoom();\n this.svg.container.call(this.zoom_listener).on('wheel.zoom', zoom_handler).on('mousewheel.zoom', zoom_handler).on('DOMMouseScroll.zoom', zoom_handler);\n }\n // Render data layers in order by z-index\n this.data_layer_ids_by_z_index.forEach(function (data_layer_id) {\n this.data_layers[data_layer_id].draw().render();\n }.bind(this));\n return this;\n };\n /**\n * Render ticks for a particular axis\n * @param {('x'|'y1'|'y2')} axis The identifier of the axes\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.renderAxis = function (axis) {\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(axis) === -1) {\n throw new Error('Unable to render axis; invalid axis identifier: ' + axis);\n }\n var canRender = this.layout.axes[axis].render && typeof this[axis + '_scale'] == 'function' && !isNaN(this[axis + '_scale'](0));\n // If the axis has already been rendered then check if we can/can't render it\n // Make sure the axis element is shown/hidden to suit\n if (this[axis + '_axis']) {\n this.svg.container.select('g.lz-axis.lz-' + axis).style('display', canRender ? null : 'none');\n }\n if (!canRender) {\n return this;\n }\n // Axis-specific values to plug in where needed\n var axis_params = {\n x: {\n position: 'translate(' + this.layout.margin.left + ',' + (this.layout.height - this.layout.margin.bottom) + ')',\n orientation: 'bottom',\n label_x: this.layout.cliparea.width / 2,\n label_y: this.layout.axes[axis].label_offset || 0,\n label_rotate: null\n },\n y1: {\n position: 'translate(' + this.layout.margin.left + ',' + this.layout.margin.top + ')',\n orientation: 'left',\n label_x: -1 * (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n },\n y2: {\n position: 'translate(' + (this.layout.width - this.layout.margin.right) + ',' + this.layout.margin.top + ')',\n orientation: 'right',\n label_x: this.layout.axes[axis].label_offset || 0,\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n }\n };\n // Generate Ticks\n this[axis + '_ticks'] = this.generateTicks(axis);\n // Determine if the ticks are all numbers (d3-automated tick rendering) or not (manual tick rendering)\n var ticksAreAllNumbers = function (ticks) {\n for (var i = 0; i < ticks.length; i++) {\n if (isNaN(ticks[i])) {\n return false;\n }\n }\n return true;\n }(this[axis + '_ticks']);\n // Initialize the axis; set scale and orientation\n this[axis + '_axis'] = d3.svg.axis().scale(this[axis + '_scale']).orient(axis_params[axis].orientation).tickPadding(3);\n // Set tick values and format\n if (ticksAreAllNumbers) {\n this[axis + '_axis'].tickValues(this[axis + '_ticks']);\n if (this.layout.axes[axis].tick_format === 'region') {\n this[axis + '_axis'].tickFormat(function (d) {\n return LocusZoom.positionIntToString(d, 6);\n });\n }\n } else {\n var ticks = this[axis + '_ticks'].map(function (t) {\n return t[axis.substr(0, 1)];\n });\n this[axis + '_axis'].tickValues(ticks).tickFormat(function (t, i) {\n return this[axis + '_ticks'][i].text;\n }.bind(this));\n }\n // Position the axis in the SVG and apply the axis construct\n this.svg[axis + '_axis'].attr('transform', axis_params[axis].position).call(this[axis + '_axis']);\n // If necessary manually apply styles and transforms to ticks as specified by the layout\n if (!ticksAreAllNumbers) {\n var tick_selector = d3.selectAll('g#' + this.getBaseId().replace('.', '\\\\.') + '\\\\.' + axis + '_axis g.tick');\n var panel = this;\n tick_selector.each(function (d, i) {\n var selector = d3.select(this).select('text');\n if (panel[axis + '_ticks'][i].style) {\n selector.style(panel[axis + '_ticks'][i].style);\n }\n if (panel[axis + '_ticks'][i].transform) {\n selector.attr('transform', panel[axis + '_ticks'][i].transform);\n }\n });\n }\n // Render the axis label if necessary\n var label = this.layout.axes[axis].label || null;\n if (label !== null) {\n this.svg[axis + '_axis_label'].attr('x', axis_params[axis].label_x).attr('y', axis_params[axis].label_y).text(LocusZoom.parseFields(this.state, label));\n if (axis_params[axis].label_rotate !== null) {\n this.svg[axis + '_axis_label'].attr('transform', 'rotate(' + axis_params[axis].label_rotate + ' ' + axis_params[axis].label_x + ',' + axis_params[axis].label_y + ')');\n }\n }\n // Attach interactive handlers to ticks as needed\n [\n 'x',\n 'y1',\n 'y2'\n ].forEach(function (axis) {\n if (this.layout.interaction['drag_' + axis + '_ticks_to_scale']) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var tick_mouseover = function () {\n if (typeof d3.select(this).node().focus == 'function') {\n d3.select(this).node().focus();\n }\n var cursor = axis === 'x' ? 'ew-resize' : 'ns-resize';\n if (d3.event && d3.event.shiftKey) {\n cursor = 'move';\n }\n d3.select(this).style({\n 'font-weight': 'bold',\n 'cursor': cursor\n }).on('keydown' + namespace, tick_mouseover).on('keyup' + namespace, tick_mouseover);\n };\n this.svg.container.selectAll('.lz-axis.lz-' + axis + ' .tick text').attr('tabindex', 0) // necessary to make the tick focusable so keypress events can be captured\n.on('mouseover' + namespace, tick_mouseover).on('mouseout' + namespace, function () {\n d3.select(this).style({ 'font-weight': 'normal' });\n d3.select(this).on('keydown' + namespace, null).on('keyup' + namespace, null);\n }).on('mousedown' + namespace, function () {\n this.parent.startDrag(this, axis + '_tick');\n }.bind(this));\n }\n }.bind(this));\n return this;\n };\n /**\n * Force the height of this panel to the largest absolute height of the data in\n * all child data layers (if not null for any child data layers)\n * @param {number|null} [target_height] A target height, which will be used in situations when the expected height can be\n * pre-calculated (eg when the layers are transitioning)\n */\n LocusZoom.Panel.prototype.scaleHeightToData = function (target_height) {\n target_height = +target_height || null;\n if (target_height === null) {\n this.data_layer_ids_by_z_index.forEach(function (id) {\n var dh = this.data_layers[id].getAbsoluteDataHeight();\n if (+dh) {\n if (target_height === null) {\n target_height = +dh;\n } else {\n target_height = Math.max(target_height, +dh);\n }\n }\n }.bind(this));\n }\n if (+target_height) {\n target_height += +this.layout.margin.top + +this.layout.margin.bottom;\n this.setDimensions(this.layout.width, target_height);\n this.parent.setDimensions();\n this.parent.panel_ids_by_y_index.forEach(function (id) {\n this.parent.panels[id].layout.proportional_height = null;\n }.bind(this));\n this.parent.positionPanels();\n }\n };\n /**\n * Methods to set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n */\n LocusZoom.Panel.prototype.setElementStatusByFilters = function (status, toggle, filters, exclusive) {\n this.data_layer_ids_by_z_index.forEach(function (id) {\n this.data_layers[id].setElementStatusByFilters(status, toggle, filters, exclusive);\n }.bind(this));\n };\n /**\n * Set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n */\n LocusZoom.Panel.prototype.setAllElementStatus = function (status, toggle) {\n this.data_layer_ids_by_z_index.forEach(function (id) {\n this.data_layers[id].setAllElementStatus(status, toggle);\n }.bind(this));\n };\n // TODO: Capture documentation for dynamically generated methods\n LocusZoom.DataLayer.Statuses.verbs.forEach(function (verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.Panel.prototype[verb + 'ElementsByFilters'] = function (filters, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.Panel.prototype[antiverb + 'ElementsByFilters'] = function (filters, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.Panel.prototype[verb + 'AllElements'] = function () {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.Panel.prototype[antiverb + 'AllElements'] = function () {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n });\n /**\n * Add a \"basic\" loader to a panel\n * This method is just a shortcut for adding the most commonly used type of loading indicator, which appears when\n * data is requested, animates (e.g. shows an infinitely cycling progress bar as opposed to one that loads from\n * 0-100% based on actual load progress), and disappears when new data is loaded and rendered.\n *\n *\n * @param {Boolean} show_immediately\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.addBasicLoader = function (show_immediately) {\n if (typeof show_immediately != 'undefined') {\n show_immediately = true;\n }\n if (show_immediately) {\n this.loader.show('Loading...').animate();\n }\n this.on('data_requested', function () {\n this.loader.show('Loading...').animate();\n }.bind(this));\n this.on('data_rendered', function () {\n this.loader.hide();\n }.bind(this));\n return this;\n };\n } catch (plugin_loading_error) {\n console.error('LocusZoom Plugin error: ', plugin_loading_error);\n }\n return LocusZoom;\n })); //# sourceMappingURL=locuszoom.app.js.map\n } catch (plugin_loading_error) {\n console.error('LocusZoom Plugin error: ', plugin_loading_error);\n }\n return LocusZoom;\n}));","/* global LocusZoom */\n'use strict';\n\n/**\n * A Dashboard is an HTML element used for presenting arbitrary user interface components. Dashboards are anchored\n * to either the entire Plot or to individual Panels.\n *\n * Each dashboard is an HTML-based (read: not SVG) collection of components used to display information or provide\n * user interface. Dashboards can exist on entire plots, where their visibility is permanent and vertically adjacent\n * to the plot, or on individual panels, where their visibility is tied to a behavior (e.g. a mouseover) and is as\n * an overlay.\n * @class\n */\nLocusZoom.Dashboard = function(parent) {\n // parent must be a locuszoom plot or panel\n if (!(parent instanceof LocusZoom.Plot) && !(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create dashboard, parent must be a locuszoom plot or panel');\n }\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.dashboard';\n /** @member {('plot'|'panel')} */\n this.type = (this.parent instanceof LocusZoom.Plot) ? 'plot' : 'panel';\n /** @member {LocusZoom.Plot} */\n this.parent_plot = this.type === 'plot' ? this.parent : this.parent.parent;\n\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {LocusZoom.Dashboard.Component[]} */\n this.components = [];\n /**\n * The timer identifier as returned by setTimeout\n * @member {Number}\n */\n this.hide_timeout = null;\n /**\n * Whether to hide the dashboard. Can be overridden by a child component. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n\n // TODO: Return value from constructor function?\n return this.initialize();\n};\n\n/**\n * Prepare the dashboard for first use: generate all component instances for this dashboard, based on the provided\n * layout of the parent. Connects event listeners and shows/hides as appropriate.\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.initialize = function() {\n // Parse layout to generate component instances\n if (Array.isArray(this.parent.layout.dashboard.components)) {\n this.parent.layout.dashboard.components.forEach(function(layout) {\n try {\n var component = LocusZoom.Dashboard.Components.get(layout.type, layout, this);\n this.components.push(component);\n } catch (e) {\n console.warn(e);\n }\n }.bind(this));\n }\n\n // Add mouseover event handlers to show/hide panel dashboard\n if (this.type === 'panel') {\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseover.' + this.id, function() {\n clearTimeout(this.hide_timeout);\n if (!this.selector || this.selector.style('visibility') === 'hidden') { this.show(); }\n }.bind(this));\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseout.' + this.id, function() {\n clearTimeout(this.hide_timeout);\n this.hide_timeout = setTimeout(function() { this.hide(); }.bind(this), 300);\n }.bind(this));\n }\n\n return this;\n\n};\n\n/**\n * Whether to persist the dashboard. Returns true if at least one component should persist, or if the panel is engaged\n * in an active drag event.\n * @returns {boolean}\n */\nLocusZoom.Dashboard.prototype.shouldPersist = function() {\n if (this.persist) { return true; }\n var persist = false;\n // Persist if at least one component should also persist\n this.components.forEach(function(component) {\n persist = persist || component.shouldPersist();\n });\n // Persist if in a parent drag event\n persist = persist || (this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.dragging);\n return !!persist;\n};\n\n/**\n * Make the dashboard appear. If it doesn't exist yet create it, including creating/positioning all components within,\n * and make sure it is set to be visible.\n */\nLocusZoom.Dashboard.prototype.show = function() {\n if (!this.selector) {\n switch (this.type) {\n case 'plot':\n this.selector = d3.select(this.parent.svg.node().parentNode)\n .insert('div',':first-child');\n break;\n case 'panel':\n this.selector = d3.select(this.parent.parent.svg.node().parentNode)\n .insert('div', '.lz-data_layer-tooltip, .lz-dashboard-menu, .lz-curtain').classed('lz-panel-dashboard', true);\n break;\n }\n this.selector.classed('lz-dashboard', true).classed('lz-' + this.type + '-dashboard', true).attr('id', this.id);\n }\n this.components.forEach(function(component) { component.show(); });\n this.selector.style({ visibility: 'visible' });\n return this.update();\n};\n\n/**\n * Update the dashboard and rerender all child components. This can be called whenever plot state changes.\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.update = function() {\n if (!this.selector) { return this; }\n this.components.forEach(function(component) { component.update(); });\n return this.position();\n};\n\n/**\n * Position the dashboard (and child components) within the panel\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.position = function() {\n if (!this.selector) { return this; }\n // Position the dashboard itself (panel only)\n if (this.type === 'panel') {\n var page_origin = this.parent.getPageOrigin();\n var top = (page_origin.y + 3.5).toString() + 'px';\n var left = page_origin.x.toString() + 'px';\n var width = (this.parent.layout.width - 4).toString() + 'px';\n this.selector.style({ position: 'absolute', top: top, left: left, width: width });\n }\n // Recursively position components\n this.components.forEach(function(component) { component.position(); });\n return this;\n};\n\n/**\n * Hide the dashboard (make invisible but do not destroy). Will do nothing if `shouldPersist` returns true.\n *\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.hide = function() {\n if (!this.selector || this.shouldPersist()) { return this; }\n this.components.forEach(function(component) { component.hide(); });\n this.selector.style({ visibility: 'hidden' });\n return this;\n};\n\n/**\n * Completely remove dashboard and all child components. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.destroy = function(force) {\n if (typeof force == 'undefined') { force = false; }\n if (!this.selector) { return this; }\n if (this.shouldPersist() && !force) { return this; }\n this.components.forEach(function(component) { component.destroy(true); });\n this.components = [];\n this.selector.remove();\n this.selector = null;\n return this;\n};\n\n/**\n *\n * A dashboard component is an empty div rendered on a dashboard that can display custom\n * html of user interface elements. LocusZoom.Dashboard.Components is a singleton used to\n * define and manage an extendable collection of dashboard components.\n * (e.g. by LocusZoom.Dashboard.Components.add())\n * @class\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @param {('left'|'right')} [layout.position='left'] Whether to float the component left or right.\n * @param {('start'|'middle'|'end')} [layout.group_position] Buttons can optionally be gathered into a visually\n * distinctive group whose elements are closer together. If a button is identified as the start or end of a group,\n * it will be drawn with rounded corners and an extra margin of spacing from any button not part of the group.\n * For example, the region_nav_plot dashboard is a defined as a group.\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple'} [layout.color='gray'] Color scheme for the\n * component. Applies to buttons and menus.\n * @param {LocusZoom.Dashboard} parent The dashboard that contains this component\n*/\nLocusZoom.Dashboard.Component = function(layout, parent) {\n /** @member {Object} */\n this.layout = layout || {};\n if (!this.layout.color) { this.layout.color = 'gray'; }\n\n /** @member {LocusZoom.Dashboard|*} */\n this.parent = parent || null;\n /**\n * Some dashboards are attached to a panel, rather than directly to a plot\n * @member {LocusZoom.Panel|null}\n */\n this.parent_panel = null;\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n /**\n * This is a reference to either the panel or the plot, depending on what the dashboard is\n * tied to. Useful when absolutely positioning dashboard components relative to their SVG anchor.\n * @member {LocusZoom.Plot|LocusZoom.Panel}\n */\n this.parent_svg = null;\n if (this.parent instanceof LocusZoom.Dashboard) {\n // TODO: when is the immediate parent *not* a dashboard?\n if (this.parent.type === 'panel') {\n this.parent_panel = this.parent.parent;\n this.parent_plot = this.parent.parent.parent;\n this.parent_svg = this.parent_panel;\n } else {\n this.parent_plot = this.parent.parent;\n this.parent_svg = this.parent_plot;\n }\n }\n /** @member {d3.selection} */\n this.selector = null;\n /**\n * If this is an interactive component, it will contain a button or menu instance that handles the interactivity.\n * There is a 1-to-1 relationship of dashboard component to button\n * @member {null|LocusZoom.Dashboard.Component.Button}\n */\n this.button = null;\n /**\n * If any single component is marked persistent, it will bubble up to prevent automatic hide behavior on a\n * component's parent dashboard. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n if (!this.layout.position) { this.layout.position = 'left'; }\n\n // TODO: Return value in constructor\n return this;\n};\n/**\n * Perform all rendering of component, including toggling visibility to true. Will initialize and create SVG element\n * if necessary, as well as updating with new data and performing layout actions.\n */\nLocusZoom.Dashboard.Component.prototype.show = function() {\n if (!this.parent || !this.parent.selector) { return; }\n if (!this.selector) {\n var group_position = (['start','middle','end'].indexOf(this.layout.group_position) !== -1 ? ' lz-dashboard-group-' + this.layout.group_position : '');\n this.selector = this.parent.selector.append('div')\n .attr('class', 'lz-dashboard-' + this.layout.position + group_position);\n if (this.layout.style) { this.selector.style(this.layout.style); }\n if (typeof this.initialize == 'function') { this.initialize(); }\n }\n if (this.button && this.button.status === 'highlighted') { this.button.menu.show(); }\n this.selector.style({ visibility: 'visible' });\n this.update();\n return this.position();\n};\n/**\n * Update the dashboard component with any new data or plot state as appropriate. This method performs all\n * necessary rendering steps.\n */\nLocusZoom.Dashboard.Component.prototype.update = function() { /* stub */ };\n/**\n * Place the component correctly in the plot\n * @returns {LocusZoom.Dashboard.Component}\n */\nLocusZoom.Dashboard.Component.prototype.position = function() {\n if (this.button) { this.button.menu.position(); }\n return this;\n};\n/**\n * Determine whether the component should persist (will bubble up to parent dashboard)\n * @returns {boolean}\n */\nLocusZoom.Dashboard.Component.prototype.shouldPersist = function() {\n if (this.persist) { return true; }\n if (this.button && this.button.persist) { return true; }\n return false;\n};\n/**\n * Toggle visibility to hidden, unless marked as persistent\n * @returns {LocusZoom.Dashboard.Component}\n */\nLocusZoom.Dashboard.Component.prototype.hide = function() {\n if (!this.selector || this.shouldPersist()) { return this; }\n if (this.button) { this.button.menu.hide(); }\n this.selector.style({ visibility: 'hidden' });\n return this;\n};\n/**\n * Completely remove component and button. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.Component.prototype.destroy = function(force) {\n if (typeof force == 'undefined') { force = false; }\n if (!this.selector) { return this; }\n if (this.shouldPersist() && !force) { return this; }\n if (this.button && this.button.menu) { this.button.menu.destroy(); }\n this.selector.remove();\n this.selector = null;\n this.button = null;\n return this;\n};\n\n/**\n * Singleton registry of all known components\n * @class\n * @static\n */\nLocusZoom.Dashboard.Components = (function() {\n /** @lends LocusZoom.Dashboard.Components */\n var obj = {};\n var components = {};\n\n /**\n * Create a new component instance by name\n * @param {String} name The string identifier of the desired component\n * @param {Object} layout The layout to use to create the component\n * @param {LocusZoom.Dashboard} parent The containing dashboard to use when creating the component\n * @returns {LocusZoom.Dashboard.Component}\n */\n obj.get = function(name, layout, parent) {\n if (!name) {\n return null;\n } else if (components[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for dashboard component [' + name + ']');\n } else {\n return new components[name](layout, parent);\n }\n } else {\n throw new Error('dashboard component [' + name + '] not found');\n }\n };\n /**\n * Add a new component constructor to the registry and ensure that it extends the correct parent class\n * @protected\n * @param name\n * @param component\n */\n obj.set = function(name, component) {\n if (component) {\n if (typeof component != 'function') {\n throw new Error('unable to set dashboard component [' + name + '], argument provided is not a function');\n } else {\n components[name] = component;\n components[name].prototype = new LocusZoom.Dashboard.Component();\n }\n } else {\n delete components[name];\n }\n };\n\n /**\n * Register a new component constructor by name\n * @param {String} name\n * @param {function} component The component constructor\n */\n obj.add = function(name, component) {\n if (components[name]) {\n throw new Error('dashboard component already exists with name: ' + name);\n } else {\n obj.set(name, component);\n }\n };\n\n /**\n * List the names of all registered components\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(components);\n };\n\n return obj;\n})();\n\n/**\n * Plots and panels may have a \"dashboard\" element suited for showing HTML components that may be interactive.\n * When components need to incorporate a generic button, or additionally a button that generates a menu, this\n * class provides much of the necessary framework.\n * @class\n * @param {LocusZoom.Dashboard.Component} parent\n */\nLocusZoom.Dashboard.Component.Button = function(parent) {\n\n if (!(parent instanceof LocusZoom.Dashboard.Component)) {\n throw new Error('Unable to create dashboard component button, invalid parent');\n }\n /** @member {LocusZoom.Dashboard.Component} */\n this.parent = parent;\n /** @member {LocusZoom.Dashboard.Panel} */\n this.parent_panel = this.parent.parent_panel;\n /** @member {LocusZoom.Dashboard.Plot} */\n this.parent_plot = this.parent.parent_plot;\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent_svg = this.parent.parent_svg;\n\n /** @member {LocusZoom.Dashboard|null|*} */\n this.parent_dashboard = this.parent.parent;\n /** @member {d3.selection} */\n this.selector = null;\n\n /**\n * Tag to use for the button (default: a)\n * @member {String}\n */\n this.tag = 'a';\n\n /**\n * TODO This method does not appear to be used anywhere\n * @param {String} tag\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTag = function(tag) {\n if (typeof tag != 'undefined') { this.tag = tag.toString(); }\n return this;\n };\n\n /**\n * HTML for the button to show.\n * @protected\n * @member {String}\n */\n this.html = '';\n /**\n * Specify the HTML content of this button.\n * WARNING: The string provided will be inserted into the document as raw markup; XSS mitigation is the\n * responsibility of each button implementation.\n * @param {String} html\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setHtml = function(html) {\n if (typeof html != 'undefined') { this.html = html.toString(); }\n return this;\n };\n /**\n * @deprecated since 0.5.6; use setHtml instead\n */\n this.setText = this.setHtml;\n\n /**\n * Mouseover title text for the button to show\n * @protected\n * @member {String}\n */\n this.title = '';\n /**\n * Set the mouseover title text for the button (if any)\n * @param {String} title Simple text to display\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTitle = function(title) {\n if (typeof title != 'undefined') { this.title = title.toString(); }\n return this;\n };\n\n /**\n * Color of the button\n * @member {String}\n */\n this.color = 'gray';\n\n /**\n * Set the color associated with this button\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple')} color Any selection not in the preset list\n * will be replaced with gray.\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setColor = function(color) {\n if (typeof color != 'undefined') {\n if (['gray', 'red', 'orange', 'yellow', 'green', 'blue', 'purple'].indexOf(color) !== -1) { this.color = color; }\n else { this.color = 'gray'; }\n }\n return this;\n };\n\n /**\n * Hash of arbitrary button styles to apply as {name: value} entries\n * @protected\n * @member {Object}\n */\n this.style = {};\n /**\n * Set a collection of custom styles to be used by the button\n * @param {Object} style Hash of {name:value} entries\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setStyle = function(style) {\n if (typeof style != 'undefined') { this.style = style; }\n return this;\n };\n\n //\n /**\n * Method to generate a CSS class string\n * @returns {string}\n */\n this.getClass = function() {\n var group_position = (['start','middle','end'].indexOf(this.parent.layout.group_position) !== -1 ? ' lz-dashboard-button-group-' + this.parent.layout.group_position : '');\n return 'lz-dashboard-button lz-dashboard-button-' + this.color + (this.status ? '-' + this.status : '') + group_position;\n };\n\n // Permanence\n /**\n * Track internal state on whether to keep showing the button/ menu contents at the moment\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n /**\n * Configuration when defining a button: track whether this component should be allowed to keep open\n * menu/button contents in response to certain events\n * @protected\n * @member {Boolean}\n */\n this.permanent = false;\n /**\n * Allow code to change whether the button is allowed to be `permanent`\n * @param {boolean} bool\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setPermanent = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n this.permanent = bool;\n if (this.permanent) { this.persist = true; }\n return this;\n };\n /**\n * Determine whether the button/menu contents should persist in response to a specific event\n * @returns {Boolean}\n */\n this.shouldPersist = function() {\n return this.permanent || this.persist;\n };\n\n /**\n * Button status (highlighted / disabled/ etc)\n * @protected\n * @member {String}\n */\n this.status = '';\n /**\n * Change button state\n * @param {('highlighted'|'disabled'|'')} status\n */\n this.setStatus = function(status) {\n if (typeof status != 'undefined' && ['', 'highlighted', 'disabled'].indexOf(status) !== -1) { this.status = status; }\n return this.update();\n };\n /**\n * Toggle whether the button is highlighted\n * @param {boolean} bool If provided, explicitly set highlighted state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.highlight = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n if (bool) { return this.setStatus('highlighted'); }\n else if (this.status === 'highlighted') { return this.setStatus(''); }\n return this;\n };\n /**\n * Toggle whether the button is disabled\n * @param {boolean} bool If provided, explicitly set disabled state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.disable = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n if (bool) { return this.setStatus('disabled'); }\n else if (this.status === 'disabled') { return this.setStatus(''); }\n return this;\n };\n\n // Mouse events\n /** @member {function} */\n this.onmouseover = function() {};\n this.setOnMouseover = function(onmouseover) {\n if (typeof onmouseover == 'function') { this.onmouseover = onmouseover; }\n else { this.onmouseover = function() {}; }\n return this;\n };\n /** @member {function} */\n this.onmouseout = function() {};\n this.setOnMouseout = function(onmouseout) {\n if (typeof onmouseout == 'function') { this.onmouseout = onmouseout; }\n else { this.onmouseout = function() {}; }\n return this;\n };\n /** @member {function} */\n this.onclick = function() {};\n this.setOnclick = function(onclick) {\n if (typeof onclick == 'function') { this.onclick = onclick; }\n else { this.onclick = function() {}; }\n return this;\n };\n\n // Primary behavior functions\n /**\n * Show the button, including creating DOM elements if necessary for first render\n */\n this.show = function() {\n if (!this.parent) { return; }\n if (!this.selector) {\n this.selector = this.parent.selector.append(this.tag).attr('class', this.getClass());\n }\n return this.update();\n };\n /**\n * Hook for any actions or state cleanup to be performed before rerendering\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.preUpdate = function() { return this; };\n /**\n * Update button state and contents, and fully rerender\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.update = function() {\n if (!this.selector) { return this; }\n this.preUpdate();\n this.selector\n .attr('class', this.getClass())\n .attr('title', this.title).style(this.style)\n .on('mouseover', (this.status === 'disabled') ? null : this.onmouseover)\n .on('mouseout', (this.status === 'disabled') ? null : this.onmouseout)\n .on('click', (this.status === 'disabled') ? null : this.onclick)\n .html(this.html);\n this.menu.update();\n this.postUpdate();\n return this;\n };\n /**\n * Hook for any behavior to be added/changed after the button has been re-rendered\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.postUpdate = function() { return this; };\n /**\n * Hide the button by removing it from the DOM (may be overridden by current persistence setting)\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.hide = function() {\n if (this.selector && !this.shouldPersist()) {\n this.selector.remove();\n this.selector = null;\n }\n return this;\n };\n\n /**\n * Button Menu Object\n * The menu is an HTML overlay that can appear below a button. It can contain arbitrary HTML and\n * has logic to be automatically positioned and sized to behave more or less like a dropdown menu.\n * @member {Object}\n */\n this.menu = {\n outer_selector: null,\n inner_selector: null,\n scroll_position: 0,\n hidden: true,\n /**\n * Show the button menu, including setting up any DOM elements needed for first rendering\n */\n show: function() {\n if (!this.menu.outer_selector) {\n this.menu.outer_selector = d3.select(this.parent_plot.svg.node().parentNode).append('div')\n .attr('class', 'lz-dashboard-menu lz-dashboard-menu-' + this.color)\n .attr('id', this.parent_svg.getBaseId() + '.dashboard.menu');\n this.menu.inner_selector = this.menu.outer_selector.append('div')\n .attr('class', 'lz-dashboard-menu-content');\n this.menu.inner_selector.on('scroll', function() {\n this.menu.scroll_position = this.menu.inner_selector.node().scrollTop;\n }.bind(this));\n }\n this.menu.outer_selector.style({ visibility: 'visible' });\n this.menu.hidden = false;\n return this.menu.update();\n }.bind(this),\n /**\n * Update the rendering of the menu\n */\n update: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.populate(); // This function is stubbed for all buttons by default and custom implemented in component definition\n if (this.menu.inner_selector) { this.menu.inner_selector.node().scrollTop = this.menu.scroll_position; }\n return this.menu.position();\n }.bind(this),\n position: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n // Unset any explicitly defined outer selector height so that menus dynamically shrink if content is removed\n this.menu.outer_selector.style({ height: null });\n var padding = 3;\n var scrollbar_padding = 20;\n var menu_height_padding = 14; // 14: 2x 6px padding, 2x 1px border\n var page_origin = this.parent_svg.getPageOrigin();\n var page_scroll_top = document.documentElement.scrollTop || document.body.scrollTop;\n var container_offset = this.parent_plot.getContainerOffset();\n var dashboard_client_rect = this.parent_dashboard.selector.node().getBoundingClientRect();\n var button_client_rect = this.selector.node().getBoundingClientRect();\n var menu_client_rect = this.menu.outer_selector.node().getBoundingClientRect();\n var total_content_height = this.menu.inner_selector.node().scrollHeight;\n var top = 0; var left = 0;\n if (this.parent_dashboard.type === 'panel') {\n top = (page_origin.y + dashboard_client_rect.height + (2 * padding));\n left = Math.max(page_origin.x + this.parent_svg.layout.width - menu_client_rect.width - padding, page_origin.x + padding);\n } else {\n top = button_client_rect.bottom + page_scroll_top + padding - container_offset.top;\n left = Math.max(button_client_rect.left + button_client_rect.width - menu_client_rect.width - container_offset.left, page_origin.x + padding);\n }\n var base_max_width = Math.max(this.parent_svg.layout.width - (2 * padding) - scrollbar_padding, scrollbar_padding);\n var container_max_width = base_max_width;\n var content_max_width = (base_max_width - (4 * padding));\n var base_max_height = Math.max(this.parent_svg.layout.height - (10 * padding) - menu_height_padding, menu_height_padding);\n var height = Math.min(total_content_height, base_max_height);\n var max_height = base_max_height;\n this.menu.outer_selector.style({\n 'top': top.toString() + 'px',\n 'left': left.toString() + 'px',\n 'max-width': container_max_width.toString() + 'px',\n 'max-height': max_height.toString() + 'px',\n 'height': height.toString() + 'px'\n });\n this.menu.inner_selector.style({ 'max-width': content_max_width.toString() + 'px' });\n this.menu.inner_selector.node().scrollTop = this.menu.scroll_position;\n return this.menu;\n }.bind(this),\n hide: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.outer_selector.style({ visibility: 'hidden' });\n this.menu.hidden = true;\n return this.menu;\n }.bind(this),\n destroy: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.inner_selector.remove();\n this.menu.outer_selector.remove();\n this.menu.inner_selector = null;\n this.menu.outer_selector = null;\n return this.menu;\n }.bind(this),\n /**\n * Internal method definition\n * By convention populate() does nothing and should be reimplemented with each dashboard button definition\n * Reimplement by way of Dashboard.Component.Button.menu.setPopulate to define the populate method and hook\n * up standard menu click-toggle behavior prototype.\n * @protected\n */\n populate: function() { /* stub */ }.bind(this),\n /**\n * Define how the menu is populated with items, and set up click and display properties as appropriate\n * @public\n */\n setPopulate: function(menu_populate_function) {\n if (typeof menu_populate_function == 'function') {\n this.menu.populate = menu_populate_function;\n this.setOnclick(function() {\n if (this.menu.hidden) {\n this.menu.show();\n this.highlight().update();\n this.persist = true;\n } else {\n this.menu.hide();\n this.highlight(false).update();\n if (!this.permanent) { this.persist = false; }\n }\n }.bind(this));\n } else {\n this.setOnclick();\n }\n return this;\n }.bind(this)\n };\n\n};\n\n/**\n * Renders arbitrary text with title formatting\n * @class LocusZoom.Dashboard.Components.title\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.title Text to render\n */\nLocusZoom.Dashboard.Components.add('title', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.show = function() {\n this.div_selector = this.parent.selector.append('div')\n .attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position);\n this.title_selector = this.div_selector.append('h3');\n return this.update();\n };\n this.update = function() {\n var title = layout.title.toString();\n if (this.layout.subtitle) { title += ' ' + this.layout.subtitle + ''; }\n this.title_selector.html(title);\n return this;\n };\n});\n\n/**\n * Renders text to display the current dimensions of the plot. Automatically updated as plot dimensions change\n * @class LocusZoom.Dashboard.Components.dimensions\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('dimensions', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n var display_width = this.parent_plot.layout.width.toString().indexOf('.') === -1 ? this.parent_plot.layout.width : this.parent_plot.layout.width.toFixed(2);\n var display_height = this.parent_plot.layout.height.toString().indexOf('.') === -1 ? this.parent_plot.layout.height : this.parent_plot.layout.height.toFixed(2);\n this.selector.html(display_width + 'px × ' + display_height + 'px');\n if (layout.class) { this.selector.attr('class', layout.class); }\n if (layout.style) { this.selector.style(layout.style); }\n return this;\n };\n});\n\n/**\n * Display the current scale of the genome region displayed in the plot, as defined by the difference between\n * `state.end` and `state.start`.\n * @class LocusZoom.Dashboard.Components.region_scale\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('region_scale', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (!isNaN(this.parent_plot.state.start) && !isNaN(this.parent_plot.state.end)\n && this.parent_plot.state.start !== null && this.parent_plot.state.end !== null) {\n this.selector.style('display', null);\n this.selector.html(LocusZoom.positionIntToString(this.parent_plot.state.end - this.parent_plot.state.start, null, true));\n } else {\n this.selector.style('display', 'none');\n }\n if (layout.class) { this.selector.attr('class', layout.class); }\n if (layout.style) { this.selector.style(layout.style); }\n return this;\n };\n});\n\n/**\n * Button to export current plot to an SVG image\n * @class LocusZoom.Dashboard.Components.download\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Download Image\"]\n * @param {string} [layout.button_title=\"Download image of the current plot as locuszoom.svg\"]\n */\nLocusZoom.Dashboard.Components.add('download', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html || 'Download Image')\n .setTitle(layout.button_title || 'Download image of the current plot as locuszoom.svg')\n .setOnMouseover(function() {\n this.button.selector\n .classed('lz-dashboard-button-gray-disabled', true)\n .html('Preparing Image');\n this.generateBase64SVG().then(function(url) {\n var old = this.button.selector.attr('href');\n if (old) { URL.revokeObjectURL(old); } // Clean up old url instance to prevent memory leaks\n this.button.selector\n .attr('href', url)\n .classed('lz-dashboard-button-gray-disabled', false)\n .classed('lz-dashboard-button-gray-highlighted', true)\n .html(layout.button_html || 'Download Image');\n }.bind(this));\n }.bind(this))\n .setOnMouseout(function() {\n this.button.selector.classed('lz-dashboard-button-gray-highlighted', false);\n }.bind(this));\n this.button.show();\n this.button.selector.attr('href-lang', 'image/svg+xml').attr('download', layout.filename || 'locuszoom.svg');\n return this;\n };\n this.css_string = '';\n for (var stylesheet in Object.keys(document.styleSheets)) {\n if ( document.styleSheets[stylesheet].href !== null\n && document.styleSheets[stylesheet].href.indexOf('locuszoom.css') !== -1) {\n // TODO: \"Download image\" button will render the image incorrectly if the stylesheet has been renamed or concatenated\n LocusZoom.createCORSPromise('GET', document.styleSheets[stylesheet].href)\n .then(function(response) {\n this.css_string = response.replace(/[\\r\\n]/g,' ').replace(/\\s+/g,' ');\n if (this.css_string.indexOf('/* ! LocusZoom HTML Styles */')) {\n this.css_string = this.css_string.substring(0, this.css_string.indexOf('/* ! LocusZoom HTML Styles */'));\n }\n }.bind(this));\n break;\n }\n }\n this.generateBase64SVG = function() {\n return new Promise(function (resolve, reject) {\n // Insert a hidden div, clone the node into that so we can modify it with d3\n var container = this.parent.selector.append('div').style('display', 'none')\n .html(this.parent_plot.svg.node().outerHTML);\n // Remove unnecessary elements\n container.selectAll('g.lz-curtain').remove();\n container.selectAll('g.lz-mouse_guide').remove();\n // Convert units on axis tick dy attributes from ems to pixels\n container.selectAll('g.tick text').each(function() {\n var dy = +(d3.select(this).attr('dy').substring(-2).slice(0,-2)) * 10;\n d3.select(this).attr('dy', dy);\n });\n // Pull the svg into a string and add the contents of the locuszoom stylesheet\n // Don't add this with d3 because it will escape the CDATA declaration incorrectly\n var initial_html = d3.select(container.select('svg').node().parentNode).html();\n var style_def = '';\n var insert_at = initial_html.indexOf('>') + 1;\n initial_html = initial_html.slice(0,insert_at) + style_def + initial_html.slice(insert_at);\n // Delete the container node\n container.remove();\n // Create an object URL based on the rendered markup\n var content = new Blob([initial_html], { type: 'image/svg+xml' });\n resolve(URL.createObjectURL(content));\n }.bind(this));\n };\n});\n\n/**\n * Button to remove panel from plot.\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.remove_panel\n * @augments LocusZoom.Dashboard.Component\n * @param {Boolean} [layout.suppress_confirm=false] If true, removes the panel without prompting user for confirmation\n */\nLocusZoom.Dashboard.Components.add('remove_panel', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('×')\n .setTitle('Remove panel')\n .setOnclick(function() {\n if (!layout.suppress_confirm && !confirm('Are you sure you want to remove this panel? This cannot be undone!')) {\n return false;\n }\n var panel = this.parent_panel;\n panel.dashboard.hide(true);\n d3.select(panel.parent.svg.node().parentNode).on('mouseover.' + panel.getBaseId() + '.dashboard', null);\n d3.select(panel.parent.svg.node().parentNode).on('mouseout.' + panel.getBaseId() + '.dashboard', null);\n return panel.parent.removePanel(panel.id);\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Button to move panel up relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_up\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('move_panel_up', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) {\n var is_at_top = (this.parent_panel.layout.y_index === 0);\n this.button.disable(is_at_top);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('▴')\n .setTitle('Move panel up')\n .setOnclick(function() {\n this.parent_panel.moveUp();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n});\n\n/**\n * Button to move panel down relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_down\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('move_panel_down', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) {\n var is_at_bottom = (this.parent_panel.layout.y_index === this.parent_plot.panel_ids_by_y_index.length - 1);\n this.button.disable(is_at_bottom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('▾')\n .setTitle('Move panel down')\n .setOnclick(function() {\n this.parent_panel.moveDown();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n});\n\n/**\n * Button to shift plot region forwards or back by a `step` increment provided in the layout\n * @class LocusZoom.Dashboard.Components.shift_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=50000] The stepsize to change the region by\n * @param {string} [layout.button_html]\n * @param {string} [layout.button_title]\n */\nLocusZoom.Dashboard.Components.add('shift_region', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function() {};\n console.warn('Unable to add shift_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) { layout.step = 50000; }\n if (typeof layout.button_html !== 'string') { layout.button_html = layout.step > 0 ? '>' : '<'; }\n if (typeof layout.button_title !== 'string') {\n layout.button_title = 'Shift region by ' + (layout.step > 0 ? '+' : '-') + LocusZoom.positionIntToString(Math.abs(layout.step),null,true);\n }\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start + layout.step, 1),\n end: this.parent_plot.state.end + layout.step\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Zoom in or out on the plot, centered on the middle of the plot region, by the specified amount\n * @class LocusZoom.Dashboard.Components.zoom_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=0.2] The amount to zoom in by (where 1 indicates 100%)\n */\nLocusZoom.Dashboard.Components.add('zoom_region', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function() {};\n console.warn('Unable to add zoom_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) { layout.step = 0.2; }\n if (typeof layout.button_html != 'string') { layout.button_html = layout.step > 0 ? 'z–' : 'z+'; }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Zoom region ' + (layout.step > 0 ? 'out' : 'in') + ' by ' + (Math.abs(layout.step) * 100).toFixed(1) + '%';\n }\n this.update = function() {\n if (this.button) {\n var can_zoom = true;\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n if (layout.step > 0 && !isNaN(this.parent_plot.layout.max_region_scale) && current_region_scale >= this.parent_plot.layout.max_region_scale) {\n can_zoom = false;\n }\n if (layout.step < 0 && !isNaN(this.parent_plot.layout.min_region_scale) && current_region_scale <= this.parent_plot.layout.min_region_scale) {\n can_zoom = false;\n }\n this.button.disable(!can_zoom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n var zoom_factor = 1 + layout.step;\n var new_region_scale = current_region_scale * zoom_factor;\n if (!isNaN(this.parent_plot.layout.max_region_scale)) {\n new_region_scale = Math.min(new_region_scale, this.parent_plot.layout.max_region_scale);\n }\n if (!isNaN(this.parent_plot.layout.min_region_scale)) {\n new_region_scale = Math.max(new_region_scale, this.parent_plot.layout.min_region_scale);\n }\n var delta = Math.floor((new_region_scale - current_region_scale) / 2);\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start - delta, 1),\n end: this.parent_plot.state.end + delta\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Renders button with arbitrary text that, when clicked, shows a dropdown containing arbitrary HTML\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @class LocusZoom.Dashboard.Components.menu\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n * @param {string} layout.menu_html The HTML content of the dropdown menu\n */\nLocusZoom.Dashboard.Components.add('menu', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title);\n this.button.menu.setPopulate(function() {\n this.button.menu.inner_selector.html(layout.menu_html);\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Special button/menu to allow model building by tracking individual covariants. Will track a list of covariate\n * objects and store them in the special `model.covariates` field of plot `state`.\n * @class LocusZoom.Dashboard.Components.covariates_model\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n */\nLocusZoom.Dashboard.Components.add('covariates_model', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n this.initialize = function() {\n // Initialize state.model.covariates\n this.parent_plot.state.model = this.parent_plot.state.model || {};\n this.parent_plot.state.model.covariates = this.parent_plot.state.model.covariates || [];\n // Create an object at the plot level for easy access to interface methods in custom client-side JS\n /**\n * When a covariates model dashboard element is present, create (one) object at the plot level that exposes\n * component data and state for custom interactions with other plot elements.\n * @class LocusZoom.Plot.CovariatesModel\n */\n this.parent_plot.CovariatesModel = {\n /** @member {LocusZoom.Dashboard.Component.Button} */\n button: this,\n /**\n * Add an element to the model and show a representation of it in the dashboard component menu. If the\n * element is already part of the model, do nothing (to avoid adding duplicates).\n * When plot state is changed, this will automatically trigger requests for new data accordingly.\n * @param {string|object} element_reference Can be any value that can be put through JSON.stringify()\n * to create a serialized representation of itself.\n */\n add: function(element_reference) {\n var element = JSON.parse(JSON.stringify(element_reference));\n if (typeof element_reference == 'object' && typeof element.html != 'string') {\n element.html = ( (typeof element_reference.toHTML == 'function') ? element_reference.toHTML() : element_reference.toString());\n }\n // Check if the element is already in the model covariates array and return if it is.\n for (var i = 0; i < this.state.model.covariates.length; i++) {\n if (JSON.stringify(this.state.model.covariates[i]) === JSON.stringify(element)) {\n return this;\n }\n }\n this.state.model.covariates.push(element);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Remove an element from `state.model.covariates` (and from the dashboard component menu's\n * representation of the state model). When plot state is changed, this will automatically trigger\n * requests for new data accordingly.\n * @param {number} idx Array index of the element, in the `state.model.covariates array`.\n */\n removeByIdx: function(idx) {\n if (typeof this.state.model.covariates[idx] == 'undefined') {\n throw new Error('Unable to remove model covariate, invalid index: ' + idx.toString());\n }\n this.state.model.covariates.splice(idx, 1);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Empty the `state.model.covariates` array (and dashboard component menu representation thereof) of all\n * elements. When plot state is changed, this will automatically trigger requests for new data accordingly\n */\n removeAll: function() {\n this.state.model.covariates = [];\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Manually trigger the update methods on the dashboard component's button and menu elements to force\n * display of most up-to-date content. Can be used to force the dashboard to reflect changes made, eg if\n * modifying `state.model.covariates` directly instead of via `plot.CovariatesModel`\n */\n updateComponent: function() {\n this.button.update();\n this.button.menu.update();\n }.bind(this)\n };\n }.bind(this);\n\n this.update = function() {\n\n if (this.button) { return this; }\n\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.button.menu.populate();\n }.bind(this));\n\n this.button.menu.setPopulate(function() {\n var selector = this.button.menu.inner_selector;\n selector.html('');\n // General model HTML representation\n if (typeof this.parent_plot.state.model.html != 'undefined') {\n selector.append('div').html(this.parent_plot.state.model.html);\n }\n // Model covariates table\n if (!this.parent_plot.state.model.covariates.length) {\n selector.append('i').html('no covariates in model');\n } else {\n selector.append('h5').html('Model Covariates (' + this.parent_plot.state.model.covariates.length + ')');\n var table = selector.append('table');\n this.parent_plot.state.model.covariates.forEach(function(covariate, idx) {\n var html = ( (typeof covariate == 'object' && typeof covariate.html == 'string') ? covariate.html : covariate.toString() );\n var row = table.append('tr');\n row.append('td').append('button')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color)\n .style({ 'margin-left': '0em' })\n .on('click', function() {\n this.parent_plot.CovariatesModel.removeByIdx(idx);\n }.bind(this))\n .html('×');\n row.append('td').html(html);\n }.bind(this));\n selector.append('button')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color)\n .style({ 'margin-left': '4px' }).html('× Remove All Covariates')\n .on('click', function() {\n this.parent_plot.CovariatesModel.removeAll();\n }.bind(this));\n }\n }.bind(this));\n\n this.button.preUpdate = function() {\n var html = 'Model';\n if (this.parent_plot.state.model.covariates.length) {\n var cov = this.parent_plot.state.model.covariates.length > 1 ? 'covariates' : 'covariate';\n html += ' (' + this.parent_plot.state.model.covariates.length + ' ' + cov + ')';\n }\n this.button.setHtml(html).disable(false);\n }.bind(this);\n\n this.button.show();\n\n return this;\n };\n});\n\n/**\n * Button to toggle split tracks\n * @class LocusZoom.Dashboard.Components.toggle_split_tracks\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('toggle_split_tracks', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (!layout.data_layer_id) { layout.data_layer_id = 'intervals'; }\n if (!this.parent_panel.data_layers[layout.data_layer_id]) {\n throw new Error('Dashboard toggle split tracks component missing valid data layer ID');\n }\n this.update = function() {\n var data_layer = this.parent_panel.data_layers[layout.data_layer_id];\n var html = data_layer.layout.split_tracks ? 'Merge Tracks' : 'Split Tracks';\n if (this.button) {\n this.button.setHtml(html);\n this.button.show();\n this.parent.position();\n return this;\n } else {\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(html)\n .setTitle('Toggle whether tracks are split apart or merged together')\n .setOnclick(function() {\n data_layer.toggleSplitTracks();\n if (this.scale_timeout) { clearTimeout(this.scale_timeout); }\n var timeout = data_layer.layout.transition ? +data_layer.layout.transition.duration || 0 : 0;\n this.scale_timeout = setTimeout(function() {\n this.parent_panel.scaleHeightToData();\n this.parent_plot.positionPanels();\n }.bind(this), timeout);\n this.update();\n }.bind(this));\n return this.update();\n }\n };\n});\n\n/**\n * Button to resize panel height to fit available data (eg when showing a list of tracks)\n * @class LocusZoom.Dashboard.Components.resize_to_data\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Resize to Data\"]\n * @param {string} [layout.button_title]\n */\nLocusZoom.Dashboard.Components.add('resize_to_data', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html || 'Resize to Data')\n .setTitle(layout.button_title || 'Automatically resize this panel to show all data available')\n .setOnclick(function() {\n this.parent_panel.scaleHeightToData();\n this.update();\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Button to toggle legend\n * @class LocusZoom.Dashboard.Components.toggle_legend\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('toggle_legend', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n var html = this.parent_panel.legend.layout.hidden ? 'Show Legend' : 'Hide Legend';\n if (this.button) {\n this.button.setHtml(html).show();\n this.parent.position();\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setTitle('Show or hide the legend for this panel')\n .setOnclick(function() {\n this.parent_panel.legend.layout.hidden = !this.parent_panel.legend.layout.hidden;\n this.parent_panel.legend.render();\n this.update();\n }.bind(this));\n return this.update();\n };\n});\n\n/**\n * Menu for manipulating multiple data layers in a single panel: show/hide, change order, etc.\n * @class LocusZoom.Dashboard.Components.data_layers\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('data_layers', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n this.update = function() {\n\n if (typeof layout.button_html != 'string') { layout.button_html = 'Data Layers'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Manipulate Data Layers (sort, dim, show/hide, etc.)'; }\n\n if (this.button) { return this; }\n\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.button.menu.populate();\n }.bind(this));\n\n this.button.menu.setPopulate(function() {\n this.button.menu.inner_selector.html('');\n var table = this.button.menu.inner_selector.append('table');\n this.parent_panel.data_layer_ids_by_z_index.slice().reverse().forEach(function(id, idx) {\n var data_layer = this.parent_panel.data_layers[id];\n var name = (typeof data_layer.layout.name != 'string') ? data_layer.id : data_layer.layout.name;\n var row = table.append('tr');\n // Layer name\n row.append('td').html(name);\n // Status toggle buttons\n layout.statuses.forEach(function(status_adj) {\n var status_idx = LocusZoom.DataLayer.Statuses.adjectives.indexOf(status_adj);\n var status_verb = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n var html, onclick, highlight;\n if (data_layer.global_statuses[status_adj]) {\n html = LocusZoom.DataLayer.Statuses.menu_antiverbs[status_idx];\n onclick = 'un' + status_verb + 'AllElements';\n highlight = '-highlighted';\n } else {\n html = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n onclick = status_verb + 'AllElements';\n highlight = '';\n }\n row.append('td').append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color + highlight)\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer[onclick](); this.button.menu.populate(); }.bind(this))\n .html(html);\n }.bind(this));\n // Sort layer buttons\n var at_top = (idx === 0);\n var at_bottom = (idx === (this.parent_panel.data_layer_ids_by_z_index.length - 1));\n var td = row.append('td');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-start lz-dashboard-button-' + this.layout.color + (at_bottom ? '-disabled' : ''))\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer.moveDown(); this.button.menu.populate(); }.bind(this))\n .html('▾').attr('title', 'Move layer down (further back)');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-middle lz-dashboard-button-' + this.layout.color + (at_top ? '-disabled' : ''))\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer.moveUp(); this.button.menu.populate(); }.bind(this))\n .html('▴').attr('title', 'Move layer up (further front)');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-end lz-dashboard-button-red')\n .style({ 'margin-left': '0em' })\n .on('click', function() {\n if (confirm('Are you sure you want to remove the ' + name + ' layer? This cannot be undone!')) {\n data_layer.parent.removeDataLayer(id);\n }\n return this.button.menu.populate();\n }.bind(this))\n .html('×').attr('title', 'Remove layer');\n }.bind(this));\n return this;\n }.bind(this));\n\n this.button.show();\n\n return this;\n };\n});\n\n/**\n * Dropdown menu allowing the user to choose between different display options for a single specific data layer\n * within a panel.\n *\n * This allows controlling how points on a datalayer can be displayed- any display options supported via the layout for the target datalayer. This includes point\n * size/shape, coloring, etc.\n *\n * This button intentionally limits display options it can control to those available on common plot types.\n * Although the list of options it sets can be overridden (to control very special custom plot types), this\n * capability should be used sparingly if at all.\n *\n * @class LocusZoom.Dashboard.Components.display_options\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Display options...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Control how plot items are displayed\"] Hover text for the toolbar button\n * @param {string} layout.layer_name Specify the datalayer that this button should affect\n * @param {string} [layout.default_config_display_name] Store the default configuration for this datalayer\n * configuration, and show a button to revert to the \"default\" (listing the human-readable display name provided)\n * @param {Array} [layout.fields_whitelist='see code'] The list of presentation fields that this button can control.\n * This can be overridden if this button needs to be used on a custom layer type with special options.\n * @typedef {{display_name: string, display: Object}} DisplayOptionsButtonConfigField\n * @param {DisplayOptionsButtonConfigField[]} layout.options Specify a label and set of layout directives associated\n * with this `display` option. Display field should include all changes to datalayer presentation options.\n */\nLocusZoom.Dashboard.Components.add('display_options', function (layout) {\n if (typeof layout.button_html != 'string') { layout.button_html = 'Display options...'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Control how plot items are displayed'; }\n\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n // List of layout fields that this button is allowed to control. This ensures that we don't override any other\n // information (like plot height etc) while changing point rendering\n var allowed_fields = layout.fields_whitelist || ['color', 'fill_opacity', 'label', 'legend',\n 'point_shape', 'point_size', 'tooltip', 'tooltip_positioning'];\n\n var dataLayer = this.parent_panel.data_layers[layout.layer_name];\n if (!dataLayer) {\n throw new Error(\"Display options could not locate the specified layer_name: '\" + layout.layer_name + \"'\");\n }\n var dataLayerLayout = dataLayer.layout;\n\n // Store default configuration for the layer as a clean deep copy, so we may revert later\n var defaultConfig = {};\n allowed_fields.forEach(function(name) {\n var configSlot = dataLayerLayout[name];\n if (configSlot !== undefined) {\n defaultConfig[name] = JSON.parse(JSON.stringify(configSlot));\n }\n });\n\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n this._selected_item = 'default';\n\n // Define the button + menu that provides the real functionality for this dashboard component\n var self = this;\n this.button = new LocusZoom.Dashboard.Component.Button(self)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 1e4).toString();\n\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n\n var menuLayout = self.layout;\n\n var renderRow = function(display_name, display_options, row_id) { // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td')\n .append('input')\n .attr({id: radioId, type: 'radio', name: 'display-option-' + uniqueID, value: row_id})\n .style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n .property('checked', (row_id === self._selected_item))\n .on('click', function () {\n // If an option is not specified in these display options, use the original defaults\n allowed_fields.forEach(function(field_name) {\n dataLayer.layout[field_name] = display_options[field_name] || defaultConfig[field_name];\n });\n\n self._selected_item = row_id;\n self.parent_panel.render();\n var legend = self.parent_panel.legend;\n if (legend) {\n legend.render();\n }\n });\n row.append('td').append('label')\n .style('font-weight', 'normal')\n .attr('for', radioId)\n .text(display_name);\n };\n // Render the \"display options\" menu: default and special custom options\n var defaultName = menuLayout.default_config_display_name || 'Default style';\n renderRow(defaultName, defaultConfig, 'default');\n menuLayout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.display, index);\n });\n return self;\n });\n\n this.update = function () {\n this.button.show();\n return this;\n };\n});\n\n\n/**\n * Dropdown menu allowing the user to set the value of a specific `state_field` in plot.state\n * This is useful for things (like datasources) that allow dynamic configuration based on global information in state\n *\n * For example, the LDLZ2 data source can use it to change LD reference population (for all panels) after render\n *\n * @class LocusZoom.Dashboard.Components.set_state\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Set option...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Choose an option to customize the plot\"] Hover text for the toolbar button\n * @param {bool} [layout.show_selected=false] Whether to append the selected value to the button label\n * @param {string} [layout.state_field] The name of the field in plot.state that will be set by this button\n * @typedef {{display_name: string, value: *}} SetStateOptionsConfigField\n * @param {SetStateOptionsConfigField[]} layout.options Specify human labels and associated values for the dropdown menu\n */\nLocusZoom.Dashboard.Components.add('set_state', function (layout) {\n var self = this;\n if (typeof layout.button_html != 'string') { layout.button_html = 'Set option...'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Choose an option to customize the plot'; }\n\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n if (this.parent_panel) {\n throw new Error('This widget is designed to set global options, so it can only be used at the top (plot) level');\n }\n if (!layout.state_field) {\n throw new Error('Must specify the `state_field` that this widget controls');\n }\n\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n // The first option listed is automatically assumed to be the default, unless a value exists in plot.state\n this._selected_item = this.parent_plot.state[layout.state_field] || layout.options[0].value;\n if (!layout.options.find(function(item) { return item.value === self._selected_item; })) {\n // Check only gets run at widget creation, but generally this widget is assumed to be an exclusive list of options\n throw new Error('There is an existing state value that does not match the known values in this widget');\n }\n\n // Define the button + menu that provides the real functionality for this dashboard component\n this.button = new LocusZoom.Dashboard.Component.Button(self)\n .setColor(layout.color)\n .setHtml(layout.button_html + (layout.show_selected ? this._selected_item : ''))\n .setTitle(layout.button_title)\n .setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 1e4).toString();\n\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n\n var renderRow = function(display_name, value, row_id) { // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td')\n .append('input')\n .attr({id: radioId, type: 'radio', name: 'set-state-' + uniqueID, value: row_id})\n .style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n .property('checked', (value === self._selected_item))\n .on('click', function () {\n var new_state = {};\n new_state[layout.state_field] = value;\n self._selected_item = value;\n self.parent_plot.applyState(new_state);\n self.button.setHtml(layout.button_html + (layout.show_selected ? self._selected_item : ''));\n });\n row.append('td').append('label')\n .style('font-weight', 'normal')\n .attr('for', radioId)\n .text(display_name);\n };\n layout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.value, index);\n });\n return self;\n });\n\n this.update = function () {\n this.button.show();\n return this;\n };\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n *\n * LocusZoom has various singleton objects that are used for registering functions or classes.\n * These objects provide safe, standard methods to redefine or delete existing functions/classes\n * as well as define new custom functions/classes to be used in a plot.\n *\n * @namespace Singletons\n */\n\n\n/*\n * The Collection of \"Known\" Data Sources. This registry is used internally by the `DataSources` class\n * @class\n * @static\n */\nLocusZoom.KnownDataSources = (function() {\n /** @lends LocusZoom.KnownDataSources */\n var obj = {};\n /* @member {function[]} */\n var sources = [];\n\n var findSourceByName = function(x) {\n for(var i = 0; i < sources.length; i++) {\n if (!sources[i].SOURCE_NAME) {\n throw new Error('KnownDataSources at position ' + i + \" does not have a 'SOURCE_NAME' static property\");\n }\n if (sources[i].SOURCE_NAME === x) {\n return sources[i];\n }\n }\n return null;\n };\n\n /**\n * Identify the datasource associated with a given name\n * @param {String} name\n * @returns {function} The constructor for the data source; will usually extend `Data.Source`\n */\n obj.get = function(name) {\n return findSourceByName(name);\n };\n\n /**\n * Register a data source constructor so that it may be located by name\n * @param {function} source A constructor function for a data source; will usually extend `Data.Source`,\n * and should have a `SOURCE_NAME` property\n */\n obj.add = function(source) {\n if (!source.SOURCE_NAME) {\n console.warn('Data source added does not have a SOURCE_NAME');\n }\n sources.push(source);\n };\n\n /**\n * Create a custom source type that extends the behavior of an existing source, and registers that\n * source by the provided name\n * @param {String} parent_name The name of a previously registered data source type to use as a template\n * @param {String} source_name The new name to use when registering this data source\n * @param {Object} overrides An object of additional properties and methods to add/override behavior\n * @returns {LocusZoom.Data.Source} The newly defined class for this source\n */\n obj.extend = function(parent_name, source_name, overrides) {\n var parent = findSourceByName(parent_name);\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered data source');\n }\n if (!source_name) {\n throw new Error('Must provide a name for the new data source');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n child.SOURCE_NAME = source_name;\n sources.push(child);\n return child;\n };\n\n /** @deprecated */\n obj.push = function(source) {\n console.warn('Warning: KnownDataSources.push() is deprecated. Use .add() instead');\n obj.add(source);\n };\n\n /**\n * List the names of all registered datasources\n * @returns {String[]}\n */\n obj.list = function() {\n return sources.map(function(x) {return x.SOURCE_NAME;});\n };\n\n /**\n * Create a datasource instance\n * @param {String} name The name of the desired datasource to instantiate (must be defined in the registry)\n * @returns {LocusZoom.Data.Source}\n */\n obj.create = function(name) {\n //create new object (pass additional parameters to constructor)\n var newObj = findSourceByName(name);\n if (newObj) {\n var params = arguments;\n params[0] = null;\n return new (Function.prototype.bind.apply(newObj, params));\n } else {\n throw new Error('Unable to find data source for name: ' + name);\n }\n };\n\n /**\n * Get the array of all registered constructors\n * Generally only used for unit tests internally\n * @private\n * @returns {function[]}\n */\n obj.getAll = function() {\n return sources;\n };\n\n /**\n * Register an entire collection of data sources\n * Generally only used for unit tests internally\n * @private\n * @param {function[]} x An array of datasource constructors\n */\n obj.setAll = function(x) {\n sources = x;\n };\n\n /**\n * Unregister all known data sources\n * Generally only used for unit tests internally\n * @private\n */\n obj.clear = function() {\n sources = [];\n };\n\n return obj;\n})();\n\n/**************************\n * Transformation Functions\n *\n * Singleton for formatting or transforming a single input, for instance turning raw p values into negative log10 form\n * Transformation functions are chainable with a pipe on a field name, like so: \"pvalue|neglog10\"\n *\n * NOTE: Because these functions are chainable the FUNCTION is returned by get(), not the result of that function.\n *\n * All transformation functions must accept an object of parameters and a value to process.\n * @class\n */\nLocusZoom.TransformationFunctions = (function() {\n /** @lends LocusZoom.TransformationFunctions */\n var obj = {};\n var transformations = {};\n\n var getTrans = function(name) {\n if (!name) {\n return null;\n }\n var fun = transformations[name];\n if (fun) {\n return fun;\n } else {\n throw new Error('transformation ' + name + ' not found');\n }\n };\n\n //a single transformation with any parameters\n //(parameters not currently supported)\n var parseTrans = function(name) {\n return getTrans(name);\n };\n\n //a \"raw\" transformation string with a leading pipe\n //and one or more transformations\n var parseTransString = function(x) {\n var funs = [];\n var re = /\\|([^|]+)/g;\n var result;\n while((result = re.exec(x)) !== null) {\n funs.push(result[1]);\n }\n if (funs.length === 1) {\n return parseTrans(funs[0]);\n } else if (funs.length > 1) {\n return function(x) {\n var val = x;\n for(var i = 0; i < funs.length; i++) {\n val = parseTrans(funs[i])(val);\n }\n return val;\n };\n }\n return null;\n };\n\n /**\n * Retrieve a transformation function by name\n * @param {String} name The name of the transformation function to retrieve. May optionally be prefixed with a\n * pipe (`|`) when chaining multiple transformation functions.\n * @returns {function} The constructor for the transformation function\n */\n obj.get = function(name) {\n if (name && name.substring(0,1) === '|') {\n return parseTransString(name);\n } else {\n return parseTrans(name);\n }\n };\n /**\n * Internal logic that registers a transformation function\n * @protected\n * @param {String} name\n * @param {function} fn\n */\n obj.set = function(name, fn) {\n if (name.substring(0,1) === '|') {\n throw new Error('transformation name should not start with a pipe');\n } else {\n if (fn) {\n transformations[name] = fn;\n } else {\n delete transformations[name];\n }\n }\n };\n\n /**\n * Register a transformation function\n * @param {String} name\n * @param {function} fn A transformation function (should accept one argument with the value)\n */\n obj.add = function(name, fn) {\n if (transformations[name]) {\n throw new Error('transformation already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n /**\n * List the names of all registered transformation functions\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(transformations);\n };\n\n return obj;\n})();\n\n/**\n * Return the -log (base 10)\n * @function neglog10\n */\nLocusZoom.TransformationFunctions.add('neglog10', function(x) {\n if (isNaN(x) || x <= 0) { return null; }\n return -Math.log(x) / Math.LN10;\n});\n\n/**\n * Convert a number from logarithm to scientific notation. Useful for, eg, a datasource that returns -log(p) by default\n * @function logtoscinotation\n */\nLocusZoom.TransformationFunctions.add('logtoscinotation', function(x) {\n if (isNaN(x)) { return 'NaN'; }\n if (x === 0) { return '1'; }\n var exp = Math.ceil(x);\n var diff = exp - x;\n var base = Math.pow(10, diff);\n if (exp === 1) {\n return (base / 10).toFixed(4);\n } else if (exp === 2) {\n return (base / 100).toFixed(3);\n } else {\n return base.toFixed(2) + ' × 10^-' + exp;\n }\n});\n\n/**\n * Represent a number in scientific notation\n * @function scinotation\n * @param {Number} x\n * @returns {String}\n */\nLocusZoom.TransformationFunctions.add('scinotation', function(x) {\n if (isNaN(x)) { return 'NaN'; }\n if (x === 0) { return '0'; }\n\n var abs = Math.abs(x);\n var log;\n if (abs > 1) {\n log = Math.ceil(Math.log(abs) / Math.LN10);\n } else { // 0...1\n log = Math.floor(Math.log(abs) / Math.LN10);\n }\n if (Math.abs(log) <= 3) {\n return x.toFixed(3);\n } else {\n return x.toExponential(2).replace('+', '').replace('e', ' × 10^');\n }\n});\n\n/**\n * URL-encode the provided text, eg for constructing hyperlinks\n * @function urlencode\n * @param {String} str\n */\nLocusZoom.TransformationFunctions.add('urlencode', function(str) {\n return encodeURIComponent(str);\n});\n\n/**\n * HTML-escape user entered values for use in constructed HTML fragments\n *\n * For example, this filter can be used on tooltips with custom HTML display\n * @function htmlescape\n * @param {String} str HTML-escape the provided value\n */\nLocusZoom.TransformationFunctions.add('htmlescape', function(str) {\n if ( !str ) {\n return '';\n }\n str = str + '';\n\n return str.replace( /['\"<>&`]/g, function( s ) {\n switch ( s ) {\n case \"'\":\n return ''';\n case '\"':\n return '"';\n case '<':\n return '<';\n case '>':\n return '>';\n case '&':\n return '&';\n case '`':\n return '`';\n }\n });\n});\n\n/**\n * Singleton for accessing/storing functions that will convert arbitrary data points to values in a given scale\n * Useful for anything that needs to scale discretely with data (e.g. color, point size, etc.)\n *\n * A Scale Function can be thought of as a modifier to a layout directive that adds extra logic to how a piece of data\n * can be resolved to a value.\n *\n * All scale functions must accept an object of parameters and a value to process.\n * @class\n * @static\n */\nLocusZoom.ScaleFunctions = (function() {\n /** @lends LocusZoom.ScaleFunctions */\n var obj = {};\n var functions = {};\n\n /**\n * Find a scale function and return it. If parameters and values are passed, calls the function directly; otherwise\n * returns a callable.\n * @param {String} name\n * @param {Object} [parameters] Configuration parameters specific to the specified scale function\n * @param {*} [value] The value to operate on\n * @returns {*}\n */\n obj.get = function(name, parameters, value) {\n if (!name) {\n return null;\n } else if (functions[name]) {\n if (typeof parameters === 'undefined' && typeof value === 'undefined') {\n return functions[name];\n } else {\n return functions[name](parameters, value);\n }\n } else {\n throw new Error('scale function [' + name + '] not found');\n }\n };\n\n /**\n * @protected\n * @param {String} name The name of the function to set/unset\n * @param {Function} [fn] The function to register. If blank, removes this function name from the registry.\n */\n obj.set = function(name, fn) {\n if (fn) {\n functions[name] = fn;\n } else {\n delete functions[name];\n }\n };\n\n /**\n * Add a new scale function to the registry\n * @param {String} name The name of the scale function\n * @param {function} fn A scale function that accepts two parameters: an object of configuration and a value\n */\n obj.add = function(name, fn) {\n if (functions[name]) {\n throw new Error('scale function already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n\n /**\n * List the names of all registered scale functions\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(functions);\n };\n\n return obj;\n})();\n\n/**\n * Basic conditional function to evaluate the value of the input field and return based on equality.\n * @param {Object} parameters\n * @param {*} parameters.field_value The value against which to test the input value.\n * @param {*} parameters.then The value to return if the input value matches the field value\n * @param {*} parameters.else The value to return if the input value does not match the field value. Optional. If not\n * defined this scale function will return null (or value of null_value parameter, if defined) when input value fails\n * to match field_value.\n * @param {*} input value\n */\nLocusZoom.ScaleFunctions.add('if', function(parameters, input) {\n if (typeof input == 'undefined' || parameters.field_value !== input) {\n if (typeof parameters.else != 'undefined') {\n return parameters.else;\n } else {\n return null;\n }\n } else {\n return parameters.then;\n }\n});\n\n/**\n * Function to sort numerical values into bins based on numerical break points. Will only operate on numbers and\n * return null (or value of null_value parameter, if defined) if provided a non-numeric input value. Parameters:\n * @function numerical_bin\n * @param {Object} parameters\n * @param {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter. If the input value is greater than or equal to break n and less than\n * or equal to break n+1 (or break n+1 doesn't exist) then returned value is the nth entry in the values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against break points. Must be of\n * equal length to breaks parameter. Each entry n represents the value to return if the input value is greater than\n * or equal to break n and less than or equal to break n+1 (or break n+1 doesn't exist).\n * @param {*} null_value\n * @param {*} input value\n * @returns\n */\nLocusZoom.ScaleFunctions.add('numerical_bin', function(parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n if (typeof input == 'undefined' || input === null || isNaN(+input)) {\n return (parameters.null_value ? parameters.null_value : null);\n }\n var threshold = breaks.reduce(function(prev, curr) {\n if (+input < prev || (+input >= prev && +input < curr)) {\n return prev;\n } else {\n return curr;\n }\n });\n return values[breaks.indexOf(threshold)];\n});\n\n/**\n * Function to sort values of any type into bins based on direct equality testing with a list of categories.\n * Will return null if provided an input value that does not match to a listed category.\n * @function categorical_bin\n * @param {Object} parameters\n * @param {Array} parameters.categories Array of values against which to evaluate the input value. Must be of equal\n * length to values parameter. If the input value is equal to category n then returned value is the nth entry in the\n * values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against categories. Must be of equal\n * length to categories parameter. Each entry n represents the value to return if the input value is equal to the nth\n * value in the categories parameter.\n * @param {*} parameters.null_value Value to return if the input value fails to match to any categories. Optional.\n */\nLocusZoom.ScaleFunctions.add('categorical_bin', function(parameters, value) {\n if (typeof value == 'undefined' || parameters.categories.indexOf(value) === -1) {\n return (parameters.null_value ? parameters.null_value : null);\n } else {\n return parameters.values[parameters.categories.indexOf(value)];\n }\n});\n\n/**\n * Function for continuous interpolation of numerical values along a gradient with arbitrarily many break points.\n * @function interpolate\n * @parameters {Object} parameters\n * @parameters {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter and contain at least two elements. Input value will be evaluated for\n * relative position between two break points n and n+1 and the returned value will be interpolated at a relative\n * position between values n and n+1.\n * @parameters {*[]} parameters.values Array of values to interpolate and return given evaluations against break\n * points. Must be of equal length to breaks parameter and contain at least two elements. Each entry n represents\n * the value to return if the input value matches the nth entry in breaks exactly. Note that this scale function\n * uses d3.interpolate to provide for effective interpolation of many different value types, including numbers,\n * colors, shapes, etc.\n * @parameters {*} parameters.null_value\n */\nLocusZoom.ScaleFunctions.add('interpolate', function(parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n var nullval = (parameters.null_value ? parameters.null_value : null);\n if (breaks.length < 2 || breaks.length !== values.length) { return nullval; }\n if (typeof input == 'undefined' || input === null || isNaN(+input)) { return nullval; }\n if (+input <= parameters.breaks[0]) {\n return values[0];\n } else if (+input >= parameters.breaks[parameters.breaks.length - 1]) {\n return values[breaks.length - 1];\n } else {\n var upper_idx = null;\n breaks.forEach(function(brk, idx) {\n if (!idx) { return; }\n if (breaks[idx - 1] <= +input && breaks[idx] >= +input) { upper_idx = idx; }\n });\n if (upper_idx === null) { return nullval; }\n var normalized_input = (+input - breaks[upper_idx - 1]) / (breaks[upper_idx] - breaks[upper_idx - 1]);\n if (!isFinite(normalized_input)) { return nullval; }\n return d3.interpolate(values[upper_idx - 1], values[upper_idx])(normalized_input);\n }\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A data layer is an abstract class representing a data set and its graphical representation within a panel\n * @public\n * @class\n * @param {Object} layout A JSON-serializable object describing the layout for this layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n*/\nLocusZoom.DataLayer = function(layout, parent) {\n /** @member {Boolean} */\n this.initialized = false;\n /** @member {Number} */\n this.layout_idx = null;\n\n /** @member {String} */\n this.id = null;\n /** @member {LocusZoom.Panel} */\n this.parent = parent || null;\n /**\n * @member {{group: d3.selection, container: d3.selection, clipRect: d3.selection}}\n */\n this.svg = {};\n\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n if (typeof parent != 'undefined' && parent instanceof LocusZoom.Panel) { this.parent_plot = parent.parent; }\n\n /** @member {Object} */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.DataLayer.DefaultLayout);\n if (this.layout.id) { this.id = this.layout.id; }\n\n // Ensure any axes defined in the layout have an explicit axis number (default: 1)\n if (this.layout.x_axis !== {} && typeof this.layout.x_axis.axis !== 'number') { this.layout.x_axis.axis = 1; }\n if (this.layout.y_axis !== {} && typeof this.layout.y_axis.axis !== 'number') { this.layout.y_axis.axis = 1; }\n\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original data layer state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n\n /** @member {Object} */\n this.state = {};\n /** @member {String} */\n this.state_id = null;\n\n this.setDefaultState();\n\n // Initialize parameters for storing data and tool tips\n /** @member {Array} */\n this.data = [];\n if (this.layout.tooltip) {\n /** @member {Object} */\n this.tooltips = {};\n }\n\n // Initialize flags for tracking global statuses\n this.global_statuses = {\n 'highlighted': false,\n 'selected': false,\n 'faded': false,\n 'hidden': false\n };\n\n return this;\n\n};\n\n/**\n * Instruct this datalayer to begin tracking additional fields from data sources (does not guarantee that such a field actually exists)\n *\n * Custom plots can use this to dynamically extend datalayer functionality after the plot is drawn\n *\n * (since removing core fields may break layer functionality, there is presently no hook for the inverse behavior)\n * @param fieldName\n * @param namespace\n * @param {String|String[]} transformations The name (or array of names) of transformations to apply to this field\n * @returns {String} The raw string added to the fields array\n */\nLocusZoom.DataLayer.prototype.addField = function(fieldName, namespace, transformations) {\n if (!fieldName || !namespace) {\n throw new Error('Must specify field name and namespace to use when adding field');\n }\n var fieldString = namespace + ':' + fieldName;\n if (transformations) {\n fieldString += '|';\n if (typeof transformations === 'string') {\n fieldString += transformations;\n } else if (Array.isArray(transformations)) {\n fieldString += transformations.join('|');\n } else {\n throw new Error('Must provide transformations as either a string or array of strings');\n }\n }\n var fields = this.layout.fields;\n if (fields.indexOf(fieldString) === -1) {\n fields.push(fieldString);\n }\n return fieldString;\n};\n\n/**\n * Define default state that should get tracked during the lifetime of this layer.\n *\n * In some special custom usages, it may be useful to completely reset a panel (eg \"click for\n * genome region\" links), plotting new data that invalidates any previously tracked state. This hook makes it\n * possible to reset without destroying the panel entirely. It is used by `Plot.clearPanelData`.\n */\nLocusZoom.DataLayer.prototype.setDefaultState = function() {\n // Define state parameters specific to this data layer. Within plot state, this will live under a key\n // `panel_name.layer_name`.\n if (this.parent) {\n this.state = this.parent.state;\n this.state_id = this.parent.id + '.' + this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n var layer_state = this.state[this.state_id];\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function(status) {\n layer_state[status] = layer_state[status] || [];\n });\n // Also initialize \"internal-only\" state fields\n layer_state['has_tooltip'] = layer_state['has_tooltip'] || [];\n }\n};\n\n/**\n * A basic description of keys expected in a layout. Not intended to be directly used or modified by an end user.\n * @protected\n * @type {{type: string, fields: Array, x_axis: {}, y_axis: {}}}\n */\nLocusZoom.DataLayer.DefaultLayout = {\n type: '',\n fields: [],\n x_axis: {},\n y_axis: {}\n};\n\n/**\n * Available statuses that individual elements can have. Each status is described by\n * a verb/antiverb and an adjective. Verbs and antiverbs are used to generate data layer\n * methods for updating the status on one or more elements. Adjectives are used in class\n * names and applied or removed from elements to have a visual representation of the status,\n * as well as used as keys in the state for tracking which elements are in which status(es)\n * @static\n * @type {{verbs: String[], adjectives: String[], menu_antiverbs: String[]}}\n */\nLocusZoom.DataLayer.Statuses = {\n verbs: ['highlight', 'select', 'fade', 'hide'],\n adjectives: ['highlighted', 'selected', 'faded', 'hidden'],\n menu_antiverbs: ['unhighlight', 'deselect', 'unfade', 'show']\n};\n\n/**\n * Get the fully qualified identifier for the data layer, prefixed by any parent or container elements\n *\n * @returns {string} A dot-delimited string of the format ..\n */\nLocusZoom.DataLayer.prototype.getBaseId = function() {\n return this.parent_plot.id + '.' + this.parent.id + '.' + this.id;\n};\n\n/**\n * Determine the pixel height of data-bound objects represented inside this data layer. (excluding elements such as axes)\n *\n * May be used by operations that resize the data layer to fit available data\n *\n * @public\n * @returns {number}\n */\nLocusZoom.DataLayer.prototype.getAbsoluteDataHeight = function() {\n var dataBCR = this.svg.group.node().getBoundingClientRect();\n return dataBCR.height;\n};\n\n/**\n * Whether transitions can be applied to this data layer\n * @returns {boolean}\n */\nLocusZoom.DataLayer.prototype.canTransition = function() {\n if (!this.layout.transition) { return false; }\n return !(this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.panel_id);\n};\n\n/**\n * Fetch the fully qualified ID to be associated with a specific visual element, based on the data to which that\n * element is bound. In general this element ID will be unique, allowing it to be addressed directly via selectors.\n * @param {String|Object} element\n * @returns {String}\n */\nLocusZoom.DataLayer.prototype.getElementId = function(element) {\n var element_id = 'element';\n if (typeof element == 'string') {\n element_id = element;\n } else if (typeof element == 'object') {\n var id_field = this.layout.id_field || 'id';\n if (typeof element[id_field] == 'undefined') {\n throw new Error('Unable to generate element ID');\n }\n element_id = element[id_field].toString().replace(/\\W/g,'');\n }\n return (this.getBaseId() + '-' + element_id).replace(/([:.[\\],])/g, '_');\n};\n\n/**\n * Fetch an ID that may bind a data element to a separate visual node for displaying status\n * Examples of this might be seperate visual nodes to show select/highlight statuses, or\n * even a common/shared node to show status across many elements in a set.\n * Abstract method. It should be overridden by data layers that implement seperate status\n * nodes specifically to the use case of the data layer type.\n * @param {String|Object} element\n * @returns {String|null}\n */\nLocusZoom.DataLayer.prototype.getElementStatusNodeId = function(element) {\n return null;\n};\n\n/**\n * Returns a reference to the underlying data associated with a single visual element in the data layer, as\n * referenced by the unique identifier for the element\n\n * @param {String} id The unique identifier for the element, as defined by `getElementId`\n * @returns {Object|null} The data bound to that element\n */\nLocusZoom.DataLayer.prototype.getElementById = function(id) {\n var selector = d3.select('#' + id.replace(/([:.[\\],])/g, '\\\\$1')); // escape special characters\n if (!selector.empty() && selector.data() && selector.data().length) {\n return selector.data()[0];\n } else {\n return null;\n }\n};\n\n/**\n * Basic method to apply arbitrary methods and properties to data elements.\n * This is called on all data immediately after being fetched.\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.applyDataMethods = function() {\n var field_to_match = (this.layout.match && this.layout.match.receive);\n var broadcast_value = this.parent_plot.state.lz_match_value;\n\n this.data.forEach(function(d, i) {\n // Basic toHTML() method - return the stringified value in the id_field, if defined.\n\n // When this layer receives data, mark whether points match (via a synthetic boolean field)\n // Any field-based layout directives (color, size, shape) can then be used to control display\n if (field_to_match && broadcast_value !== null && broadcast_value !== undefined) {\n d.lz_highlight_match = (d[field_to_match] === broadcast_value);\n }\n\n this.data[i].toHTML = function() {\n var id_field = this.layout.id_field || 'id';\n var html = '';\n if (this.data[i][id_field]) { html = this.data[i][id_field].toString(); }\n return html;\n }.bind(this);\n // getDataLayer() method - return a reference to the data layer\n this.data[i].getDataLayer = function() {\n return this;\n }.bind(this);\n // deselect() method - shortcut method to deselect the element\n this.data[i].deselect = function() {\n var data_layer = this.getDataLayer();\n data_layer.unselectElement(this);\n };\n }.bind(this));\n this.applyCustomDataMethods();\n return this;\n};\n\n/**\n * Hook that allows custom datalayers to apply additional methods and properties to data elements as needed\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.applyCustomDataMethods = function() {\n return this;\n};\n\n/**\n * Initialize a data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.initialize = function() {\n\n // Append a container group element to house the main data layer group element and the clip path\n this.svg.container = this.parent.svg.group.append('g')\n .attr('class', 'lz-data_layer-container')\n .attr('id', this.getBaseId() + '.data_layer_container');\n\n // Append clip path to the container element\n this.svg.clipRect = this.svg.container.append('clipPath')\n .attr('id', this.getBaseId() + '.clip')\n .append('rect');\n\n // Append svg group for rendering all data layer elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g')\n .attr('id', this.getBaseId() + '.data_layer')\n .attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n\n return this;\n\n};\n\n/**\n * Move a data layer up relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.moveUp = function() {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n};\n\n/**\n * Move a data layer down relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.moveDown = function() {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n};\n\n/**\n * Apply scaling functions to an element or parameter as needed, based on its layout and the element's data\n * If the layout parameter is already a primitive type, simply return the value as given\n * @param {Array|Number|String|Object} layout\n * @param {*} data The value to be used with the filter\n * @returns {*} The transformed value\n */\nLocusZoom.DataLayer.prototype.resolveScalableParameter = function(layout, data) {\n var ret = null;\n if (Array.isArray(layout)) {\n var idx = 0;\n while (ret === null && idx < layout.length) {\n ret = this.resolveScalableParameter(layout[idx], data);\n idx++;\n }\n } else {\n switch (typeof layout) {\n case 'number':\n case 'string':\n ret = layout;\n break;\n case 'object':\n if (layout.scale_function) {\n if(layout.field) {\n var f = new LocusZoom.Data.Field(layout.field);\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, f.resolve(data));\n } else {\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, data);\n }\n }\n break;\n }\n }\n return ret;\n};\n\n\n/**\n * Implementation hook for fetching the min and max values of available data. Used to determine axis range, if no other\n * explicit axis settings override. Useful for data layers where the data extent depends on more than one field.\n * (eg confidence intervals in a forest plot)\n * @param data\n * @param axis_config The configuration object for the specified axis.\n * @returns {Array} [min, max] without any padding applied\n * @private\n */\nLocusZoom.DataLayer.prototype._getDataExtent = function(data, axis_config) {\n data = data || this.data;\n // By default this depends only on a single field.\n return d3.extent(data, function (d) {\n var f = new LocusZoom.Data.Field(axis_config.field);\n return +f.resolve(d);\n });\n};\n\n/**\n * Generate dimension extent function based on layout parameters\n * @param {('x'|'y')} dimension\n */\nLocusZoom.DataLayer.prototype.getAxisExtent = function(dimension) {\n\n if (['x', 'y'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier passed to LocusZoom.DataLayer.getAxisExtent()');\n }\n\n var axis_name = dimension + '_axis';\n var axis_layout = this.layout[axis_name];\n\n // If a floor AND a ceiling are explicitly defined then just return that extent and be done\n if (!isNaN(axis_layout.floor) && !isNaN(axis_layout.ceiling)) {\n return [+axis_layout.floor, +axis_layout.ceiling];\n }\n\n // If a field is defined for the axis and the data layer has data then generate the extent from the data set\n var data_extent = [];\n if (axis_layout.field && this.data) {\n if (!this.data.length) {\n // If data has been fetched (but no points in region), enforce the min_extent (with no buffers,\n // because we don't need padding around an empty screen)\n data_extent = axis_layout.min_extent || [];\n return data_extent;\n } else {\n data_extent = this._getDataExtent(this.data, axis_layout);\n\n // Apply upper/lower buffers, if applicable\n var original_extent_span = data_extent[1] - data_extent[0];\n if (!isNaN(axis_layout.lower_buffer)) {\n data_extent[0] -= original_extent_span * axis_layout.lower_buffer;\n }\n if (!isNaN(axis_layout.upper_buffer)) {\n data_extent[1] += original_extent_span * axis_layout.upper_buffer;\n }\n\n if (typeof axis_layout.min_extent == 'object') {\n // The data should span at least the range specified by min_extent, an array with [low, high]\n var range_min = axis_layout.min_extent[0];\n var range_max = axis_layout.min_extent[1];\n if (!isNaN(range_min) && !isNaN(range_max)) {\n data_extent[0] = Math.min(data_extent[0], range_min);\n }\n if (!isNaN(range_max)) {\n data_extent[1] = Math.max(data_extent[1], range_max);\n }\n }\n // If specified, floor and ceiling will override the actual data range\n return [\n isNaN(axis_layout.floor) ? data_extent[0] : axis_layout.floor,\n isNaN(axis_layout.ceiling) ? data_extent[1] : axis_layout.ceiling\n ];\n }\n }\n\n // If this is for the x axis and no extent could be generated yet but state has a defined start and end\n // then default to using the state-defined region as the extent\n if (dimension === 'x' && !isNaN(this.state.start) && !isNaN(this.state.end)) {\n return [this.state.start, this.state.end];\n }\n\n // No conditions met for generating a valid extent, return an empty array\n return [];\n\n};\n\n/**\n * Allow this data layer to tell the panel what axis ticks it thinks it will require. The panel may choose whether\n * to use some, all, or none of these when rendering, either alone or in conjunction with other data layers.\n *\n * This method is a stub and should be overridden in data layers that need to specify custom behavior.\n *\n * @param {('x'|'y1'|'y2')} dimension\n * @param {Object} [config] Additional parameters for the panel to specify how it wants ticks to be drawn. The names\n * and meanings of these parameters may vary between different data layers.\n * @returns {Object[]}\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\nLocusZoom.DataLayer.prototype.getTicks = function (dimension, config) {\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier at layer level' + dimension);\n }\n return [];\n};\n\n/**\n * Generate a tool tip for a given element\n * @param {String|Object} data Data for the element associated with the tooltip\n */\nLocusZoom.DataLayer.prototype.createTooltip = function(data) {\n if (typeof this.layout.tooltip != 'object') {\n throw new Error('DataLayer [' + this.id + '] layout does not define a tooltip');\n }\n var id = this.getElementId(data);\n if (this.tooltips[id]) {\n this.positionTooltip(id);\n return;\n }\n this.tooltips[id] = {\n data: data,\n arrow: null,\n selector: d3.select(this.parent_plot.svg.node().parentNode).append('div')\n .attr('class', 'lz-data_layer-tooltip')\n .attr('id', id + '-tooltip')\n };\n this.state[this.state_id]['has_tooltip'].push(id);\n this.updateTooltip(data);\n return this;\n};\n\n/**\n * Update a tool tip (generate its inner HTML)\n * @param {String|Object} d The element associated with the tooltip\n * @param {String} [id] An identifier to the tooltip\n */\nLocusZoom.DataLayer.prototype.updateTooltip = function(d, id) {\n if (typeof id == 'undefined') { id = this.getElementId(d); }\n // Empty the tooltip of all HTML (including its arrow!)\n this.tooltips[id].selector.html('');\n this.tooltips[id].arrow = null;\n // Set the new HTML\n if (this.layout.tooltip.html) {\n this.tooltips[id].selector.html(LocusZoom.parseFields(d, this.layout.tooltip.html));\n }\n // If the layout allows tool tips on this data layer to be closable then add the close button\n // and add padding to the tooltip to accommodate it\n if (this.layout.tooltip.closable) {\n this.tooltips[id].selector.insert('button', ':first-child')\n .attr('class', 'lz-tooltip-close-button')\n .attr('title', 'Close')\n .text('×')\n .on('click', function() {\n this.destroyTooltip(id);\n }.bind(this));\n }\n // Apply data directly to the tool tip for easier retrieval by custom UI elements inside the tool tip\n this.tooltips[id].selector.data([d]);\n // Reposition and draw a new arrow\n this.positionTooltip(id);\n return this;\n};\n\n/**\n * Destroy tool tip - remove the tool tip element from the DOM and delete the tool tip's record on the data layer\n * @param {String|Object} element_or_id The element (or id) associated with the tooltip\n * @param {boolean} [temporary=false] Whether this is temporary (not to be tracked in state). Differentiates\n * \"recreate tooltips on re-render\" (which is temporary) from \"user has closed this tooltip\" (permanent)\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.destroyTooltip = function(element_or_id, temporary) {\n var id;\n if (typeof element_or_id == 'string') {\n id = element_or_id;\n } else {\n id = this.getElementId(element_or_id);\n }\n if (this.tooltips[id]) {\n if (typeof this.tooltips[id].selector == 'object') {\n this.tooltips[id].selector.remove();\n }\n delete this.tooltips[id];\n }\n // When a tooltip is removed, also remove the reference from the state\n if (!temporary) {\n var state = this.state[this.state_id]['has_tooltip'];\n var label_mark_position = state.indexOf(id);\n state.splice(label_mark_position, 1);\n }\n return this;\n};\n\n/**\n * Loop through and destroy all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.destroyAllTooltips = function() {\n for (var id in this.tooltips) {\n this.destroyTooltip(id, true);\n }\n return this;\n};\n\n//\n/**\n * Position tool tip - naïve function to place a tool tip to the lower right of the current mouse element\n * Most data layers reimplement this method to position tool tips specifically for the data they display\n * @param {String} id The identifier of the tooltip to position\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n // Position the div itself\n this.tooltips[id].selector\n .style('left', (d3.event.pageX) + 'px')\n .style('top', (d3.event.pageY) + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!this.tooltips[id].arrow) {\n this.tooltips[id].arrow = this.tooltips[id].selector.append('div')\n .style('position', 'absolute')\n .attr('class', 'lz-data_layer-tooltip-arrow_top_left');\n }\n this.tooltips[id].arrow\n .style('left', '-1px')\n .style('top', '-1px');\n return this;\n};\n\n/**\n * Loop through and position all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.positionAllTooltips = function() {\n for (var id in this.tooltips) {\n this.positionTooltip(id);\n }\n return this;\n};\n\n/**\n * Show or hide a tool tip by ID depending on directives in the layout and state values relative to the ID\n * @param {String|Object} element The element associated with the tooltip\n * @param {boolean} first_time Because panels can re-render, the rules for showing a tooltip\n * depend on whether this is the first time a status change affecting display has been applied.\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.showOrHideTooltip = function(element, first_time) {\n if (typeof this.layout.tooltip != 'object') { return; }\n var id = this.getElementId(element);\n\n /**\n * Apply rules and decide whether to show or hide the tooltip\n * @param {Object} statuses All statuses that apply to an element\n * @param {String[]|object} directive A layout directive object\n * @param operator\n * @returns {null|bool}\n */\n var resolveStatus = function(statuses, directive, operator) {\n var status = null;\n if (typeof statuses != 'object' || statuses === null) { return null; }\n if (Array.isArray(directive)) {\n // This happens when the function is called on the inner part of the directive\n operator = operator || 'and';\n if (directive.length === 1) {\n status = statuses[directive[0]];\n } else {\n status = directive.reduce(function(previousValue, currentValue) {\n if (operator === 'and') {\n return statuses[previousValue] && statuses[currentValue];\n } else if (operator === 'or') {\n return statuses[previousValue] || statuses[currentValue];\n }\n return null;\n });\n }\n } else if (typeof directive == 'object') {\n var sub_status;\n for (var sub_operator in directive) {\n sub_status = resolveStatus(statuses, directive[sub_operator], sub_operator);\n if (status === null) {\n status = sub_status;\n } else if (operator === 'and') {\n status = status && sub_status;\n } else if (operator === 'or') {\n status = status || sub_status;\n }\n }\n } else {\n return false;\n }\n return status;\n };\n\n var show_directive = {};\n if (typeof this.layout.tooltip.show == 'string') {\n show_directive = { and: [ this.layout.tooltip.show ] };\n } else if (typeof this.layout.tooltip.show == 'object') {\n show_directive = this.layout.tooltip.show;\n }\n\n var hide_directive = {};\n if (typeof this.layout.tooltip.hide == 'string') {\n hide_directive = { and: [ this.layout.tooltip.hide ] };\n } else if (typeof this.layout.tooltip.hide == 'object') {\n hide_directive = this.layout.tooltip.hide;\n }\n\n // Find all the statuses that apply to just this single element\n var layer_state = this.state[this.state_id];\n var statuses = {}; // {status_name: bool}\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function(status) {\n var antistatus = 'un' + status;\n statuses[status] = (layer_state[status].indexOf(id) !== -1);\n statuses[antistatus] = !statuses[status];\n });\n\n // Decide whether to show/hide the tooltip based solely on the underlying element\n var show_resolved = resolveStatus(statuses, show_directive);\n var hide_resolved = resolveStatus(statuses, hide_directive);\n\n // Most of the tooltip display logic depends on behavior layouts: was point (un)selected, (un)highlighted, etc.\n // But sometimes, a point is selected, and the user then closes the tooltip. If the panel is re-rendered for\n // some outside reason (like state change), we must track this in the create/destroy events as tooltip state.\n var has_tooltip = (layer_state['has_tooltip'].indexOf(id) !== -1);\n var tooltip_was_closed = first_time ? false : !has_tooltip;\n if (show_resolved && !tooltip_was_closed && !hide_resolved) {\n this.createTooltip(element);\n } else {\n this.destroyTooltip(element);\n }\n\n return this;\n};\n\n/**\n * Find the elements (or indices) that match any of a set of provided filters\n * @protected\n * @param {Array[]} filters A list of filter entries: [field, value] (for equivalence testing) or\n * [field, operator, value] for other operators\n * @param {('indexes'|'elements')} [return_type='indexes'] Specify whether to return either the indices of the matching\n * elements, or references to the elements themselves\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filter = function(filters, return_type) {\n if (typeof return_type == 'undefined' || ['indexes','elements'].indexOf(return_type) === -1) {\n return_type = 'indexes';\n }\n if (!Array.isArray(filters)) { return []; }\n var test = function(element, filter) {\n var operators = {\n '=': function(a,b) { return a === b; },\n // eslint-disable-next-line eqeqeq\n '!=': function(a,b) { return a != b; }, // For absence of a value, deliberately allow weak comparisons (eg undefined/null)\n '<': function(a,b) { return a < b; },\n '<=': function(a,b) { return a <= b; },\n '>': function(a,b) { return a > b; },\n '>=': function(a,b) { return a >= b; },\n '%': function(a,b) { return a % b; }\n };\n if (!Array.isArray(filter)) { return false; }\n if (filter.length === 2) {\n return element[filter[0]] === filter[1];\n } else if (filter.length === 3 && operators[filter[1]]) {\n return operators[filter[1]](element[filter[0]], filter[2]);\n } else {\n return false;\n }\n };\n var matches = [];\n this.data.forEach(function(element, idx) {\n var match = true;\n filters.forEach(function(filter) {\n if (!test(element, filter)) { match = false; }\n });\n if (match) { matches.push(return_type === 'indexes' ? idx : element); }\n });\n return matches;\n};\n\n/**\n * @param filters\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filterIndexes = function(filters) { return this.filter(filters, 'indexes'); };\n/**\n * @param filters\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filterElements = function(filters) { return this.filter(filters, 'elements'); };\n\nLocusZoom.DataLayer.Statuses.verbs.forEach(function(verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset a single element's status\n // TODO: Improve documentation for dynamically generated methods/properties\n LocusZoom.DataLayer.prototype[verb + 'Element'] = function(element, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n this.setElementStatus(adjective, element, true, exclusive);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'Element'] = function(element, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n this.setElementStatus(adjective, element, false, exclusive);\n return this;\n };\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.DataLayer.prototype[verb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.DataLayer.prototype[antiverb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.DataLayer.prototype[verb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n});\n\n/**\n * Toggle a status (e.g. highlighted, selected, identified) on an element\n * @param {String} status The name of a recognized status to be added/removed on an appropriate element\n * @param {String|Object} element The data bound to the element of interest\n * @param {Boolean} active True to add the status (and associated CSS styles); false to remove it\n * @param {Boolean} exclusive Whether to only allow a state for a single element at a time\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setElementStatus = function(status, element, active, exclusive) {\n if (status === 'has_tooltip') {\n // This is a special adjective that exists solely to track tooltip state. It has no CSS and never gets set\n // directly. It is invisible to the official enums.\n return this;\n }\n\n // Sanity checks\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatus()');\n }\n if (typeof element == 'undefined') {\n throw new Error('Invalid element passed to DataLayer.setElementStatus()');\n }\n if (typeof active == 'undefined') {\n active = true;\n }\n\n // Get an ID for the element or return having changed nothing\n try {\n var element_id = this.getElementId(element);\n } catch (get_element_id_error) {\n return this;\n }\n\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !active);\n }\n\n // Set/unset the proper status class on the appropriate DOM element(s)\n d3.select('#' + element_id).classed('lz-data_layer-' + this.layout.type + '-' + status, active);\n var element_status_node_id = this.getElementStatusNodeId(element);\n if (element_status_node_id !== null) {\n d3.select('#' + element_status_node_id).classed('lz-data_layer-' + this.layout.type + '-statusnode-' + status, active);\n }\n\n // Track element ID in the proper status state array\n var element_status_idx = this.state[this.state_id][status].indexOf(element_id);\n var added_status = (element_status_idx === -1); // On a re-render, existing statuses will be reapplied.\n if (active && added_status) {\n this.state[this.state_id][status].push(element_id);\n }\n if (!active && !added_status) {\n this.state[this.state_id][status].splice(element_status_idx, 1);\n }\n\n // Trigger tool tip show/hide logic\n this.showOrHideTooltip(element, added_status);\n\n // Trigger layout changed event hook\n if (added_status) {\n this.parent.emit('layout_changed', true);\n }\n\n var is_selected = (status === 'selected');\n if (is_selected && (added_status || !active)) {\n // Notify parents that an element has changed selection status (either active, or inactive)\n this.parent.emit('element_selection', { element: element, active: active }, true);\n }\n\n var value_to_broadcast = (this.layout.match && this.layout.match.send);\n if (is_selected && value_to_broadcast && (added_status || !active)) {\n this.parent.emit(\n 'match_requested',\n { value: element[value_to_broadcast], active: active },\n true\n );\n }\n return this;\n};\n\n/**\n * Toggle a status on elements in the data layer based on a set of filters\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setElementStatusByFilters = function(status, toggle, filters, exclusive) {\n\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatusByFilters()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; } else { toggle = !!toggle; }\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n if (!Array.isArray(filters)) { filters = []; }\n\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !toggle);\n }\n\n // Apply statuses\n this.filterElements(filters).forEach(function(element) {\n this.setElementStatus(status, element, toggle);\n }.bind(this));\n\n return this;\n};\n\n/**\n * Toggle a status on all elements in the data layer\n * @param {String} status\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setAllElementStatus = function(status, toggle) {\n\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; }\n\n // Apply statuses\n if (toggle) {\n this.data.forEach(function(element) {\n this.setElementStatus(status, element, true);\n }.bind(this));\n } else {\n var status_ids = this.state[this.state_id][status].slice();\n status_ids.forEach(function(id) {\n var element = this.getElementById(id);\n if (typeof element == 'object' && element !== null) {\n this.setElementStatus(status, element, false);\n }\n }.bind(this));\n this.state[this.state_id][status] = [];\n }\n\n // Update global status flag\n this.global_statuses[status] = toggle;\n\n return this;\n};\n\n/**\n * Apply all layout-defined behaviors (DOM event handlers) to a selection of elements\n * @param {d3.selection} selection\n */\nLocusZoom.DataLayer.prototype.applyBehaviors = function(selection) {\n if (typeof this.layout.behaviors != 'object') { return; }\n Object.keys(this.layout.behaviors).forEach(function(directive) {\n var event_match = /(click|mouseover|mouseout)/.exec(directive);\n if (!event_match) { return; }\n selection.on(event_match[0] + '.' + directive, this.executeBehaviors(directive, this.layout.behaviors[directive]));\n }.bind(this));\n};\n\n/**\n * Generate a function that executes an arbitrary list of behaviors on an element during an event\n * @param {String} directive The name of the event, as described in layout.behaviors for this datalayer\n * @param {Object} behaviors An object describing the behavior to attach to this single element\n * @param {string} behaviors.action The name of the action that would trigger this behavior (eg click, mouseover, etc)\n * @param {string} behaviors.status What status to apply to the element when this behavior is triggered (highlighted,\n * selected, etc)\n * @param {string} [behaviors.exclusive] Whether triggering the event for this element should unset the relevant status\n * for all other elements. Useful for, eg, click events that exclusively highlight one thing.\n * @returns {function(this:LocusZoom.DataLayer)} Return a function that handles the event in context with the behavior\n * and the element- can be attached as an event listener\n */\nLocusZoom.DataLayer.prototype.executeBehaviors = function(directive, behaviors) {\n\n // Determine the required state of control and shift keys during the event\n var requiredKeyStates = {\n 'ctrl': (directive.indexOf('ctrl') !== -1),\n 'shift': (directive.indexOf('shift') !== -1)\n };\n\n return function(element) {\n\n // Do nothing if the required control and shift key presses (or lack thereof) doesn't match the event\n if (requiredKeyStates.ctrl !== !!d3.event.ctrlKey || requiredKeyStates.shift !== !!d3.event.shiftKey) { return; }\n\n // Loop through behaviors making each one go in succession\n behaviors.forEach(function(behavior) {\n\n // Route first by the action, if defined\n if (typeof behavior != 'object' || behavior === null) { return; }\n\n switch (behavior.action) {\n\n // Set a status (set to true regardless of current status, optionally with exclusivity)\n case 'set':\n this.setElementStatus(behavior.status, element, true, behavior.exclusive);\n break;\n\n // Unset a status (set to false regardless of current status, optionally with exclusivity)\n case 'unset':\n this.setElementStatus(behavior.status, element, false, behavior.exclusive);\n break;\n\n // Toggle a status\n case 'toggle':\n var current_status_boolean = (this.state[this.state_id][behavior.status].indexOf(this.getElementId(element)) !== -1);\n var exclusive = behavior.exclusive && !current_status_boolean;\n this.setElementStatus(behavior.status, element, !current_status_boolean, exclusive);\n break;\n\n // Link to a dynamic URL\n case 'link':\n if (typeof behavior.href == 'string') {\n var url = LocusZoom.parseFields(element, behavior.href);\n if (typeof behavior.target == 'string') {\n window.open(url, behavior.target);\n } else {\n window.location.href = url;\n }\n }\n break;\n\n // Action not defined, just return\n default:\n break;\n\n }\n\n return;\n\n }.bind(this));\n\n }.bind(this);\n\n};\n\n/**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\nLocusZoom.DataLayer.prototype.getPageOrigin = function() {\n var panel_origin = this.parent.getPageOrigin();\n return {\n x: panel_origin.x + this.parent.layout.margin.left,\n y: panel_origin.y + this.parent.layout.margin.top\n };\n};\n\n/**\n * Get a data layer's current underlying data in a standard format (e.g. JSON or CSV)\n * @param {('csv'|'tsv'|'json')} format How to export the data\n * @returns {*}\n */\nLocusZoom.DataLayer.prototype.exportData = function(format) {\n var default_format = 'json';\n format = format || default_format;\n format = (typeof format == 'string' ? format.toLowerCase() : default_format);\n if (['json','csv','tsv'].indexOf(format) === -1) { format = default_format; }\n var ret;\n switch (format) {\n case 'json':\n try {\n ret = JSON.stringify(this.data);\n } catch (e) {\n ret = null;\n console.warn('Unable to export JSON data from data layer: ' + this.getBaseId());\n console.error(e);\n }\n break;\n case 'tsv':\n case 'csv':\n try {\n var jsonified = JSON.parse(JSON.stringify(this.data));\n if (typeof jsonified != 'object') {\n ret = jsonified.toString();\n } else if (!Array.isArray(jsonified)) {\n ret = 'Object';\n } else {\n var delimiter = (format === 'tsv') ? '\\t' : ',';\n var header = this.layout.fields.map(function(header) {\n return JSON.stringify(header);\n }).join(delimiter) + '\\n';\n ret = header + jsonified.map(function(record) {\n return this.layout.fields.map(function(field) {\n if (typeof record[field] == 'undefined') {\n return JSON.stringify(null);\n } else if (typeof record[field] == 'object' && record[field] !== null) {\n return Array.isArray(record[field]) ? '\"[Array(' + record[field].length + ')]\"' : '\"[Object]\"';\n } else {\n return JSON.stringify(record[field]);\n }\n }).join(delimiter);\n }.bind(this)).join('\\n');\n }\n } catch (e) {\n ret = null;\n console.error('Unable to export CSV data from data layer: ' + this.getBaseId() + ';', e);\n }\n break;\n }\n return ret;\n};\n\n/**\n * Position the datalayer and all tooltips\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.draw = function() {\n this.svg.container.attr('transform', 'translate(' + this.parent.layout.cliparea.origin.x + ',' + this.parent.layout.cliparea.origin.y + ')');\n this.svg.clipRect\n .attr('width', this.parent.layout.cliparea.width)\n .attr('height', this.parent.layout.cliparea.height);\n this.positionAllTooltips();\n return this;\n};\n\n\n/**\n * Re-Map a data layer to reflect changes in the state of a plot (such as viewing region/ chromosome range)\n * @return {Promise}\n */\nLocusZoom.DataLayer.prototype.reMap = function() {\n this.destroyAllTooltips(); // hack - only non-visible tooltips should be destroyed\n // and then recreated if returning to visibility\n\n // Fetch new data. Datalayers are only given access to the final consolidated data from the chain (not headers or raw payloads)\n var promise = this.parent_plot.lzd.getData(this.state, this.layout.fields);\n promise.then(function(new_data) {\n this.data = new_data.body;\n this.applyDataMethods();\n this.initialized = true;\n }.bind(this));\n\n return promise;\n};\n\n\n/**\n * The central registry of known data layer definitions (which may be stored in separate files due to length)\n * @namespace\n */\nLocusZoom.DataLayers = (function() {\n var obj = {};\n var datalayers = {};\n /**\n * @name LocusZoom.DataLayers.get\n * @param {String} name The name of the datalayer\n * @param {Object} layout The configuration object for this data layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n * @returns {LocusZoom.DataLayer}\n */\n obj.get = function(name, layout, parent) {\n if (!name) {\n return null;\n } else if (datalayers[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for data layer [' + name + ']');\n } else {\n return new datalayers[name](layout, parent);\n }\n } else {\n throw new Error('data layer [' + name + '] not found');\n }\n };\n\n /**\n * @name LocusZoom.DataLayers.set\n * @protected\n * @param {String} name\n * @param {Function} datalayer Constructor for the datalayer\n */\n obj.set = function(name, datalayer) {\n if (datalayer) {\n if (typeof datalayer != 'function') {\n throw new Error('unable to set data layer [' + name + '], argument provided is not a function');\n } else {\n datalayers[name] = datalayer;\n datalayers[name].prototype = new LocusZoom.DataLayer();\n }\n } else {\n delete datalayers[name];\n }\n };\n\n /**\n * Add a new type of datalayer to the registry of known layer types\n * @name LocusZoom.DataLayers.add\n * @param {String} name The name of the data layer to register\n * @param {Function} datalayer\n */\n obj.add = function(name, datalayer) {\n if (datalayers[name]) {\n throw new Error('data layer already exists with name: ' + name);\n } else {\n obj.set(name, datalayer);\n }\n };\n\n /**\n * Register a new datalayer that inherits and extends basic behaviors from a known datalayer\n * @param {String} parent_name The name of the parent data layer whose behavior is to be extended\n * @param {String} name The name of the new datalayer to register\n * @param {Object} [overrides] Object of properties and methods to combine with the prototype of the parent datalayer\n * @returns {Function} The constructor for the new child class\n */\n obj.extend = function(parent_name, name, overrides) {\n // TODO: Consider exposing additional constructor argument, if there is a use case for very granular extension\n overrides = overrides || {};\n\n var parent = datalayers[parent_name];\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered datalayer type');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n // Bypass .set() because we want a layer of inheritance below `DataLayer`\n datalayers[name] = child;\n return child;\n };\n\n /**\n * List the names of all known datalayers\n * @name LocusZoom.DataLayers.list\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(datalayers);\n };\n\n return obj;\n})();\n","/* global LocusZoom */\n'use strict';\n\nvar LZ_SIG_THRESHOLD_LOGP = 7.301; // -log10(.05/1e6)\n\n/**\n * Manage known layouts for all parts of the LocusZoom plot\n *\n * This registry allows for layouts to be reused and customized many times on a page, using a common base pattern.\n * It handles the work of ensuring that each new instance of the layout has no shared state with other copies.\n *\n * @class\n */\nLocusZoom.Layouts = (function () {\n var obj = {};\n var layouts = {\n 'plot': {},\n 'panel': {},\n 'data_layer': {},\n 'dashboard': {},\n 'dashboard_components': {},\n 'tooltip': {}\n };\n\n /**\n * Generate a layout configuration object\n * @param {('plot'|'panel'|'data_layer'|'dashboard'|'tooltip')} type The type of layout to retrieve\n * @param {string} name Identifier of the predefined layout within the specified type\n * @param {object} [modifications] Custom properties that override default settings for this layout\n * @returns {object} A JSON-serializable object representation\n */\n obj.get = function (type, name, modifications) {\n if (typeof type != 'string' || typeof name != 'string') {\n throw new Error('invalid arguments passed to LocusZoom.Layouts.get, requires string (layout type) and string (layout name)');\n } else if (layouts[type][name]) {\n // Get the base layout\n var layout = LocusZoom.Layouts.merge(modifications || {}, layouts[type][name]);\n // If \"unnamespaced\" is true then strike that from the layout and return the layout without namespacing\n if (layout.unnamespaced) {\n delete layout.unnamespaced;\n return JSON.parse(JSON.stringify(layout));\n }\n // Determine the default namespace for namespaced values\n var default_namespace = '';\n if (typeof layout.namespace == 'string') {\n default_namespace = layout.namespace;\n } else if (typeof layout.namespace == 'object' && Object.keys(layout.namespace).length) {\n if (typeof layout.namespace.default != 'undefined') {\n default_namespace = layout.namespace.default;\n } else {\n default_namespace = layout.namespace[Object.keys(layout.namespace)[0]].toString();\n }\n }\n default_namespace += default_namespace.length ? ':' : '';\n // Apply namespaces to layout, recursively\n var applyNamespaces = function (element, namespace) {\n if (namespace) {\n if (typeof namespace == 'string') {\n namespace = { default: namespace };\n }\n } else {\n namespace = { default: '' };\n }\n if (typeof element == 'string') {\n var re = /\\{\\{namespace(\\[[A-Za-z_0-9]+\\]|)\\}\\}/g;\n var match, base, key, resolved_namespace;\n var replace = [];\n while ((match = re.exec(element)) !== null) {\n base = match[0];\n key = match[1].length ? match[1].replace(/(\\[|\\])/g, '') : null;\n resolved_namespace = default_namespace;\n if (namespace != null && typeof namespace == 'object' && typeof namespace[key] != 'undefined') {\n resolved_namespace = namespace[key] + (namespace[key].length ? ':' : '');\n }\n replace.push({ base: base, namespace: resolved_namespace });\n }\n for (var r in replace) {\n element = element.replace(replace[r].base, replace[r].namespace);\n }\n } else if (typeof element == 'object' && element != null) {\n if (typeof element.namespace != 'undefined') {\n var merge_namespace = (typeof element.namespace == 'string') ? { default: element.namespace } : element.namespace;\n namespace = LocusZoom.Layouts.merge(namespace, merge_namespace);\n }\n var namespaced_element, namespaced_property;\n for (var property in element) {\n if (property === 'namespace') {\n continue;\n }\n namespaced_element = applyNamespaces(element[property], namespace);\n namespaced_property = applyNamespaces(property, namespace);\n if (property !== namespaced_property) {\n delete element[property];\n }\n element[namespaced_property] = namespaced_element;\n }\n }\n return element;\n };\n layout = applyNamespaces(layout, layout.namespace);\n // Return the layout as valid JSON only\n return JSON.parse(JSON.stringify(layout));\n } else {\n throw new Error('layout type [' + type + '] name [' + name + '] not found');\n }\n };\n\n /** @private */\n obj.set = function (type, name, layout) {\n if (typeof type != 'string' || typeof name != 'string' || typeof layout != 'object') {\n throw new Error('unable to set new layout; bad arguments passed to set()');\n }\n if (!layouts[type]) {\n layouts[type] = {};\n }\n if (layout) {\n return (layouts[type][name] = JSON.parse(JSON.stringify(layout)));\n } else {\n delete layouts[type][name];\n return null;\n }\n };\n\n /**\n * Register a new layout definition by name.\n *\n * @param {string} type The type of layout to add. Usually, this will be one of the predefined LocusZoom types,\n * but if you pass a different name, this method will automatically create the new `type` bucket\n * @param {string} name The identifier of the newly added layout\n * @param {object} [layout] A JSON-serializable object containing configuration properties for this layout\n * @returns The JSON representation of the newly created layout\n */\n obj.add = function (type, name, layout) {\n return obj.set(type, name, layout);\n };\n\n /**\n * List all registered layouts\n * @param [type] Optionally narrow the list to only layouts of a specific type; else return all known layouts\n * @returns {*}\n */\n obj.list = function (type) {\n if (!layouts[type]) {\n var list = {};\n Object.keys(layouts).forEach(function (type) {\n list[type] = Object.keys(layouts[type]);\n });\n return list;\n } else {\n return Object.keys(layouts[type]);\n }\n };\n\n /**\n * A helper method used for merging two objects. If a key is present in both, takes the value from the first object\n * Values from `default_layout` will be cleanly copied over, ensuring no references or shared state.\n *\n * Frequently used for preparing custom layouts. Both objects should be JSON-serializable.\n *\n * @param {object} custom_layout An object containing configuration parameters that override or add to defaults\n * @param {object} default_layout An object containing default settings.\n * @returns {object} The custom layout is modified in place and also returned from this method.\n */\n obj.merge = function (custom_layout, default_layout) {\n if (typeof custom_layout !== 'object' || typeof default_layout !== 'object') {\n throw new Error('LocusZoom.Layouts.merge only accepts two layout objects; ' + (typeof custom_layout) + ', ' + (typeof default_layout) + ' given');\n }\n for (var property in default_layout) {\n if (!default_layout.hasOwnProperty(property)) {\n continue;\n }\n // Get types for comparison. Treat nulls in the custom layout as undefined for simplicity.\n // (javascript treats nulls as \"object\" when we just want to overwrite them as if they're undefined)\n // Also separate arrays from objects as a discrete type.\n var custom_type = custom_layout[property] === null ? 'undefined' : typeof custom_layout[property];\n var default_type = typeof default_layout[property];\n if (custom_type === 'object' && Array.isArray(custom_layout[property])) {\n custom_type = 'array';\n }\n if (default_type === 'object' && Array.isArray(default_layout[property])) {\n default_type = 'array';\n }\n // Unsupported property types: throw an exception\n if (custom_type === 'function' || default_type === 'function') {\n throw new Error('LocusZoom.Layouts.merge encountered an unsupported property type');\n }\n // Undefined custom value: pull the default value\n if (custom_type === 'undefined') {\n custom_layout[property] = JSON.parse(JSON.stringify(default_layout[property]));\n continue;\n }\n // Both values are objects: merge recursively\n if (custom_type === 'object' && default_type === 'object') {\n custom_layout[property] = LocusZoom.Layouts.merge(custom_layout[property], default_layout[property]);\n continue;\n }\n }\n return custom_layout;\n };\n\n return obj;\n})();\n\n\n/**\n * Tooltip Layouts\n * @namespace LocusZoom.Layouts.tooltips\n */\n\nLocusZoom.Layouts.add('tooltip', 'standard_association', {\n namespace: { 'assoc': 'assoc' },\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[assoc]}}variant|htmlescape}}
'\n + 'P Value: {{{{namespace[assoc]}}log_pvalue|logtoscinotation|htmlescape}}
'\n + 'Ref. Allele: {{{{namespace[assoc]}}ref_allele|htmlescape}}
'\n + 'Make LD Reference
'\n});\n\nLocusZoom.Layouts.add('tooltip', 'covariates_model_association', function () {\n var covariates_model_association = LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true });\n covariates_model_association.html += 'Condition on Variant
';\n return covariates_model_association;\n}());\n\nLocusZoom.Layouts.add('tooltip', 'standard_genes', {\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '

{{gene_name|htmlescape}}

'\n + 'Gene ID: {{gene_id|htmlescape}}
'\n + 'Transcript ID: {{transcript_id|htmlescape}}
'\n + 'More data on gnomAD'\n});\n\nLocusZoom.Layouts.add('tooltip', 'standard_intervals', {\n namespace: { 'intervals': 'intervals' },\n closable: false,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[intervals]}}state_name|htmlescape}}
{{{{namespace[intervals]}}start|htmlescape}}-{{{{namespace[intervals]}}end|htmlescape}}'\n});\n\nLocusZoom.Layouts.add('tooltip', 'catalog_variant', {\n namespace: { 'assoc': 'assoc', 'catalog': 'catalog' },\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[catalog]}}variant|htmlescape}}
'\n + 'Catalog entries: {{n_catalog_matches|htmlescape}}
'\n + 'Top Trait: {{{{namespace[catalog]}}trait|htmlescape}}
'\n + 'Top P Value: {{{{namespace[catalog]}}log_pvalue|logtoscinotation}}
'\n // User note: if a different catalog is used, the tooltip will need to be replaced with a different link URL\n + 'More: GWAS catalog / dbSNP'\n});\n\n/**\n * Data Layer Layouts: represent specific information from a data source\n * @namespace Layouts.data_layer\n */\n\nLocusZoom.Layouts.add('data_layer', 'significance', {\n id: 'significance',\n type: 'orthogonal_line',\n orientation: 'horizontal',\n offset: LZ_SIG_THRESHOLD_LOGP\n});\n\nLocusZoom.Layouts.add('data_layer', 'recomb_rate', {\n namespace: { 'recomb': 'recomb' },\n id: 'recombrate',\n type: 'line',\n fields: ['{{namespace[recomb]}}position', '{{namespace[recomb]}}recomb_rate'],\n z_index: 1,\n style: {\n 'stroke': '#0000FF',\n 'stroke-width': '1.5px'\n },\n x_axis: {\n field: '{{namespace[recomb]}}position'\n },\n y_axis: {\n axis: 2,\n field: '{{namespace[recomb]}}recomb_rate',\n floor: 0,\n ceiling: 100\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'association_pvalues', {\n namespace: { 'assoc': 'assoc', 'ld': 'ld' },\n id: 'associationpvalues',\n type: 'scatter',\n point_shape: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 'diamond',\n else: 'circle'\n }\n },\n point_size: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 80,\n else: 40\n }\n },\n color: [\n {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: '#9632b8'\n }\n },\n {\n scale_function: 'numerical_bin',\n field: '{{namespace[ld]}}state',\n parameters: {\n breaks: [0, 0.2, 0.4, 0.6, 0.8],\n values: ['#357ebd', '#46b8da', '#5cb85c', '#eea236', '#d43f3a']\n }\n },\n '#B8B8B8'\n ],\n legend: [\n { shape: 'diamond', color: '#9632b8', size: 40, label: 'LD Ref Var', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#d43f3a', size: 40, label: '1.0 > r² ≥ 0.8', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#eea236', size: 40, label: '0.8 > r² ≥ 0.6', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#5cb85c', size: 40, label: '0.6 > r² ≥ 0.4', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#46b8da', size: 40, label: '0.4 > r² ≥ 0.2', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#357ebd', size: 40, label: '0.2 > r² ≥ 0.0', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#B8B8B8', size: 40, label: 'no r² data', class: 'lz-data_layer-scatter' }\n ],\n label: null,\n fields: ['{{namespace[assoc]}}variant', '{{namespace[assoc]}}position', '{{namespace[assoc]}}log_pvalue', '{{namespace[assoc]}}log_pvalue|logtoscinotation', '{{namespace[assoc]}}ref_allele', '{{namespace[ld]}}state', '{{namespace[ld]}}isrefvar'],\n id_field: '{{namespace[assoc]}}variant',\n z_index: 2,\n x_axis: {\n field: '{{namespace[assoc]}}position'\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[assoc]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.10,\n min_extent: [0, 10]\n },\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'association_pvalues_catalog', function () {\n // Slightly modify an existing layout\n var l = LocusZoom.Layouts.get('data_layer', 'association_pvalues', {\n unnamespaced: true,\n id: 'associationpvaluescatalog',\n fill_opacity: 0.7\n });\n l.tooltip.html += '{{#if {{namespace[catalog]}}rsid}}
See hits in GWAS catalog{{/if}}';\n l.namespace.catalog = 'catalog';\n l.fields.push('{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait', '{{namespace[catalog]}}log_pvalue');\n return l;\n}());\n\nLocusZoom.Layouts.add('data_layer', 'phewas_pvalues', {\n namespace: { 'phewas': 'phewas' },\n id: 'phewaspvalues',\n type: 'category_scatter',\n point_shape: 'circle',\n point_size: 70,\n tooltip_positioning: 'vertical',\n id_field: '{{namespace[phewas]}}id',\n fields: ['{{namespace[phewas]}}id', '{{namespace[phewas]}}log_pvalue', '{{namespace[phewas]}}trait_group', '{{namespace[phewas]}}trait_label'],\n x_axis: {\n field: '{{namespace[phewas]}}x', // Synthetic/derived field added by `category_scatter` layer\n category_field: '{{namespace[phewas]}}trait_group',\n lower_buffer: 0.025,\n upper_buffer: 0.025\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[phewas]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.15\n },\n color: [{\n field: '{{namespace[phewas]}}trait_group',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [],\n values: [],\n null_value: '#B8B8B8'\n }\n }],\n fill_opacity: 0.7,\n tooltip: {\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: [\n 'Trait: {{{{namespace[phewas]}}trait_label|htmlescape}}
',\n 'Trait Category: {{{{namespace[phewas]}}trait_group|htmlescape}}
',\n 'P-value: {{{{namespace[phewas]}}log_pvalue|logtoscinotation|htmlescape}}
'\n ].join('')\n },\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n label: {\n text: '{{{{namespace[phewas]}}trait_label|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n {\n field: '{{namespace[phewas]}}log_pvalue',\n operator: '>=',\n value: 20\n }\n ],\n style: {\n 'font-size': '14px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'genes', {\n namespace: { 'gene': 'gene' },\n id: 'genes',\n type: 'genes',\n fields: ['{{namespace[gene]}}all'],\n id_field: 'gene_id',\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_genes', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'genome_legend', {\n namespace: { 'genome': 'genome' },\n id: 'genome_legend',\n type: 'genome_legend',\n fields: ['{{namespace[genome]}}chr', '{{namespace[genome]}}base_pairs'],\n x_axis: {\n floor: 0,\n ceiling: 2881033286\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'intervals', {\n namespace: { 'intervals': 'intervals' },\n id: 'intervals',\n type: 'intervals',\n fields: ['{{namespace[intervals]}}start', '{{namespace[intervals]}}end', '{{namespace[intervals]}}state_id', '{{namespace[intervals]}}state_name'],\n id_field: '{{namespace[intervals]}}start',\n start_field: '{{namespace[intervals]}}start',\n end_field: '{{namespace[intervals]}}end',\n track_split_field: '{{namespace[intervals]}}state_id',\n split_tracks: true,\n always_hide_legend: false,\n color: {\n field: '{{namespace[intervals]}}state_id',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],\n values: ['rgb(212,63,58)', 'rgb(250,120,105)', 'rgb(252,168,139)', 'rgb(240,189,66)', 'rgb(250,224,105)', 'rgb(240,238,84)', 'rgb(244,252,23)', 'rgb(23,232,252)', 'rgb(32,191,17)', 'rgb(23,166,77)', 'rgb(32,191,17)', 'rgb(162,133,166)', 'rgb(212,212,212)'],\n null_value: '#B8B8B8'\n }\n },\n legend: [\n { shape: 'rect', color: 'rgb(212,63,58)', width: 9, label: 'Active Promoter', '{{namespace[intervals]}}state_id': 1 },\n { shape: 'rect', color: 'rgb(250,120,105)', width: 9, label: 'Weak Promoter', '{{namespace[intervals]}}state_id': 2 },\n { shape: 'rect', color: 'rgb(252,168,139)', width: 9, label: 'Poised Promoter', '{{namespace[intervals]}}state_id': 3 },\n { shape: 'rect', color: 'rgb(240,189,66)', width: 9, label: 'Strong enhancer', '{{namespace[intervals]}}state_id': 4 },\n { shape: 'rect', color: 'rgb(250,224,105)', width: 9, label: 'Strong enhancer', '{{namespace[intervals]}}state_id': 5 },\n { shape: 'rect', color: 'rgb(240,238,84)', width: 9, label: 'Weak enhancer', '{{namespace[intervals]}}state_id': 6 },\n { shape: 'rect', color: 'rgb(244,252,23)', width: 9, label: 'Weak enhancer', '{{namespace[intervals]}}state_id': 7 },\n { shape: 'rect', color: 'rgb(23,232,252)', width: 9, label: 'Insulator', '{{namespace[intervals]}}state_id': 8 },\n { shape: 'rect', color: 'rgb(32,191,17)', width: 9, label: 'Transcriptional transition', '{{namespace[intervals]}}state_id': 9 },\n { shape: 'rect', color: 'rgb(23,166,77)', width: 9, label: 'Transcriptional elongation', '{{namespace[intervals]}}state_id': 10 },\n { shape: 'rect', color: 'rgb(136,240,129)', width: 9, label: 'Weak transcribed', '{{namespace[intervals]}}state_id': 11 },\n { shape: 'rect', color: 'rgb(162,133,166)', width: 9, label: 'Polycomb-repressed', '{{namespace[intervals]}}state_id': 12 },\n { shape: 'rect', color: 'rgb(212,212,212)', width: 9, label: 'Heterochromatin / low signal', '{{namespace[intervals]}}state_id': 13 }\n ],\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_intervals', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'annotation_catalog', {\n // Identify GWAS hits that are present in the GWAS catalog\n namespace: { 'assoc': 'assoc', 'catalog': 'catalog' },\n id: 'annotation_catalog',\n type: 'annotation_track',\n id_field: '{{namespace[catalog]}}variant',\n x_axis: {\n field: '{{namespace[assoc]}}position'\n },\n color: '#0000CC',\n fields: [\n '{{namespace[assoc]}}variant', '{{namespace[assoc]}}chromosome', '{{namespace[assoc]}}position',\n '{{namespace[catalog]}}variant', '{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait',\n '{{namespace[catalog]}}log_pvalue', '{{namespace[catalog]}}pos'\n ],\n filters: [\n // Specify which points to show on the track. Any selection must satisfy ALL filters\n ['{{namespace[catalog]}}rsid', '!=', null],\n ['{{namespace[catalog]}}log_pvalue', '>', LZ_SIG_THRESHOLD_LOGP]\n ],\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'catalog_variant', { unnamespaced: true }),\n tooltip_positioning: 'top'\n});\n\n/**\n * Individual dashboard buttons\n * @namespace Layouts.dashboard_components\n */\nLocusZoom.Layouts.add('dashboard_components', 'ldlz2_pop_selector', {\n // **Note**: this widget is aimed at the LDLZ2 datasource, and the UM 1000G LDServer. Older LZ usages\n // (on the original LD data source) will not work with these population names.\n type: 'set_state',\n position: 'right',\n color: 'blue',\n button_html: 'LD Population: ',\n show_selected: true,\n button_title: 'Select LD Population: ',\n state_field: 'ld_pop',\n // This list below is hardcoded to work with the UMich LDServer, default 1000G populations\n // It can be customized to work with other LD servers that specify population differently\n // https://portaldev.sph.umich.edu/ld/genome_builds/GRCh37/references/1000G/populations\n options: [\n { display_name: 'ALL (default)', value: 'ALL' },\n { display_name: 'AFR', value: 'AFR' },\n { display_name: 'AMR', value: 'AMR' },\n { display_name: 'EAS', value: 'EAS' },\n { display_name: 'EUR', value: 'EUR' },\n { display_name: 'SAS', value: 'SAS' }\n ]\n});\n\n/**\n * Dashboard Layouts: Collections of toolbar buttons etc\n * @namespace Layouts.dashboard\n */\nLocusZoom.Layouts.add('dashboard', 'standard_panel', {\n components: [\n {\n type: 'remove_panel',\n position: 'right',\n color: 'red',\n group_position: 'end'\n },\n {\n type: 'move_panel_up',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'move_panel_down',\n position: 'right',\n group_position: 'start',\n style: { 'margin-left': '0.75em' }\n }\n ]\n});\n\nLocusZoom.Layouts.add('dashboard', 'standard_plot', {\n components: [\n {\n type: 'title',\n title: 'LocusZoom',\n subtitle: 'v' + LocusZoom.version + '',\n position: 'left'\n },\n {\n type: 'download',\n position: 'right'\n }\n ]\n});\n\nLocusZoom.Layouts.add('dashboard', 'covariates_model_plot', function () {\n var covariates_model_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n covariates_model_plot_dashboard.components.push({\n type: 'covariates_model',\n button_html: 'Model',\n button_title: 'Show and edit covariates currently in model',\n position: 'left'\n });\n return covariates_model_plot_dashboard;\n}());\n\nLocusZoom.Layouts.add('dashboard', 'region_nav_plot', function () {\n var region_nav_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n region_nav_plot_dashboard.components.push(\n {\n type: 'shift_region',\n step: 500000,\n button_html: '>>',\n position: 'right',\n group_position: 'end'\n }, {\n type: 'shift_region',\n step: 50000,\n button_html: '>',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'zoom_region',\n step: 0.2,\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'zoom_region',\n step: -0.2,\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'shift_region',\n step: -50000,\n button_html: '<',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'shift_region',\n step: -500000,\n button_html: '<<',\n position: 'right',\n group_position: 'start'\n }\n );\n return region_nav_plot_dashboard;\n}());\n\n/**\n * Panel Layouts\n * @namespace Layouts.panel\n */\n\nLocusZoom.Layouts.add('panel', 'association', {\n id: 'association',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 200,\n proportional_width: 1,\n margin: { top: 35, right: 50, bottom: 40, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_legend',\n position: 'right'\n });\n return l;\n })(),\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n },\n y2: {\n label: 'Recombination Rate (cM/Mb)',\n label_offset: 40\n }\n },\n legend: {\n orientation: 'vertical',\n origin: { x: 55, y: 40 },\n hidden: true\n },\n interaction: {\n drag_background_to_pan: true,\n drag_x_ticks_to_scale: true,\n drag_y1_ticks_to_scale: true,\n drag_y2_ticks_to_scale: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'association_catalog', function () {\n var l = LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n id: 'associationcatalog',\n namespace: { 'assoc': 'assoc', 'ld': 'ld', 'catalog': 'catalog' } // Required to resolve display options\n });\n l.dashboard.components.push({\n type: 'display_options',\n position: 'right',\n color: 'blue',\n // Below: special config specific to this widget\n button_html: 'Display options...',\n button_title: 'Control how plot items are displayed',\n\n layer_name: 'associationpvaluescatalog',\n default_config_display_name: 'No catalog labels (default)', // display name for the default plot color option (allow user to revert to plot defaults)\n\n options: [\n {\n // First dropdown menu item\n display_name: 'Label catalog traits', // Human readable representation of field name\n display: { // Specify layout directives that control display of the plot for this option\n label: {\n text: '{{{{namespace[catalog]}}trait|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n // Only label points if they are significant for some trait in the catalog, AND in high LD\n // with the top hit of interest\n {\n field: '{{namespace[catalog]}}trait',\n operator: '!=',\n value: null\n },\n {\n field: '{{namespace[catalog]}}log_pvalue',\n operator: '>',\n value: LZ_SIG_THRESHOLD_LOGP\n },\n {\n field: '{{namespace[ld]}}state',\n operator: '>',\n value: 0.4\n },\n ],\n style: {\n 'font-size': '10px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n }\n }\n ]\n });\n l.data_layers = [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues_catalog', { unnamespaced: true })\n ];\n return l;\n}());\n\nLocusZoom.Layouts.add('panel', 'genes', {\n id: 'genes',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 112.5,\n proportional_width: 1,\n margin: { top: 20, right: 50, bottom: 20, left: 50 },\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'resize_to_data',\n position: 'right',\n button_html: 'Show all genes',\n });\n return l;\n })(),\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'genes', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'phewas', {\n id: 'phewas',\n width: 800,\n height: 300,\n min_width: 800,\n min_height: 300,\n proportional_width: 1,\n margin: { top: 20, right: 50, bottom: 120, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n axes: {\n x: {\n ticks: { // Object based config (shared defaults; allow layers to specify ticks)\n style: {\n 'font-weight': 'bold',\n 'font-size': '11px',\n 'text-anchor': 'start'\n },\n transform: 'rotate(50)',\n position: 'left' // Special param recognized by `category_scatter` layers\n }\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'phewas_pvalues', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'genome_legend', {\n id: 'genome_legend',\n width: 800,\n height: 50,\n origin: { x: 0, y: 300 },\n min_width: 800,\n min_height: 50,\n proportional_width: 1,\n margin: { top: 0, right: 50, bottom: 35, left: 50 },\n axes: {\n x: {\n label: 'Genomic Position (number denotes chromosome)',\n label_offset: 35,\n ticks: [\n {\n x: 124625310,\n text: '1',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 370850307,\n text: '2',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 591461209,\n text: '3',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 786049562,\n text: '4',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 972084330,\n text: '5',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1148099493,\n text: '6',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1313226358,\n text: '7',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1465977701,\n text: '8',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1609766427,\n text: '9',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1748140516,\n text: '10',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1883411148,\n text: '11',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2017840353,\n text: '12',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2142351240,\n text: '13',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2253610949,\n text: '14',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2358551415,\n text: '15',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2454994487,\n text: '16',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2540769469,\n text: '17',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2620405698,\n text: '18',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2689008813,\n text: '19',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2750086065,\n text: '20',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2805663772,\n text: '21',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2855381003,\n text: '22',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n }\n ]\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'genome_legend', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'intervals', {\n id: 'intervals',\n width: 1000,\n height: 50,\n min_width: 500,\n min_height: 50,\n margin: { top: 25, right: 150, bottom: 5, left: 50 },\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_split_tracks',\n data_layer_id: 'intervals',\n position: 'right'\n });\n return l;\n })(),\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n legend: {\n hidden: true,\n orientation: 'horizontal',\n origin: { x: 50, y: 0 },\n pad_from_bottom: 5\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'intervals', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'annotation_catalog', {\n id: 'annotationcatalog',\n width: 800,\n height: 50,\n min_height: 50,\n proportional_width: 1,\n margin: { top: 25, right: 50, bottom: 0, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true }),\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'annotation_catalog', { unnamespaced: true })\n ]\n});\n\n/**\n * Plot Layouts\n * @namespace Layouts.plot\n */\n\nLocusZoom.Layouts.add('plot', 'standard_association', {\n state: {},\n width: 800,\n height: 450,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', { unnamespaced: true, proportional_height: 0.5 }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true, proportional_height: 0.5 })\n ]\n});\n\nLocusZoom.Layouts.add('plot', 'association_catalog', {\n state: {},\n width: 800,\n height: 500,\n responsive_resize: 'width_only',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'annotation_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'association_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true })\n ]\n});\n\n// Shortcut to \"StandardLayout\" for backward compatibility\nLocusZoom.StandardLayout = LocusZoom.Layouts.get('plot', 'standard_association');\n\nLocusZoom.Layouts.add('plot', 'standard_phewas', {\n width: 800,\n height: 600,\n min_width: 800,\n min_height: 600,\n responsive_resize: 'both',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'phewas', { unnamespaced: true, proportional_height: 0.45 }),\n LocusZoom.Layouts.get('panel', 'genome_legend', { unnamespaced: true, proportional_height: 0.1 }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true, proportional_height: 0.45,\n margin: { bottom: 40 },\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n }\n }\n })\n ],\n mouse_guide: false\n});\n\nLocusZoom.Layouts.add('plot', 'interval_association', {\n state: {},\n width: 800,\n height: 550,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n width: 800,\n proportional_height: (225 / 570)\n }),\n LocusZoom.Layouts.get('panel', 'intervals', { unnamespaced: true, proportional_height: (120 / 570) }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true, width: 800, proportional_height: (225 / 570) })\n ]\n});\n","/**\n * @namespace\n */\nvar LocusZoom = {\n version: '0.10.0'\n};\n\n/**\n * Populate a single element with a LocusZoom plot.\n * selector can be a string for a DOM Query or a d3 selector.\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot} The newly created plot instance\n */\nLocusZoom.populate = function(selector, datasource, layout) {\n if (typeof selector == 'undefined') {\n throw new Error('LocusZoom.populate selector not defined');\n }\n // Empty the selector of any existing content\n d3.select(selector).html('');\n var plot;\n d3.select(selector).call(function() {\n // Require each containing element have an ID. If one isn't present, create one.\n if (typeof this.node().id == 'undefined') {\n var iterator = 0;\n while (!d3.select('#lz-' + iterator).empty()) { iterator++; }\n this.attr('id', '#lz-' + iterator);\n }\n // Create the plot\n plot = new LocusZoom.Plot(this.node().id, datasource, layout);\n plot.container = this.node();\n // Detect data-region and fill in state values if present\n if (typeof this.node().dataset !== 'undefined' && typeof this.node().dataset.region !== 'undefined') {\n var parsed_state = LocusZoom.parsePositionQuery(this.node().dataset.region);\n Object.keys(parsed_state).forEach(function(key) {\n plot.state[key] = parsed_state[key];\n });\n }\n // Add an SVG to the div and set its dimensions\n plot.svg = d3.select('div#' + plot.id)\n .append('svg')\n .attr('version', '1.1')\n .attr('xmlns', 'http://www.w3.org/2000/svg')\n .attr('id', plot.id + '_svg').attr('class', 'lz-locuszoom')\n .style(plot.layout.style);\n plot.setDimensions();\n plot.positionPanels();\n // Initialize the plot\n plot.initialize();\n // If the plot has defined data sources then trigger its first mapping based on state values\n if (typeof datasource == 'object' && Object.keys(datasource).length) {\n plot.refresh();\n }\n });\n return plot;\n};\n\n/**\n * Populate arbitrarily many elements each with a LocusZoom plot\n * using a common datasource and layout\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot[]}\n */\nLocusZoom.populateAll = function(selector, datasource, layout) {\n var plots = [];\n d3.selectAll(selector).each(function(d,i) {\n plots[i] = LocusZoom.populate(this, datasource, layout);\n });\n return plots;\n};\n\n/**\n * Convert an integer chromosome position to an SI string representation (e.g. 23423456 => \"23.42\" (Mb))\n * @param {Number} pos Position\n * @param {Number} [exp] Exponent to use for the returned string, eg 6=> MB. If not specified, will attempt to guess\n * the most appropriate SI prefix based on the number provided.\n * @param {Boolean} [suffix=false] Whether or not to append a suffix (e.g. \"Mb\") to the end of the returned string\n * @returns {string}\n */\nLocusZoom.positionIntToString = function(pos, exp, suffix) {\n var exp_symbols = { 0: '', 3: 'K', 6: 'M', 9: 'G' };\n suffix = suffix || false;\n if (isNaN(exp) || exp === null) {\n var log = Math.log(pos) / Math.LN10;\n exp = Math.min(Math.max(log - (log % 3), 0), 9);\n }\n var places_exp = exp - Math.floor((Math.log(pos) / Math.LN10).toFixed(exp + 3));\n var min_exp = Math.min(Math.max(exp, 0), 2);\n var places = Math.min(Math.max(places_exp, min_exp), 12);\n var ret = '' + (pos / Math.pow(10, exp)).toFixed(places);\n if (suffix && typeof exp_symbols[exp] !== 'undefined') {\n ret += ' ' + exp_symbols[exp] + 'b';\n }\n return ret;\n};\n\n/**\n * Convert an SI string chromosome position to an integer representation (e.g. \"5.8 Mb\" => 58000000)\n * @param {String} p The chromosome position\n * @returns {Number}\n */\nLocusZoom.positionStringToInt = function(p) {\n var val = p.toUpperCase();\n val = val.replace(/,/g, '');\n var suffixre = /([KMG])[B]*$/;\n var suffix = suffixre.exec(val);\n var mult = 1;\n if (suffix) {\n if (suffix[1] === 'M') {\n mult = 1e6;\n } else if (suffix[1] === 'G') {\n mult = 1e9;\n } else {\n mult = 1e3; //K\n }\n val = val.replace(suffixre,'');\n }\n val = Number(val) * mult;\n return val;\n};\n\n/**\n * Parse region queries into their constituent parts\n * TODO: handle genes (or send off to API)\n * @param {String} x A chromosome position query. May be any of the forms `chr:start-end`, `chr:center+offset`,\n * or `chr:pos`\n * @returns {{chr:*, start: *, end:*} | {chr:*, position:*}}\n */\nLocusZoom.parsePositionQuery = function(x) {\n var chrposoff = /^(\\w+):([\\d,.]+[kmgbKMGB]*)([-+])([\\d,.]+[kmgbKMGB]*)$/;\n var chrpos = /^(\\w+):([\\d,.]+[kmgbKMGB]*)$/;\n var match = chrposoff.exec(x);\n if (match) {\n if (match[3] === '+') {\n var center = LocusZoom.positionStringToInt(match[2]);\n var offset = LocusZoom.positionStringToInt(match[4]);\n return {\n chr:match[1],\n start: center - offset,\n end: center + offset\n };\n } else {\n return {\n chr: match[1],\n start: LocusZoom.positionStringToInt(match[2]),\n end: LocusZoom.positionStringToInt(match[4])\n };\n }\n }\n match = chrpos.exec(x);\n if (match) {\n return {\n chr:match[1],\n position: LocusZoom.positionStringToInt(match[2])\n };\n }\n return null;\n};\n\n/**\n * Generate a \"pretty\" set of ticks (multiples of 1, 2, or 5 on the same order of magnitude for the range)\n * Based on R's \"pretty\" function: https://github.com/wch/r-source/blob/b156e3a711967f58131e23c1b1dc1ea90e2f0c43/src/appl/pretty.c\n * @param {Number[]} range A two-item array specifying [low, high] values for the axis range\n * @param {('low'|'high'|'both'|'neither')} [clip_range='neither'] What to do if first and last generated ticks extend\n * beyond the range. Set this to \"low\", \"high\", \"both\", or \"neither\" to clip the first (low) or last (high) tick to\n * be inside the range or allow them to extend beyond.\n * e.g. \"low\" will clip the first (low) tick if it extends beyond the low end of the range but allow the\n * last (high) tick to extend beyond the range. \"both\" clips both ends, \"neither\" allows both to extend beyond.\n * @param {Number} [target_tick_count=5] The approximate number of ticks you would like to be returned; may not be exact\n * @returns {Number[]}\n */\nLocusZoom.prettyTicks = function(range, clip_range, target_tick_count) {\n if (typeof target_tick_count == 'undefined' || isNaN(parseInt(target_tick_count))) {\n target_tick_count = 5;\n }\n target_tick_count = parseInt(target_tick_count);\n\n var min_n = target_tick_count / 3;\n var shrink_sml = 0.75;\n var high_u_bias = 1.5;\n var u5_bias = 0.5 + 1.5 * high_u_bias;\n\n var d = Math.abs(range[0] - range[1]);\n var c = d / target_tick_count;\n if ((Math.log(d) / Math.LN10) < -2) {\n c = (Math.max(Math.abs(d)) * shrink_sml) / min_n;\n }\n\n var base = Math.pow(10, Math.floor(Math.log(c) / Math.LN10));\n var base_toFixed = 0;\n if (base < 1 && base !== 0) {\n base_toFixed = Math.abs(Math.round(Math.log(base) / Math.LN10));\n }\n\n var unit = base;\n if ( ((2 * base) - c) < (high_u_bias * (c - unit)) ) {\n unit = 2 * base;\n if ( ((5 * base) - c) < (u5_bias * (c - unit)) ) {\n unit = 5 * base;\n if ( ((10 * base) - c) < (high_u_bias * (c - unit)) ) {\n unit = 10 * base;\n }\n }\n }\n\n var ticks = [];\n var i = parseFloat( (Math.floor(range[0] / unit) * unit).toFixed(base_toFixed) );\n while (i < range[1]) {\n ticks.push(i);\n i += unit;\n if (base_toFixed > 0) {\n i = parseFloat(i.toFixed(base_toFixed));\n }\n }\n ticks.push(i);\n\n if (typeof clip_range == 'undefined' || ['low', 'high', 'both', 'neither'].indexOf(clip_range) === -1) {\n clip_range = 'neither';\n }\n if (clip_range === 'low' || clip_range === 'both') {\n if (ticks[0] < range[0]) { ticks = ticks.slice(1); }\n }\n if (clip_range === 'high' || clip_range === 'both') {\n if (ticks[ticks.length - 1] > range[1]) { ticks.pop(); }\n }\n\n return ticks;\n};\n\n/**\n * Make an AJAX request and return a promise.\n * From http://www.html5rocks.com/en/tutorials/cors/\n * and with promises from https://gist.github.com/kriskowal/593076\n *\n * @param {String} method The HTTP verb\n * @param {String} url\n * @param {String} [body] The request body to send to the server\n * @param {Object} [headers] Object of custom request headers\n * @param {Number} [timeout] If provided, wait this long (in ms) before timing out\n * @returns {Promise}\n */\nLocusZoom.createCORSPromise = function (method, url, body, headers, timeout) {\n return new Promise(function (resolve, reject) {\n var xhr = new XMLHttpRequest();\n if ('withCredentials' in xhr) {\n // Check if the XMLHttpRequest object has a \"withCredentials\" property.\n // \"withCredentials\" only exists on XMLHTTPRequest2 objects.\n xhr.open(method, url, true);\n } else if (typeof XDomainRequest != 'undefined') {\n // Otherwise, check if XDomainRequest.\n // XDomainRequest only exists in IE, and is IE's way of making CORS requests.\n xhr = new XDomainRequest();\n xhr.open(method, url);\n } else {\n // Otherwise, CORS is not supported by the browser.\n xhr = null;\n }\n if (xhr) {\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4) {\n if (xhr.status === 200 || xhr.status === 0 ) {\n resolve(xhr.response);\n } else {\n reject('HTTP ' + xhr.status + ' for ' + url);\n }\n }\n };\n timeout && setTimeout(reject, timeout);\n body = typeof body !== 'undefined' ? body : '';\n if (typeof headers !== 'undefined') {\n for (var header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n }\n // Send the request\n xhr.send(body);\n }\n });\n};\n\n/**\n * Validate a (presumed complete) plot state object against internal rules for consistency, and ensure the plot fits\n * within any constraints imposed by the layout.\n * @param {Object} new_state\n * @param {Number} new_state.start\n * @param {Number} new_state.end\n * @param {Object} layout\n * @returns {*|{}}\n */\nLocusZoom.validateState = function(new_state, layout) {\n\n new_state = new_state || {};\n layout = layout || {};\n\n // If a \"chr\", \"start\", and \"end\" are present then resolve start and end\n // to numeric values that are not decimal, negative, or flipped\n var validated_region = false;\n if (typeof new_state.chr != 'undefined' && typeof new_state.start != 'undefined' && typeof new_state.end != 'undefined') {\n // Determine a numeric scale and midpoint for the attempted region,\n var attempted_midpoint = null; var attempted_scale;\n new_state.start = Math.max(parseInt(new_state.start), 1);\n new_state.end = Math.max(parseInt(new_state.end), 1);\n if (isNaN(new_state.start) && isNaN(new_state.end)) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_midpoint = 0.5;\n attempted_scale = 0;\n } else if (isNaN(new_state.start) || isNaN(new_state.end)) {\n attempted_midpoint = new_state.start || new_state.end;\n attempted_scale = 0;\n new_state.start = (isNaN(new_state.start) ? new_state.end : new_state.start);\n new_state.end = (isNaN(new_state.end) ? new_state.start : new_state.end);\n } else {\n attempted_midpoint = Math.round((new_state.start + new_state.end) / 2);\n attempted_scale = new_state.end - new_state.start;\n if (attempted_scale < 0) {\n var temp = new_state.start;\n new_state.end = new_state.start;\n new_state.start = temp;\n attempted_scale = new_state.end - new_state.start;\n }\n if (attempted_midpoint < 0) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_scale = 0;\n }\n }\n validated_region = true;\n }\n\n // Constrain w/r/t layout-defined minimum region scale\n if (!isNaN(layout.min_region_scale) && validated_region && attempted_scale < layout.min_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.min_region_scale / 2), 1);\n new_state.end = new_state.start + layout.min_region_scale;\n }\n\n // Constrain w/r/t layout-defined maximum region scale\n if (!isNaN(layout.max_region_scale) && validated_region && attempted_scale > layout.max_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.max_region_scale / 2), 1);\n new_state.end = new_state.start + layout.max_region_scale;\n }\n\n return new_state;\n};\n\n//\n/**\n * Replace placeholders in an html string with field values defined in a data object\n * Only works on scalar values! Will ignore non-scalars.\n *\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @param {Object} data\n * @param {String} html A placeholder string in which to substitute fields. Supports several template options:\n * `{{field_name}}` is a variable placeholder for the value of `field_name` from the provided data\n * `{{#if field_name}} Conditional text {{/if}}` will insert the contents of the tag only if the value exists.\n * Since this is only an existence check, **variables with a value of 0 will be evaluated as true**.\n * This can be used with namespaced values, `{{#if assoc:field}}`; any dynamic namespacing will be applied when the\n * layout is first retrieved.\n * @returns {string}\n */\nLocusZoom.parseFields = function (data, html) {\n if (typeof data != 'object') {\n throw new Error('LocusZoom.parseFields invalid arguments: data is not an object');\n }\n if (typeof html != 'string') {\n throw new Error('LocusZoom.parseFields invalid arguments: html is not a string');\n }\n // `tokens` is like [token,...]\n // `token` is like {text: '...'} or {variable: 'foo|bar'} or {condition: 'foo|bar'} or {close: 'if'}\n var tokens = [];\n var regex = /\\{\\{(?:(#if )?([A-Za-z0-9_:|]+)|(\\/if))\\}\\}/;\n while (html.length > 0) {\n var m = regex.exec(html);\n if (!m) { tokens.push({text: html}); html = ''; }\n else if (m.index !== 0) { tokens.push({text: html.slice(0, m.index)}); html = html.slice(m.index); }\n else if (m[1] === '#if ') { tokens.push({condition: m[2]}); html = html.slice(m[0].length); }\n else if (m[2]) { tokens.push({variable: m[2]}); html = html.slice(m[0].length); }\n else if (m[3] === '/if') { tokens.push({close: 'if'}); html = html.slice(m[0].length); }\n else {\n console.error('Error tokenizing tooltip when remaining template is ' + JSON.stringify(html) +\n ' and previous tokens are ' + JSON.stringify(tokens) +\n ' and current regex match is ' + JSON.stringify([m[1], m[2], m[3]]));\n html = html.slice(m[0].length);\n }\n }\n var astify = function() {\n var token = tokens.shift();\n if (typeof token.text !== 'undefined' || token.variable) {\n return token;\n } else if (token.condition) {\n token.then = [];\n while(tokens.length > 0) {\n if (tokens[0].close === 'if') { tokens.shift(); break; }\n token.then.push(astify());\n }\n return token;\n } else {\n console.error('Error making tooltip AST due to unknown token ' + JSON.stringify(token));\n return { text: '' };\n }\n };\n // `ast` is like [thing,...]\n // `thing` is like {text: \"...\"} or {variable:\"foo|bar\"} or {condition: \"foo|bar\", then:[thing,...]}\n var ast = [];\n while (tokens.length > 0) {\n ast.push(astify());\n }\n\n var resolve = function(variable) {\n if (!resolve.cache.hasOwnProperty(variable)) {\n resolve.cache[variable] = (new LocusZoom.Data.Field(variable)).resolve(data);\n }\n return resolve.cache[variable];\n };\n resolve.cache = {};\n var render_node = function(node) {\n if (typeof node.text !== 'undefined') {\n return node.text;\n } else if (node.variable) {\n try {\n var value = resolve(node.variable);\n if (['string','number','boolean'].indexOf(typeof value) !== -1) { return value; }\n if (value === null) { return ''; }\n } catch (error) { console.error('Error while processing variable ' + JSON.stringify(node.variable)); }\n return '{{' + node.variable + '}}';\n } else if (node.condition) {\n try {\n var condition = resolve(node.condition);\n if (condition || condition === 0) {\n return node.then.map(render_node).join('');\n }\n } catch (error) { console.error('Error while processing condition ' + JSON.stringify(node.variable)); }\n return '';\n } else { console.error('Error rendering tooltip due to unknown AST node ' + JSON.stringify(node)); }\n };\n return ast.map(render_node).join('');\n};\n\n/**\n * Shortcut method for getting the data bound to a tool tip.\n * @param {Element} node\n * @returns {*} The first element of data bound to the tooltip\n */\nLocusZoom.getToolTipData = function(node) {\n if (typeof node != 'object' || typeof node.parentNode == 'undefined') {\n throw new Error('Invalid node object');\n }\n // If this node is a locuszoom tool tip then return its data\n var selector = d3.select(node);\n if (selector.classed('lz-data_layer-tooltip') && typeof selector.data()[0] != 'undefined') {\n return selector.data()[0];\n } else {\n return LocusZoom.getToolTipData(node.parentNode);\n }\n};\n\n/**\n * Shortcut method for getting a reference to the data layer that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.getToolTipDataLayer = function(node) {\n var data = LocusZoom.getToolTipData(node);\n if (data.getDataLayer) { return data.getDataLayer(); }\n return null;\n};\n\n/**\n * Shortcut method for getting a reference to the panel that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.getToolTipPanel = function(node) {\n var data_layer = LocusZoom.getToolTipDataLayer(node);\n if (data_layer) { return data_layer.parent; }\n return null;\n};\n\n/**\n * Shortcut method for getting a reference to the plot that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.getToolTipPlot = function(node) {\n var panel = LocusZoom.getToolTipPanel(node);\n if (panel) { return panel.parent; }\n return null;\n};\n\n/**\n * Generate a curtain object for a plot, panel, or any other subdivision of a layout\n * The panel curtain, like the plot curtain is an HTML overlay that obscures the entire panel. It can be styled\n * arbitrarily and display arbitrary messages. It is useful for reporting error messages visually to an end user\n * when the error renders the panel unusable.\n * TODO: Improve type doc here\n * @returns {object}\n */\nLocusZoom.generateCurtain = function() {\n var curtain = {\n showing: false,\n selector: null,\n content_selector: null,\n hide_delay: null,\n\n /**\n * Generate the curtain. Any content (string) argument passed will be displayed in the curtain as raw HTML.\n * CSS (object) can be passed which will apply styles to the curtain and its content.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n show: function(content, css) {\n if (!this.curtain.showing) {\n this.curtain.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div')\n .attr('class', 'lz-curtain').attr('id', this.id + '.curtain');\n this.curtain.content_selector = this.curtain.selector.append('div').attr('class', 'lz-curtain-content');\n this.curtain.selector.append('div').attr('class', 'lz-curtain-dismiss').html('Dismiss')\n .on('click', function() {\n this.curtain.hide();\n }.bind(this));\n this.curtain.showing = true;\n }\n return this.curtain.update(content, css);\n }.bind(this),\n\n /**\n * Update the content and css of the curtain that's currently being shown. This method also adjusts the size\n * and positioning of the curtain to ensure it still covers the entire panel with no overlap.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n update: function(content, css) {\n if (!this.curtain.showing) { return this.curtain; }\n clearTimeout(this.curtain.hide_delay);\n // Apply CSS if provided\n if (typeof css == 'object') {\n this.curtain.selector.style(css);\n }\n // Update size and position\n var page_origin = this.getPageOrigin();\n this.curtain.selector.style({\n top: page_origin.y + 'px',\n left: page_origin.x + 'px',\n width: this.layout.width + 'px',\n height: this.layout.height + 'px'\n });\n this.curtain.content_selector.style({\n 'max-width': (this.layout.width - 40) + 'px',\n 'max-height': (this.layout.height - 40) + 'px'\n });\n // Apply content if provided\n if (typeof content == 'string') {\n this.curtain.content_selector.html(content);\n }\n return this.curtain;\n }.bind(this),\n\n /**\n * Remove the curtain\n * @param {number} delay Time to wait (in ms)\n */\n hide: function(delay) {\n if (!this.curtain.showing) { return this.curtain; }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.curtain.hide_delay);\n this.curtain.hide_delay = setTimeout(this.curtain.hide, delay);\n return this.curtain;\n }\n // Remove curtain\n this.curtain.selector.remove();\n this.curtain.selector = null;\n this.curtain.content_selector = null;\n this.curtain.showing = false;\n return this.curtain;\n }.bind(this)\n };\n return curtain;\n};\n\n/**\n * Generate a loader object for a plot, panel, or any other subdivision of a layout\n *\n * The panel loader is a small HTML overlay that appears in the lower left corner of the panel. It cannot be styled\n * arbitrarily, but can show a custom message and show a minimalist loading bar that can be updated to specific\n * completion percentages or be animated.\n * TODO Improve type documentation\n * @returns {object}\n */\nLocusZoom.generateLoader = function() {\n var loader = {\n showing: false,\n selector: null,\n content_selector: null,\n progress_selector: null,\n cancel_selector: null,\n\n /**\n * Show a loading indicator\n * @param {string} [content='Loading...'] Loading message (displayed as raw HTML)\n */\n show: function(content) {\n // Generate loader\n if (!this.loader.showing) {\n this.loader.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div')\n .attr('class', 'lz-loader').attr('id', this.id + '.loader');\n this.loader.content_selector = this.loader.selector.append('div')\n .attr('class', 'lz-loader-content');\n this.loader.progress_selector = this.loader.selector\n .append('div').attr('class', 'lz-loader-progress-container')\n .append('div').attr('class', 'lz-loader-progress');\n /* TODO: figure out how to make this cancel button work\n this.loader.cancel_selector = this.loader.selector.append(\"div\")\n .attr(\"class\", \"lz-loader-cancel\").html(\"Cancel\")\n .on(\"click\", function(){\n this.loader.hide();\n }.bind(this));\n */\n this.loader.showing = true;\n if (typeof content == 'undefined') { content = 'Loading...'; }\n }\n return this.loader.update(content);\n }.bind(this),\n\n /**\n * Update the currently displayed loader and ensure the new content is positioned correctly.\n * @param {string} content The text to display (as raw HTML). If not a string, will be ignored.\n * @param {number} [percent] A number from 1-100. If a value is specified, it will stop all animations\n * in progress.\n */\n update: function(content, percent) {\n if (!this.loader.showing) { return this.loader; }\n clearTimeout(this.loader.hide_delay);\n // Apply content if provided\n if (typeof content == 'string') {\n this.loader.content_selector.html(content);\n }\n // Update size and position\n var padding = 6; // is there a better place to store/define this?\n var page_origin = this.getPageOrigin();\n var loader_boundrect = this.loader.selector.node().getBoundingClientRect();\n this.loader.selector.style({\n top: (page_origin.y + this.layout.height - loader_boundrect.height - padding) + 'px',\n left: (page_origin.x + padding) + 'px'\n });\n /* Uncomment this code when a functional cancel button can be shown\n var cancel_boundrect = this.loader.cancel_selector.node().getBoundingClientRect();\n this.loader.content_selector.style({\n \"padding-right\": (cancel_boundrect.width + padding) + \"px\"\n });\n */\n // Apply percent if provided\n if (typeof percent == 'number') {\n this.loader.progress_selector.style({\n width: (Math.min(Math.max(percent, 1), 100)) + '%'\n });\n }\n return this.loader;\n }.bind(this),\n\n /**\n * Adds a class to the loading bar that makes it loop infinitely in a loading animation. Useful when exact\n * percent progress is not available.\n */\n animate: function() {\n this.loader.progress_selector.classed('lz-loader-progress-animated', true);\n return this.loader;\n }.bind(this),\n\n /**\n * Sets the loading bar in the loader to percentage width equal to the percent (number) value passed. Percents\n * will automatically be limited to a range of 1 to 100. Will stop all animations in progress.\n */\n setPercentCompleted: function(percent) {\n this.loader.progress_selector.classed('lz-loader-progress-animated', false);\n return this.loader.update(null, percent);\n }.bind(this),\n\n /**\n * Remove the loader\n * @param {number} delay Time to wait (in ms)\n */\n hide: function(delay) {\n if (!this.loader.showing) { return this.loader; }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.loader.hide_delay);\n this.loader.hide_delay = setTimeout(this.loader.hide, delay);\n return this.loader;\n }\n // Remove loader\n this.loader.selector.remove();\n this.loader.selector = null;\n this.loader.content_selector = null;\n this.loader.progress_selector = null;\n this.loader.cancel_selector = null;\n this.loader.showing = false;\n return this.loader;\n }.bind(this)\n };\n return loader;\n};\n\n/**\n * Create a new subclass following classical inheritance patterns. Some registry singletons use this internally to\n * enable code reuse and customization of known LZ core functionality.\n *\n * @param {Function} parent A parent class constructor that will be extended by the child class\n * @param {Object} extra An object of additional properties and methods to add/override behavior for the child class.\n * The special \"constructor\" property can be used to specify a custom constructor, or it will call parent by default.\n * Implementer must manage super calls when overriding the constructor.\n * @returns {Function} The constructor for the new child class\n */\nLocusZoom.subclass = function(parent, extra) {\n if (typeof parent !== 'function' ) {\n throw new Error('Parent must be a callable constructor');\n }\n\n extra = extra || {};\n var Sub = extra.hasOwnProperty('constructor') ? extra.constructor : function() {\n parent.apply(this, arguments);\n };\n\n Sub.prototype = Object.create(parent.prototype);\n Object.keys(extra).forEach(function(k) {\n Sub.prototype[k] = extra[k];\n });\n return Sub;\n};\n\n\n/**\n * LocusZoom optional extensions will live under this namespace.\n *\n * Extension code is not part of the core LocusZoom app.js bundle.\n * @namespace\n * @public\n */\nLocusZoom.ext = {};\n","/* global LocusZoom */\n'use strict';\n\nfunction validateBuildSource(class_name, build, source) {\n // Build OR Source, not both\n if ((build && source) || !(build || source)) {\n throw new Error(class_name + ' must provide a parameter specifying either \"build\" or \"source\". It should not specify both.');\n }\n // If the build isn't recognized, our APIs can't transparently select a source to match\n if (build && ['GRCh37', 'GRCh38'].indexOf(build) === -1) {\n throw new Error(class_name + ' must specify a valid genome build number');\n }\n}\n\n/**\n * LocusZoom functionality used for data parsing and retrieval\n * @namespace\n * @public\n */\nLocusZoom.Data = LocusZoom.Data || {};\n\n/**\n * Create and coordinate an ensemble of (namespaced) data source instances\n * @public\n * @class\n */\nLocusZoom.DataSources = function() {\n /** @member {Object.} */\n this.sources = {};\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.addSource = function(ns, x) {\n console.warn('Warning: .addSource() is deprecated. Use .add() instead');\n return this.add(ns, x);\n};\n\n/**\n * Add a (namespaced) datasource to the plot\n * @public\n * @param {String} ns A namespace used for fields from this data source\n * @param {LocusZoom.Data.Source|Array|null} x An instantiated datasource, or an array of arguments that can be used to\n * create a known datasource type.\n */\nLocusZoom.DataSources.prototype.add = function(ns, x) {\n // FIXME: Some existing sites create sources with arbitrary names. This leads to subtle breakage\n // of namespaced fields in layouts. To avoid breaking existing usages outright, issue a deprecation warning.\n if (ns.match(/[^A-Za-z0-9_]/)) {\n console.warn(\"Deprecation warning: source name '\" + ns + \"' should contain only alphanumeric characters or underscores. Use of other characters may break layouts, and will be disallowed in the future.\");\n }\n return this.set(ns, x);\n};\n\n/** @protected */\nLocusZoom.DataSources.prototype.set = function(ns, x) {\n if (Array.isArray(x)) {\n // If passed array of source name and options, make the source\n var dsobj = LocusZoom.KnownDataSources.create.apply(null, x);\n // Each datasource in the chain should be aware of its assigned namespace\n dsobj.source_id = ns;\n this.sources[ns] = dsobj;\n } else {\n // If passed the already-created source object\n if (x !== null) {\n x.source_id = ns;\n this.sources[ns] = x;\n } else {\n delete this.sources[ns];\n }\n }\n return this;\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.getSource = function(ns) {\n console.warn('Warning: .getSource() is deprecated. Use .get() instead');\n return this.get(ns);\n};\n\n/**\n * Return the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n * @returns {LocusZoom.Data.Source}\n */\nLocusZoom.DataSources.prototype.get = function(ns) {\n return this.sources[ns];\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.removeSource = function(ns) {\n console.warn('Warning: .removeSource() is deprecated. Use .remove() instead');\n return this.remove(ns);\n};\n\n/**\n * Remove the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n */\nLocusZoom.DataSources.prototype.remove = function(ns) {\n return this.set(ns, null);\n};\n\n/**\n * Populate a list of datasources specified as a JSON object\n * @public\n * @param {String|Object} x An object or JSON representation containing {ns: configArray} entries\n * @returns {LocusZoom.DataSources}\n */\nLocusZoom.DataSources.prototype.fromJSON = function(x) {\n if (typeof x === 'string') {\n x = JSON.parse(x);\n }\n var ds = this;\n Object.keys(x).forEach(function(ns) {\n ds.set(ns, x[ns]);\n });\n return ds;\n};\n\n/**\n * Return the names of all currently recognized datasources\n * @public\n * @returns {Array}\n */\nLocusZoom.DataSources.prototype.keys = function() {\n return Object.keys(this.sources);\n};\n\n/**\n * Datasources can be instantiated from a JSON object instead of code. This represents existing sources in that format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n * @public\n */\nLocusZoom.DataSources.prototype.toJSON = function() {\n return this.sources;\n};\n\n/**\n * Represents an addressable unit of data from a namespaced datasource, subject to specified value transformations.\n *\n * When used by a data layer, fields will automatically be re-fetched from the appropriate data source whenever the\n * state of a plot fetches, eg pan or zoom operations that would affect what data is displayed.\n *\n * @public\n * @class\n * @param {String} field A string representing the namespace of the datasource, the name of the desired field to fetch\n * from that datasource, and arbitrarily many transformations to apply to the value. The namespace and\n * transformation(s) are optional and information is delimited according to the general syntax\n * `[namespace:]name[|transformation][|transformation]`. For example, `association:pvalue|neglog10`\n */\nLocusZoom.Data.Field = function(field) {\n\n var parts = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/.exec(field);\n /** @member {String} */\n this.full_name = field;\n /** @member {String} */\n this.namespace = parts[1] || null;\n /** @member {String} */\n this.name = parts[2] || null;\n /** @member {Array} */\n this.transformations = [];\n\n if (typeof parts[3] == 'string' && parts[3].length > 1) {\n this.transformations = parts[3].substring(1).split('|');\n this.transformations.forEach(function(transform, i) {\n this.transformations[i] = LocusZoom.TransformationFunctions.get(transform);\n }.bind(this));\n }\n\n this.applyTransformations = function(val) {\n this.transformations.forEach(function(transform) {\n val = transform(val);\n });\n return val;\n };\n\n // Resolve the field for a given data element.\n // First look for a full match with transformations already applied by the data requester.\n // Otherwise prefer a namespace match and fall back to just a name match, applying transformations on the fly.\n this.resolve = function(d) {\n if (typeof d[this.full_name] == 'undefined') {\n var val = null;\n if (typeof (d[this.namespace + ':' + this.name]) != 'undefined') { val = d[this.namespace + ':' + this.name]; }\n else if (typeof d[this.name] != 'undefined') { val = d[this.name]; }\n d[this.full_name] = this.applyTransformations(val);\n }\n return d[this.full_name];\n };\n\n};\n\n/**\n * The Requester manages fetching of data across multiple data sources. It is used internally by LocusZoom data layers.\n * It passes state information and ensures that data is formatted in the manner expected by the plot.\n *\n * It is also responsible for constructing a \"chain\" of dependent requests, by requesting each datasource\n * sequentially in the order specified in the datalayer `fields` array. Data sources are only chained within a\n * data layer, and only if that layer requests more than one kind of data source.\n * @param {LocusZoom.DataSources} sources An object of {ns: LocusZoom.Data.Source} instances\n * @class\n */\nLocusZoom.Data.Requester = function(sources) {\n\n function split_requests(fields) {\n // Given a fields array, return an object specifying what datasource names the data layer should make requests\n // to, and how to handle the returned data\n var requests = {};\n // Regular expression finds namespace:field|trans\n var re = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/;\n fields.forEach(function(raw) {\n var parts = re.exec(raw);\n var ns = parts[1] || 'base';\n var field = parts[2];\n var trans = LocusZoom.TransformationFunctions.get(parts[3]);\n if (typeof requests[ns] == 'undefined') {\n requests[ns] = {outnames:[], fields:[], trans:[]};\n }\n requests[ns].outnames.push(raw);\n requests[ns].fields.push(field);\n requests[ns].trans.push(trans);\n });\n return requests;\n }\n\n /**\n * Fetch data, and create a chain that only connects two data sources if they depend on each other\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields The list of data fields specified in the `layout` for a specific data layer\n * @returns {Promise}\n */\n this.getData = function(state, fields) {\n var requests = split_requests(fields);\n // Create an array of functions that, when called, will trigger the request to the specified datasource\n var request_handles = Object.keys(requests).map(function(key) {\n if (!sources.get(key)) {\n throw new Error('Datasource for namespace ' + key + ' not found');\n }\n return sources.get(key).getData(state, requests[key].fields,\n requests[key].outnames, requests[key].trans);\n });\n //assume the fields are requested in dependent order\n //TODO: better manage dependencies\n var ret = Promise.resolve({header:{}, body: [], discrete: {}});\n for(var i = 0; i < request_handles.length; i++) {\n // If a single datalayer uses multiple sources, perform the next request when the previous one completes\n ret = ret.then(request_handles[i]);\n }\n return ret;\n };\n};\n\n/**\n * Base class for LocusZoom data sources\n * This can be extended with .extend() to create custom data sources\n * @class\n * @public\n */\nLocusZoom.Data.Source = function() {\n /**\n * Whether this source should enable caching\n * @member {Boolean}\n */\n this.enableCache = true;\n /**\n * Whether this data source type is dependent on previous requests- for example, the LD source cannot annotate\n * association data if no data was found for that region.\n * @member {boolean}\n */\n this.dependentSource = false;\n};\n\n/**\n * A default constructor that can be used when creating new data sources\n * @param {String|Object} init Basic configuration- either a url, or a config object\n * @param {String} [init.url] The datasource URL\n * @param {String} [init.params] Initial config params for the datasource\n */\nLocusZoom.Data.Source.prototype.parseInit = function(init) {\n if (typeof init === 'string') {\n /** @member {String} */\n this.url = init;\n /** @member {String} */\n this.params = {};\n } else {\n this.url = init.url;\n this.params = init.params || {};\n }\n if (!this.url) {\n throw new Error('Source not initialized with required URL');\n }\n\n};\n\n/**\n * A unique identifier that indicates whether cached data is valid for this request\n * @protected\n * @param state\n * @param chain\n * @param fields\n * @returns {String|undefined}\n */\nLocusZoom.Data.Source.prototype.getCacheKey = function(state, chain, fields) {\n return this.getURL && this.getURL(state, chain, fields);\n};\n\n/**\n * Stub: build the URL for any requests made by this source.\n */\nLocusZoom.Data.Source.prototype.getURL = function(state, chain, fields) { return this.url; };\n\n/**\n * Perform a network request to fetch data for this source\n * @protected\n * @param {Object} state The state of the parent plot\n * @param chain\n * @param fields\n * @returns {Promise}\n */\nLocusZoom.Data.Source.prototype.fetchRequest = function(state, chain, fields) {\n var url = this.getURL(state, chain, fields);\n return LocusZoom.createCORSPromise('GET', url);\n};\n\n/**\n * Gets the data for just this source, typically via a network request (caching where possible)\n * @protected\n */\nLocusZoom.Data.Source.prototype.getRequest = function(state, chain, fields) {\n var req;\n var cacheKey = this.getCacheKey(state, chain, fields);\n if (this.enableCache && typeof(cacheKey) !== 'undefined' && cacheKey === this._cachedKey) {\n req = Promise.resolve(this._cachedResponse); // Resolve to the value of the current promise\n } else {\n req = this.fetchRequest(state, chain, fields);\n if (this.enableCache) {\n this._cachedKey = cacheKey;\n this._cachedResponse = req;\n }\n }\n return req;\n};\n\n/**\n * Fetch the data from the specified data source, and apply transformations requested by an external consumer.\n * This is the public-facing datasource method that will most commonly be called by external code.\n *\n * @public\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields Array of field names that the plot has requested from this data source. (without the \"namespace\" prefix)\n * @param {String[]} outnames Array describing how the output data should refer to this field. This represents the\n * originally requested field name, including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {function} A callable operation that can be used as part of the data chain\n */\nLocusZoom.Data.Source.prototype.getData = function(state, fields, outnames, trans) {\n if (this.preGetData) {\n var pre = this.preGetData(state, fields, outnames, trans);\n if(this.pre) {\n state = pre.state || state;\n fields = pre.fields || fields;\n outnames = pre.outnames || outnames;\n trans = pre.trans || trans;\n }\n }\n\n var self = this;\n return function (chain) {\n if (self.dependentSource && chain && chain.body && !chain.body.length) {\n // A \"dependent\" source should not attempt to fire a request if there is no data for it to act on.\n // Therefore, it should simply return the previous data chain.\n return Promise.resolve(chain);\n }\n\n return self.getRequest(state, chain, fields).then(function(resp) {\n return self.parseResponse(resp, chain, fields, outnames, trans);\n });\n };\n};\n\n/**\n * Ensure the server response is in a canonical form, an array of one object per record. [ {field: oneval} ].\n * If the server response contains columns, reformats the response from {column1: [], column2: []} to the above.\n *\n * Does not apply namespacing, transformations, or field extraction.\n *\n * May be overridden by data sources that inherently return more complex payloads, or that exist to annotate other\n * sources (eg, if the payload provides extra data rather than a series of records).\n *\n * @param {Object[]|Object} data The original parsed server response\n * @protected\n */\nLocusZoom.Data.Source.prototype.normalizeResponse = function (data) {\n if (Array.isArray(data)) {\n // Already in the desired form\n return data;\n }\n\n // Otherwise, assume the server response is an object representing columns of data.\n // Each array should have the same length (verify), and a given array index corresponds to a single row.\n var keys = Object.keys(data);\n var N = data[keys[0]].length;\n var sameLength = keys.every(function(key) {\n var item = data[key];\n return item.length === N;\n });\n if (!sameLength) {\n throw new Error(this.constructor.SOURCE_NAME + ' expects a response in which all arrays of data are the same length');\n }\n\n // Go down the rows, and create an object for each record\n var records = [];\n var fields = Object.keys(data);\n for(var i = 0; i < N; i++) {\n var record = {};\n for(var j = 0; j < fields.length; j++) {\n record[fields[j]] = data[fields[j]][i];\n }\n records.push(record);\n }\n return records;\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.prepareData = function (records) {\n console.warn('Warning: .prepareData() is deprecated. Use .annotateData() instead');\n return this.annotateData(records);\n};\n\n/**\n * Hook to post-process the data returned by this source with new, additional behavior.\n * (eg cleaning up API values or performing complex calculations on the returned data)\n *\n * @param {Object[]} records The parsed data from the source (eg standardized api response)\n * @param {Object} chain The data chain object. For example, chain.headers may provide useful annotation metadata\n * @returns {Object[]|Promise} The modified set of records\n */\nLocusZoom.Data.Source.prototype.annotateData = function(records, chain) {\n // Default behavior: no transformations\n return records;\n};\n\n/**\n * Clean up the server records for use by datalayers: extract only certain fields, with the specified names.\n * Apply per-field transformations as appropriate.\n *\n * This hook can be overridden, eg to create a source that always returns all records and ignores the \"fields\" array.\n * This is particularly common for sources at the end of a chain- many \"dependent\" sources do not allow\n * cherry-picking individual fields, in which case by **convention** the fields array specifies \"last_source_name:all\"\n *\n * @param {Object[]} data One record object per element\n * @param {String[]} fields The names of fields to extract (as named in the source data). Eg \"afield\"\n * @param {String[]} outnames How to represent the source fields in the output. Eg \"namespace:afield|atransform\"\n * @param {function[]} trans An array of transformation functions (if any). One function per data element, or null.\n * @protected\n */\nLocusZoom.Data.Source.prototype.extractFields = function (data, fields, outnames, trans) {\n //intended for an array of objects\n // [ {\"id\":1, \"val\":5}, {\"id\":2, \"val\":10}]\n // Since a number of sources exist that do not obey this format, we will provide a convenient pass-through\n if (!Array.isArray(data)) {\n return data;\n }\n\n if (!data.length) {\n // Sometimes there are regions that just don't have data- this should not trigger a missing field error message!\n return data;\n }\n\n var fieldFound = [];\n for (var k = 0; k < fields.length; k++) {\n fieldFound[k] = 0;\n }\n\n var records = data.map(function (item) {\n var output_record = {};\n for (var j = 0; j < fields.length; j++) {\n var val = item[fields[j]];\n if (typeof val != 'undefined') {\n fieldFound[j] = 1;\n }\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n output_record[outnames[j]] = val;\n }\n return output_record;\n });\n fieldFound.forEach(function(v, i) {\n if (!v) {throw new Error('field ' + fields[i] + ' not found in response for ' + outnames[i]);}\n });\n return records;\n};\n\n/**\n * Combine records from this source with others in the chain to yield final chain body.\n * Handles merging this data with other sources (if applicable).\n *\n * @param {Object[]} data The data That would be returned from this source alone\n * @param {Object} chain The data chain built up during previous requests\n * @param {String[]} fields\n * @param {String[]} outnames\n * @return {Promise|Object[]} The new chain body\n * @protected\n */\nLocusZoom.Data.Source.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n return data;\n};\n\n/**\n * Coordinates the work of parsing a response and returning records. This is broken into 4 steps, which may be\n * overridden separately for fine-grained control. Each step can return either raw data or a promise.\n *\n * @public\n * @param {String|Object} resp The raw data associated with the response\n * @param {Object} chain The combined parsed response data from this and all other requests made in the chain\n * @param {String[]} fields Array of requested field names (as they would appear in the response payload)\n * @param {String[]} outnames Array of field names as they will be represented in the data returned by this source,\n * including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {Promise|{header: ({}|*), discrete: {}, body: []}} A promise that resolves to an object containing\n * request metadata (headers), the consolidated data for plotting (body), and the individual responses that would be\n * returned by each source in the chain in isolation (discrete)\n */\nLocusZoom.Data.Source.prototype.parseResponse = function(resp, chain, fields, outnames, trans) {\n var source_id = this.source_id || this.constructor.SOURCE_NAME;\n if (!chain.discrete) {\n chain.discrete = {};\n }\n\n if (!resp) {\n // FIXME: Hack. Certain browser issues (such as mixed content warnings) are reported as a successful promise\n // resolution, even though the request was aborted. This is difficult to reliably detect, and is most likely\n // to occur for annotation sources (such as from ExAC). If empty response is received, skip parsing and log.\n // FIXME: Throw an error after pending, eg https://github.com/konradjk/exac_browser/issues/345\n console.error(\"No usable response was returned for source: '\" + source_id + \"'. Parsing will be skipped.\");\n return Promise.resolve(chain);\n }\n\n var json = typeof resp == 'string' ? JSON.parse(resp) : resp;\n\n var self = this;\n // Perform the 4 steps of parsing the payload and return a combined chain object\n return Promise.resolve(self.normalizeResponse(json.data || json))\n .then(function(standardized) {\n // Perform calculations on the data from just this source\n return Promise.resolve(self.annotateData(standardized, chain));\n }).then(function (data) {\n return Promise.resolve(self.extractFields(data, fields, outnames, trans));\n }).then(function (one_source_body) {\n // Store a copy of the data that would be returned by parsing this source in isolation (and taking the\n // fields array into account). This is useful when we want to re-use the source output in many ways.\n chain.discrete[source_id] = one_source_body;\n return Promise.resolve(self.combineChainBody(one_source_body, chain, fields, outnames, trans));\n }).then(function (new_body) {\n return { header: chain.header || {}, discrete: chain.discrete, body: new_body };\n });\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseArraysToObjects = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseArraysToObjects() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseObjectsToObjects = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseObjectsToObjects() is deprecated. Use .extractFields() instead');\n return this.extractFields(data, fields, outnames, trans);\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseData = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseData() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n};\n\n/**\n * Method to define new custom datasources based on a provided constructor. (does not allow registering any additional methods)\n * @public\n * @param {Function} constructorFun Constructor function that is used to create the specified class\n * @param {String} [uniqueName] The name by which the class should be listed in `KnownDataSources`\n * @param {String|Function} [base=LocusZoomData.Source] The name or constructor of a base class to use\n * @returns {*|Function}\n */\nLocusZoom.Data.Source.extend = function(constructorFun, uniqueName, base) {\n if (base) {\n if (Array.isArray(base)) {\n base = LocusZoom.KnownDataSources.create.apply(null, base);\n } else if (typeof base === 'string') {\n base = LocusZoom.KnownDataSources.get(base).prototype;\n } else if (typeof base === 'function') {\n base = base.prototype;\n }\n } else {\n base = new LocusZoom.Data.Source();\n }\n constructorFun = constructorFun || function() {};\n constructorFun.prototype = base;\n constructorFun.prototype.constructor = constructorFun;\n if (uniqueName) {\n /** @member {String} LocusZoom.Data.Source.SOURCENAME */\n constructorFun.SOURCE_NAME = uniqueName;\n LocusZoom.KnownDataSources.add(constructorFun);\n }\n return constructorFun;\n};\n\n/**\n * Datasources can be instantiated from a JSON object instead of code. This represents an existing source in that data format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n *\n * Custom sources with their own parameters may need to re-implement this method\n *\n * @public\n * @returns {Object}\n */\nLocusZoom.Data.Source.prototype.toJSON = function() {\n return [Object.getPrototypeOf(this).constructor.SOURCE_NAME,\n {url:this.url, params:this.params}];\n};\n\n/**\n * Data Source for Association Data, as fetched from the LocusZoom API server (or compatible)\n * @class\n * @public\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.AssociationSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'AssociationLZ');\n\nLocusZoom.Data.AssociationSource.prototype.preGetData = function(state, fields, outnames, trans) {\n var id_field = this.params.id_field || 'id';\n [id_field, 'position'].forEach(function(x) {\n if (fields.indexOf(x) === -1) {\n fields.unshift(x);\n outnames.unshift(x);\n trans.unshift(null);\n }\n });\n return {fields: fields, outnames:outnames, trans:trans};\n};\n\nLocusZoom.Data.AssociationSource.prototype.getURL = function(state, chain, fields) {\n var analysis = chain.header.analysis || this.params.source || this.params.analysis; // Old usages called this param \"analysis\"\n if (typeof analysis == 'undefined') {\n throw new Error('Association source must specify an analysis ID to plot');\n }\n return this.url + 'results/?filter=analysis in ' + analysis +\n \" and chromosome in '\" + state.chr + \"'\" +\n ' and position ge ' + state.start +\n ' and position le ' + state.end;\n};\n\nLocusZoom.Data.AssociationSource.prototype.normalizeResponse = function (data) {\n // Some association sources do not sort their data in a predictable order, which makes it hard to reliably\n // align with other sources (such as LD). For performance reasons, sorting is an opt-in argument.\n // TODO: Consider more fine grained sorting control in the future\n data = LocusZoom.Data.Source.prototype.normalizeResponse.call(this, data);\n if (this.params && this.params.sort && data.length && data[0]['position']) {\n data.sort(function (a, b) { return a['position'] - b['position']; });\n }\n return data;\n};\n\n/**\n * Data Source for LD Data, as fetched from the LocusZoom API server (or compatible)\n * This source is designed to connect its results to association data, and therefore depends on association data having\n * been loaded by a previous request in the data chain.\n *\n * This source is deprecated in favor of a new, standalone LD server. For new usages, see LDLZ2.\n *\n * @class\n * @deprecated\n * @public\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.LDSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n this.dependentSource = true;\n}, 'LDLZ');\n\nLocusZoom.Data.LDSource.prototype.preGetData = function(state, fields) {\n if (fields.length > 1) {\n if (fields.length !== 2 || fields.indexOf('isrefvar') === -1) {\n throw new Error('LD does not know how to get all fields: ' + fields.join(', '));\n }\n }\n};\n\nLocusZoom.Data.LDSource.prototype.findMergeFields = function(chain) {\n // Find the fields (as provided by a previous step in the chain, like an association source) that will be needed to\n // combine LD data with existing information\n\n // Since LD information may be shared across multiple assoc sources with different namespaces,\n // we use regex to find columns to join on, rather than requiring exact matches\n var exactMatch = function(arr) {return function() {\n var regexes = arguments;\n for(var i = 0; i < regexes.length; i++) {\n var regex = regexes[i];\n var m = arr.filter(function(x) {return x.match(regex);});\n if (m.length) {\n return m[0];\n }\n }\n return null;\n };};\n var dataFields = {\n id: this.params.id_field,\n position: this.params.position_field,\n pvalue: this.params.pvalue_field,\n _names_:null\n };\n if (chain && chain.body && chain.body.length > 0) {\n var names = Object.keys(chain.body[0]);\n var nameMatch = exactMatch(names);\n // Internally, fields are generally prefixed with the name of the source they come from.\n // If the user provides an id_field (like `variant`), it should work across data sources( `assoc1:variant`,\n // assoc2:variant), but not match fragments of other field names (assoc1:variant_thing)\n // Note: these lookups hard-code a couple of common fields that will work based on known APIs in the wild\n var id_match = dataFields.id && nameMatch(new RegExp(dataFields.id + '\\\\b'));\n dataFields.id = id_match || nameMatch(/\\bvariant\\b/) || nameMatch(/\\bid\\b/);\n dataFields.position = dataFields.position || nameMatch(/\\bposition\\b/i, /\\bpos\\b/i);\n dataFields.pvalue = dataFields.pvalue || nameMatch(/\\bpvalue\\b/i, /\\blog_pvalue\\b/i);\n dataFields._names_ = names;\n }\n return dataFields;\n};\n\nLocusZoom.Data.LDSource.prototype.findRequestedFields = function(fields, outnames) {\n // Assumption: all usages of this source will only ever ask for \"isrefvar\" or \"state\". This maps to output names.\n var obj = {};\n for(var i = 0; i < fields.length; i++) {\n if(fields[i] === 'isrefvar') {\n obj.isrefvarin = fields[i];\n obj.isrefvarout = outnames && outnames[i];\n } else {\n obj.ldin = fields[i];\n obj.ldout = outnames && outnames[i];\n }\n }\n return obj;\n};\n\nLocusZoom.Data.LDSource.prototype.normalizeResponse = function (data) { return data; };\n\n\n/**\n * Get the LD reference variant, which by default will be the most significant hit in the assoc results\n * This will be used in making the original query to the LD server for pairwise LD information\n * @returns {*|string} The marker id (expected to be in `chr:pos_ref/alt` format) of the reference variant\n */\nLocusZoom.Data.LDSource.prototype.getRefvar = function (state, chain, fields) {\n var findExtremeValue = function(records, pval_field) {\n // Finds the most significant hit (smallest pvalue, or largest -log10p). Will try to auto-detect the appropriate comparison.\n pval_field = pval_field || 'log_pvalue'; // The official LZ API returns log_pvalue\n var is_log = /log/.test(pval_field);\n var cmp;\n if (is_log) {\n cmp = function(a, b) { return a > b; };\n } else {\n cmp = function(a, b) { return a < b; };\n }\n var extremeVal = records[0][pval_field], extremeIdx = 0;\n for(var i = 1; i < records.length; i++) {\n if (cmp(records[i][pval_field], extremeVal)) {\n extremeVal = records[i][pval_field];\n extremeIdx = i;\n }\n }\n return extremeIdx;\n };\n\n var reqFields = this.findRequestedFields(fields);\n var refVar = reqFields.ldin;\n if (refVar === 'state') {\n refVar = state.ldrefvar || chain.header.ldrefvar || 'best';\n }\n if (refVar === 'best') {\n if (!chain.body) {\n throw new Error('No association data found to find best pvalue');\n }\n var keys = this.findMergeFields(chain);\n if (!keys.pvalue || !keys.id) {\n var columns = '';\n if (!keys.id) { columns += (columns.length ? ', ' : '') + 'id'; }\n if (!keys.pvalue) { columns += (columns.length ? ', ' : '') + 'pvalue'; }\n throw new Error('Unable to find necessary column(s) for merge: ' + columns + ' (available: ' + keys._names_ + ')');\n }\n refVar = chain.body[findExtremeValue(chain.body, keys.pvalue)][keys.id];\n }\n return refVar;\n};\n\nLocusZoom.Data.LDSource.prototype.getURL = function(state, chain, fields) {\n var refSource = state.ldrefsource || chain.header.ldrefsource || 1;\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n return this.url + 'results/?filter=reference eq ' + refSource +\n \" and chromosome2 eq '\" + state.chr + \"'\" +\n ' and position2 ge ' + state.start +\n ' and position2 le ' + state.end +\n \" and variant1 eq '\" + refVar + \"'\" +\n '&fields=chr,pos,rsquare';\n};\n\nLocusZoom.Data.LDSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n var keys = this.findMergeFields(chain);\n var reqFields = this.findRequestedFields(fields, outnames);\n if (!keys.position) {\n throw new Error('Unable to find position field for merge: ' + keys._names_);\n }\n var leftJoin = function(left, right, lfield, rfield) {\n var i = 0, j = 0;\n while (i < left.length && j < right.position2.length) {\n if (left[i][keys.position] === right.position2[j]) {\n left[i][lfield] = right[rfield][j];\n i++;\n j++;\n } else if (left[i][keys.position] < right.position2[j]) {\n i++;\n } else {\n j++;\n }\n }\n };\n var tagRefVariant = function(data, refvar, idfield, outrefname, outldname) {\n for(var i = 0; i < data.length; i++) {\n if (data[i][idfield] && data[i][idfield] === refvar) {\n data[i][outrefname] = 1;\n data[i][outldname] = 1; // For label/filter purposes, implicitly mark the ref var as LD=1 to itself\n } else {\n data[i][outrefname] = 0;\n }\n }\n };\n\n // LD servers vary slightly. Some report corr as \"rsquare\", others as \"correlation\"\n var corrField = data.rsquare ? 'rsquare' : 'correlation';\n leftJoin(chain.body, data, reqFields.ldout, corrField);\n if(reqFields.isrefvarin && chain.header.ldrefvar) {\n tagRefVariant(chain.body, chain.header.ldrefvar, keys.id, reqFields.isrefvarout, reqFields.ldout);\n }\n return chain.body;\n};\n\n/**\n * Fetch LD directly from the standalone Portal LD server\n *\n * @class\n * @public\n * @augments LocusZoom.Data.LDSource\n */\nLocusZoom.Data.LDSource2 = LocusZoom.KnownDataSources.extend('LDLZ', 'LDLZ2', {\n getURL: function(state, chain, fields) {\n // Accept the following params in this.params:\n // - method (r, rsquare, cov)\n // - source (aka panel)\n // - population (ALL, AFR, EUR, etc)\n // - build\n // The LD source/pop can be overridden from plot.state for dynamic layouts\n var build = state.genome_build || this.params.build || 'GRCh37';\n var source = state.ld_source || this.params.source || '1000G';\n var population = state.ld_pop || this.params.population || 'ALL'; // LDServer panels will always have an ALL\n var method = this.params.method || 'rsquare';\n\n validateBuildSource(this.constructor.SOURCE_NAME, build, null); // LD doesn't need to validate `source` option\n\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n\n return [\n this.url, 'genome_builds/', build, '/references/', source, '/populations/', population, '/variants',\n '?correlation=', method,\n '&variant=', encodeURIComponent(refVar),\n '&chrom=', encodeURIComponent(state.chr),\n '&start=', encodeURIComponent(state.start),\n '&stop=', encodeURIComponent(state.end)\n ].join('');\n },\n fetchRequest: function(state, chain, fields) {\n // The API is paginated, but we need all of the data to render a plot. Depaginate and combine where appropriate.\n var url = this.getURL(state, chain, fields);\n var combined = { data: {} };\n var chainRequests = function (url) {\n return LocusZoom.createCORSPromise('GET', url)\n .then(function(payload) {\n payload = JSON.parse(payload);\n Object.keys(payload.data).forEach(function (key) {\n combined.data[key] = (combined.data[key] || []).concat(payload.data[key]);\n });\n if (payload.next) {\n return chainRequests(payload.next);\n }\n return combined;\n });\n };\n\n return chainRequests(url);\n }\n});\n\n/**\n * Data source for GWAS catalogs of known variants\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object|String} init Configuration (URL or object)\n * @param {Object} [init.params] Optional configuration parameters\n * @param {Number} [init.params.source=2] The ID of the chosen catalog. Defaults to EBI GWAS catalog, GRCh37\n * @param {('strict'|'loose')} [init.params.match_type='strict'] Whether to match on exact variant, or just position.\n */\nLocusZoom.Data.GwasCatalog = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n this.dependentSource = true;\n}, 'GwasCatalogLZ');\n\nLocusZoom.Data.GwasCatalog.prototype.getURL = function(state, chain, fields) {\n // This is intended to be aligned with another source- we will assume they are always ordered by position, asc\n // (regardless of the actual match field)\n var build_option = state.genome_build || this.params.build;\n validateBuildSource(this.constructor.SOURCE_NAME, build_option, null); // Source can override build- not mutually exclusive\n\n // Most of our annotations will respect genome build before any other option.\n // But there can be more than one GWAS catalog for the same build, so an explicit config option will always take\n // precedence.\n var default_source = (build_option === 'GRCh38') ? 1 : 2; // EBI GWAS catalog\n var source = this.params.source || default_source;\n return this.url + '?format=objects&sort=pos&filter=id eq ' + source +\n \" and chrom eq '\" + state.chr + \"'\" +\n ' and pos ge ' + state.start +\n ' and pos le ' + state.end;\n};\n\nLocusZoom.Data.GwasCatalog.prototype.findMergeFields = function (records) {\n // Data from previous sources is already namespaced. Find the alignment field by matching.\n var knownFields = Object.keys(records);\n // Note: All API endoints involved only give results for 1 chromosome at a time; match is implied\n var posMatch = knownFields.find(function (item) { return item.match(/\\b(position|pos)\\b/i); });\n\n if (!posMatch) {\n throw new Error('Could not find data to align with GWAS catalog results');\n }\n return { 'pos': posMatch };\n};\n\n// Skip the \"individual field extraction\" step; extraction will be handled when building chain body instead\nLocusZoom.Data.GwasCatalog.prototype.extractFields = function (data, fields, outnames, trans) { return data; };\n\nLocusZoom.Data.GwasCatalog.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data.length) {\n return chain.body;\n }\n\n var decider = 'log_pvalue'; // TODO: Better reuse options in the future\n var decider_out = outnames[fields.indexOf(decider)];\n\n function leftJoin(left, right, fields, outnames, trans) { // Add `fields` from `right` to `left`\n // Add a synthetic, un-namespaced field to all matching records\n var n_matches = left['n_catalog_matches'] || 0;\n left['n_catalog_matches'] = n_matches + 1;\n if (decider && left[decider_out] && left[decider_out] > right[decider]) {\n // There may be more than one GWAS catalog entry for the same SNP. This source is intended for a 1:1\n // annotation scenario, so for now it only joins the catalog entry that has the best -log10 pvalue\n return;\n }\n\n for (var j = 0; j < fields.length; j++) {\n var fn = fields[j];\n var outn = outnames[j];\n\n var val = right[fn];\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n left[outn] = val;\n }\n }\n\n var chainNames = this.findMergeFields(chain.body[0]);\n var catNames = this.findMergeFields(data[0]);\n\n var i = 0, j = 0;\n while (i < chain.body.length && j < data.length) {\n var left = chain.body[i];\n var right = data[j];\n\n if (left[chainNames.pos] === right[catNames.pos]) {\n // There may be multiple catalog entries for each matching SNP; evaluate match one at a time\n leftJoin(left, right, fields, outnames, trans);\n j += 1;\n } else if (left[chainNames.pos] < right[catNames.pos]) {\n i += 1;\n } else {\n j += 1;\n }\n }\n return chain.body;\n};\n\n\n/**\n * Data Source for Gene Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.GeneSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'GeneLZ');\n\nLocusZoom.Data.GeneSource.prototype.getURL = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n\n if (build) { // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = (build === 'GRCh38') ? 1 : 3;\n }\n return this.url + '?filter=source in ' + source +\n \" and chrom eq '\" + state.chr + \"'\" +\n ' and start le ' + state.end +\n ' and end ge ' + state.start;\n};\n\n// Genes have a very complex internal data format. Bypass any record parsing, and provide the data layer with the\n// exact information returned by the API. (ignoring the fields array in the layout)\nLocusZoom.Data.GeneSource.prototype.normalizeResponse = function (data) { return data; };\nLocusZoom.Data.GeneSource.prototype.extractFields = function (data, fields, outnames, trans) { return data; };\n\n/**\n * Data Source for Gene Constraint Data, as fetched from the ExAC server (or compatible)\n *\n * FIXME: The ExAc server has been decommissioned. This source is kept here to avoid breaking existing layouts; we may\n * be able to restore this feature in the future once the gnomAD API is further developed\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n*/\nLocusZoom.Data.GeneConstraintSource = LocusZoom.Data.Source.extend(function(init) {\n console.warn('The gene constraint source depends on a server (ExAC) that is no longer active. This information may not be displayed.');\n this.parseInit(init);\n}, 'GeneConstraintLZ');\n\nLocusZoom.Data.GeneConstraintSource.prototype.getURL = function() {\n return this.url;\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.normalizeResponse = function (data) { return data; };\n\nLocusZoom.Data.GeneConstraintSource.prototype.getCacheKey = function(state, chain, fields) {\n return this.url + JSON.stringify(state);\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function(state, chain, fields) {\n var geneids = [];\n chain.body.forEach(function(gene) {\n var gene_id = gene.gene_id;\n if (gene_id.indexOf('.')) {\n gene_id = gene_id.substr(0, gene_id.indexOf('.'));\n }\n geneids.push(gene_id);\n });\n var url = this.getURL(state, chain, fields);\n var body = 'geneids=' + encodeURIComponent(JSON.stringify(geneids));\n var headers = {\n 'Content-Type': 'application/x-www-form-urlencoded'\n };\n return LocusZoom.createCORSPromise('POST', url, body, headers);\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data) {\n return chain;\n }\n var constraint_fields = ['bp', 'exp_lof', 'exp_mis', 'exp_syn', 'lof_z', 'mis_z', 'mu_lof', 'mu_mis','mu_syn', 'n_exons', 'n_lof', 'n_mis', 'n_syn', 'pLI', 'syn_z'];\n chain.body.forEach(function(gene, i) {\n var gene_id = gene.gene_id;\n if (gene_id.indexOf('.')) {\n gene_id = gene_id.substr(0, gene_id.indexOf('.'));\n }\n constraint_fields.forEach(function(field) {\n // Do not overwrite any fields defined in the original gene source\n if (typeof chain.body[i][field] != 'undefined') { return; }\n if (data[gene_id]) {\n var val = data[gene_id][field];\n if (typeof val == 'number' && val.toString().indexOf('.') !== -1) {\n val = parseFloat(val.toFixed(2));\n }\n chain.body[i][field] = val;\n } else {\n // If the gene did not come back in the response then set the same field with a null values\n chain.body[i][field] = null;\n }\n });\n });\n return chain.body;\n};\n\n/**\n * Data Source for Recombination Rate Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.RecombinationRateSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'RecombLZ');\n\nLocusZoom.Data.RecombinationRateSource.prototype.getURL = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n\n if (build) { // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = (build === 'GRCh38') ? 16 : 15;\n }\n return this.url + '?filter=id in ' + source +\n \" and chromosome eq '\" + state.chr + \"'\" +\n ' and position le ' + state.end +\n ' and position ge ' + state.start;\n};\n\n/**\n * Data Source for Interval Annotation Data (e.g. BED Tracks), as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.IntervalSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'IntervalLZ');\n\nLocusZoom.Data.IntervalSource.prototype.getURL = function(state, chain, fields) {\n var source = chain.header.bedtracksource || this.params.source;\n return this.url + '?filter=id in ' + source +\n \" and chromosome eq '\" + state.chr + \"'\" +\n ' and start le ' + state.end +\n ' and end ge ' + state.start;\n};\n\n/**\n * Data Source for static blobs of JSON Data. This does not perform additional parsing, and therefore it is the\n * responsibility of the user to pass information in a format that can be read and understood by the chosen plot.\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.StaticSource = LocusZoom.Data.Source.extend(function(data) {\n /** @member {Object} */\n this._data = data;\n},'StaticJSON');\n\nLocusZoom.Data.StaticSource.prototype.getRequest = function(state, chain, fields) {\n return Promise.resolve(this._data);\n};\n\nLocusZoom.Data.StaticSource.prototype.toJSON = function() {\n return [Object.getPrototypeOf(this).constructor.SOURCE_NAME, this._data];\n};\n\n/**\n * Data source for PheWAS data\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {String[]} init.params.build This datasource expects to be provided the name of the genome build that will\n * be used to provide pheWAS results for this position. Note positions may not translate between builds.\n */\nLocusZoom.Data.PheWASSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'PheWASLZ');\nLocusZoom.Data.PheWASSource.prototype.getURL = function(state, chain, fields) {\n var build = (state.genome_build ? [state.genome_build] : null) || this.params.build;\n if (!build || !Array.isArray(build) || !build.length) {\n throw new Error(['Data source', this.constructor.SOURCE_NAME, 'requires that you specify array of one or more desired genome build names'].join(' '));\n }\n var url = [\n this.url,\n \"?filter=variant eq '\", encodeURIComponent(state.variant), \"'&format=objects&\",\n build.map(function(item) {return 'build=' + encodeURIComponent(item);}).join('&')\n ];\n return url.join('');\n};\n\n/**\n * Base class for \"connectors\"- this is meant to be subclassed, rather than used directly.\n *\n * A connector is a source that makes no server requests and caches no data of its own. Instead, it decides how to\n * combine data from other sources in the chain. Connectors are useful when we want to request (or calculate) some\n * useful piece of information once, but apply it to many different kinds of record types.\n *\n * Typically, a subclass will implement the field merging logic in `combineChainBody`.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object} init Configuration for this source\n * @param {Object} init.sources Specify how the hard-coded logic should find the data it relies on in the chain,\n * as {internal_name: chain_source_id} pairs. This allows writing a reusable connector that does not need to make\n * assumptions about what namespaces a source is using.\n * @type {*|Function}\n */\nLocusZoom.Data.ConnectorSource = LocusZoom.Data.Source.extend(function(init) {\n if (!init || !init.sources) {\n throw new Error('Connectors must specify the data they require as init.sources = {internal_name: chain_source_id}} pairs');\n }\n\n /**\n * Tells the connector how to find the data it relies on\n *\n * For example, a connector that applies burden test information to the genes layer might specify:\n * {gene_ns: \"gene\", aggregation_ns: \"aggregation\"}\n *\n * @member {Object}\n */\n this._source_name_mapping = init.sources;\n\n // Validate that this source has been told how to find the required information\n var specified_ids = Object.keys(init.sources);\n var self = this;\n this.REQUIRED_SOURCES.forEach(function (k) {\n if (specified_ids.indexOf(k) === -1) {\n throw new Error('Configuration for ' + self.constructor.SOURCE_NAME + ' must specify a source ID corresponding to ' + k);\n }\n });\n this.parseInit(init);\n}, 'ConnectorSource');\n\n/** @property {String[]} Specifies the sources that must be provided in the original config object */\nLocusZoom.Data.ConnectorSource.prototype.REQUIRED_SOURCES = [];\n\nLocusZoom.Data.ConnectorSource.prototype.parseInit = function(init) {}; // Stub\n\nLocusZoom.Data.ConnectorSource.prototype.getRequest = function(state, chain, fields) {\n // Connectors do not request their own data by definition, but they *do* depend on other sources having been loaded\n // first. This method performs basic validation, and preserves the accumulated body from the chain so far.\n var self = this;\n Object.keys(this._source_name_mapping).forEach(function(ns) {\n var chain_source_id = self._source_name_mapping[ns];\n if (chain.discrete && !chain.discrete[chain_source_id]) {\n throw new Error(self.constructor.SOURCE_NAME + ' cannot be used before loading required data for: ' + chain_source_id);\n }\n });\n return Promise.resolve(chain.body || []);\n};\n\nLocusZoom.Data.ConnectorSource.prototype.parseResponse = function(data, chain, fields, outnames, trans) {\n // A connector source does not update chain.discrete, but it may use it. It bypasses data formatting\n // and field selection (both are assumed to have been done already, by the previous sources this draws from)\n\n // Because of how the chain works, connectors are not very good at applying new transformations or namespacing.\n // Typically connectors are called with `connector_name:all` in the fields array.\n return Promise.resolve(this.combineChainBody(data, chain, fields, outnames, trans))\n .then(function(new_body) {\n return {header: chain.header || {}, discrete: chain.discrete || {}, body: new_body};\n });\n};\n\nLocusZoom.Data.ConnectorSource.prototype.combineChainBody = function(records, chain) {\n // Stub method: specifies how to combine the data\n throw new Error('This method must be implemented in a subclass');\n};\n","'use strict';\n\n/**\n * Create a single continuous 2D track that provides information about each datapoint\n *\n * For example, this can be used to color by membership in a group, alongside information in other panels\n *\n * @class LocusZoom.DataLayers.annotation_track\n * @augments LocusZoom.DataLayer\n * @param {Object} layout\n * @param {Object|String} [layout.color]\n * @param {Array[]} An array of filter entries specifying which points to draw annotations for.\n * See `LocusZoom.DataLayer.filter` for details\n */\nLocusZoom.DataLayers.add('annotation_track', function(layout) {\n // In the future we may add additional options for controlling marker size/ shape, based on user feedback\n this.DefaultLayout = {\n color: '#000000',\n filters: [],\n tooltip_positioning: 'middle', // Allowed values: top, middle, bottom\n hit_area_width: 8,\n };\n\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n if (!Array.isArray(layout.filters)) {\n throw new Error('Annotation track must specify array of filters for selecting points to annotate');\n }\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n this.render = function() {\n var self = this;\n // Only render points that currently satisfy all provided filter conditions.\n var trackData = this.filter(this.layout.filters, 'elements');\n\n // Put the containing visible lines before the one containing hit areas, so that the hit areas will be on top.\n var visible_lines_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-visible_lines');\n if (visible_lines_group.size() === 0) {\n visible_lines_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-visible_lines');\n }\n var selection = visible_lines_group.selectAll('rect.lz-data_layer-' + self.layout.type)\n .data(trackData, function (d) { return d[self.layout.id_field]; });\n\n // Draw rectangles (visual and tooltip positioning)\n selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function (d) { return self.getElementId(d); });\n\n var width = 1;\n selection\n .attr('x', function (d) {return self.parent['x_scale'](d[self.layout.x_axis.field]) - width / 2; })\n .attr('width', width)\n .attr('height', self.parent.layout.height)\n .attr('fill', function(d) { return self.resolveScalableParameter(self.layout.color, d); });\n\n // Remove unused elements\n selection.exit()\n .remove();\n\n var hit_areas_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-hit_areas');\n if (hit_areas_group.size() === 0) {\n hit_areas_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-hit_areas');\n }\n var hit_areas_selection = hit_areas_group.selectAll('rect.lz-data_layer-' + self.layout.type)\n .data(trackData, function (d) { return d[self.layout.id_field]; });\n\n // Add new elements as needed\n hit_areas_selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function (d) { return self.getElementId(d); });\n\n // Update the set of elements to reflect new data\n\n var _getX = function (d, i) { // Helper for position calcs below\n var x_center = self.parent['x_scale'](d[self.layout.x_axis.field]);\n var x_left = x_center - self.layout.hit_area_width / 2;\n if (i >= 1) {\n // This assumes that the data are in sorted order.\n var left_node = trackData[i - 1];\n var left_node_x_center = self.parent['x_scale'](left_node[self.layout.x_axis.field]);\n x_left = Math.max(x_left, (x_center + left_node_x_center) / 2);\n }\n return [x_left, x_center];\n };\n hit_areas_selection\n .attr('height', self.parent.layout.height)\n .attr('opacity', 0)\n .attr('x', function (d, i) {\n var crds = _getX(d,i);\n return crds[0];\n }).attr('width', function (d, i) {\n var crds = _getX(d,i);\n return (crds[1] - crds[0]) + self.layout.hit_area_width / 2;\n });\n\n // Remove unused elements\n hit_areas_selection.exit().remove();\n\n // Set up tooltips and mouse interaction\n this.applyBehaviors(hit_areas_selection);\n };\n\n // Reimplement the positionTooltip() method to be annotation-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var offset = stroke_width / 2;\n var page_origin = this.getPageOrigin();\n\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_center = data_layer_height / 2;\n\n // Tooltip should be horizontally centered above the point to be annotated. (or below if space is limited)\n var offset_right = Math.max((tooltip_box.width / 2) - x_center, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - (tooltip_box.width / 2) - offset_left + offset_right;\n arrow_left = (tooltip_box.width / 2) - (arrow_width) + offset_left - offset_right - offset;\n\n var top_offset = 0;\n switch(this.layout.tooltip_positioning) {\n case 'top':\n arrow_type = 'down';\n break;\n case 'bottom':\n top_offset = data_layer_height;\n arrow_type = 'up';\n break;\n case 'middle':\n default:\n var position = d3.mouse(this.svg.container.node());\n // Position the tooltip so that it does not overlap the mouse pointer\n top_offset = y_center;\n if (position[1] > (data_layer_height / 2)) {\n arrow_type = 'down';\n } else {\n arrow_type = 'up';\n }\n }\n\n if (arrow_type === 'up') {\n top = page_origin.y + top_offset + stroke_width + arrow_width;\n arrow_top = 0 - stroke_width - arrow_width;\n } else if (arrow_type === 'down') {\n top = page_origin.y + top_offset - (tooltip_box.height + stroke_width + arrow_width);\n arrow_top = tooltip_box.height - stroke_width;\n }\n\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n return this;\n});\n","'use strict';\n\n/**\n * Forest Data Layer\n * Implements a standard forest plot. In order to space out points, any layout using this must specify axis ticks\n * and extent in advance.\n *\n * If you are using dynamically fetched data, consider using `category_forest` instead.\n *\n * @class LocusZoom.DataLayers.forest\n */\nLocusZoom.DataLayers.add('forest', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'square',\n color: '#888888',\n fill_opacity: 1,\n y_axis: {\n axis: 2\n },\n id_field: 'id',\n confidence_intervals: {\n start_field: 'ci_start',\n end_field: 'ci_end'\n },\n show_no_significance_line: true\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Reimplement the positionTooltip() method to be forest-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n var offset = Math.sqrt(point_size / Math.PI);\n var left, arrow_type, arrow_left;\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var top, arrow_top;\n if (y_center - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + y_center - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (y_center + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + y_center - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Implement the main render function\n this.render = function() {\n\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n // Generate confidence interval paths if fields are defined\n if (this.layout.confidence_intervals\n && this.layout.fields.indexOf(this.layout.confidence_intervals.start_field) !== -1\n && this.layout.fields.indexOf(this.layout.confidence_intervals.end_field) !== -1) {\n // Generate a selection for all forest plot confidence intervals\n var ci_selection = this.svg.group\n .selectAll('rect.lz-data_layer-forest.lz-data_layer-forest-ci')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n // Create confidence interval rect elements\n ci_selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-forest lz-data_layer-forest-ci')\n .attr('id', function(d) { return this.getElementId(d) + '_ci'; }.bind(this))\n .attr('transform', 'translate(0,' + (isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height) + ')');\n // Apply position and size parameters using transition if necessary\n var ci_transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var ci_width = function(d) {\n return this.parent[x_scale](d[this.layout.confidence_intervals.end_field])\n - this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n }.bind(this);\n var ci_height = 1;\n if (this.canTransition()) {\n ci_selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', ci_transform)\n .attr('width', ci_width).attr('height', ci_height);\n } else {\n ci_selection\n .attr('transform', ci_transform)\n .attr('width', ci_width).attr('height', ci_height);\n }\n // Remove old elements as needed\n ci_selection.exit().remove();\n }\n\n // Generate a selection for all forest plot points\n var points_selection = this.svg.group\n .selectAll('path.lz-data_layer-forest.lz-data_layer-forest-point')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n points_selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-forest lz-data_layer-forest-point')\n .attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .attr('transform', 'translate(0,' + initial_y + ')');\n\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n\n var fill = function(d) { return this.resolveScalableParameter(this.layout.color, d); }.bind(this);\n var fill_opacity = function(d) { return this.resolveScalableParameter(this.layout.fill_opacity, d); }.bind(this);\n\n var shape = d3.svg.symbol()\n .size(function(d) { return this.resolveScalableParameter(this.layout.point_size, d); }.bind(this))\n .type(function(d) { return this.resolveScalableParameter(this.layout.point_shape, d); }.bind(this));\n\n // Apply position and color, using a transition if necessary\n if (this.canTransition()) {\n points_selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n } else {\n points_selection\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n }\n\n // Remove old elements as needed\n points_selection.exit().remove();\n\n // Apply default event emitters to selection\n points_selection.on('click.event_emitter', function(element_data) {\n this.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n\n // Apply behaviors to points\n this.applyBehaviors(points_selection);\n };\n return this;\n\n});\n\n/**\n * A y-aligned forest plot in which the y-axis represents item labels, which are dynamically chosen when data is loaded.\n * Each item is assumed to include both data and confidence intervals.\n * This allows generating forest plots without defining the layout in advance.\n *\n * @class LocusZoom.DataLayers.category_forest\n * @augments LocusZoom.DataLayers.forest\n */\nLocusZoom.DataLayers.extend('forest', 'category_forest', {\n _getDataExtent: function(data, axis_config) {\n // In a forest plot, the data range is determined by *three* fields (beta + CI start/end)\n var ci_config = this.layout.confidence_intervals;\n if (ci_config\n && this.layout.fields.indexOf(ci_config.start_field) !== -1\n && this.layout.fields.indexOf(ci_config.end_field) !== -1) {\n var min = function(d) {\n var f = new LocusZoom.Data.Field(ci_config.start_field);\n return +f.resolve(d);\n };\n\n var max = function(d) {\n var f = new LocusZoom.Data.Field(ci_config.end_field);\n return +f.resolve(d);\n };\n\n return [d3.min(data, min), d3.max(data, max)];\n }\n\n // If there are no confidence intervals set, then range must depend only on a single field\n return LocusZoom.DataLayer.prototype._getDataExtent.call(this, data, axis_config);\n },\n\n getTicks: function(dimension, config) { // Overrides parent method\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier' + dimension);\n }\n\n // Design assumption: one axis (y1 or y2) has the ticks, and the layout says which to use\n // Also assumes that every tick gets assigned a unique matching label\n var axis_num = this.layout.y_axis.axis;\n if (dimension === ('y' + axis_num)) {\n var category_field = this.layout.y_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n\n return this.data.map(function (item, index) {\n return {\n y: index + 1,\n text: item[category_field]\n };\n });\n } else {\n return [];\n }\n },\n\n applyCustomDataMethods: function () {\n // Add a synthetic yaxis field to ensure data is spread out on plot. Then, set axis floor and ceiling to\n // correct extents.\n var field_to_add = this.layout.y_axis.field;\n if (!field_to_add) {\n throw new Error('Layout for ' + this.layout.id + ' must specify yaxis.field');\n }\n\n this.data = this.data.map(function (item, index) {\n item[field_to_add] = index + 1;\n return item;\n });\n // Update axis extents based on one label for every point (with a bit of padding above and below)\n this.layout.y_axis.floor = 0;\n this.layout.y_axis.ceiling = this.data.length + 1;\n return this;\n }\n});\n","'use strict';\n\n/*********************\n * Genes Data Layer\n * Implements a data layer that will render gene tracks\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('genes', function(layout) {\n /**\n * Define a default layout for this DataLayer type and merge it with the passed argument\n * @protected\n * @member {Object}\n * */\n this.DefaultLayout = {\n // Optionally specify different fill and stroke properties\n stroke: 'rgb(54, 54, 150)',\n color: '#363696',\n label_font_size: 12,\n label_exon_spacing: 4,\n exon_height: 16,\n bounding_box_padding: 6,\n track_vertical_spacing: 10\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * Generate a statusnode ID for a given element\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function(element) {\n return this.getElementId(element) + '-statusnode';\n };\n\n /**\n * Helper function to sum layout values to derive total height for a single gene track\n * @returns {number}\n */\n this.getTrackHeight = function() {\n return 2 * this.layout.bounding_box_padding\n + this.layout.label_font_size\n + this.layout.label_exon_spacing\n + this.layout.exon_height\n + this.layout.track_vertical_spacing;\n };\n\n /**\n * A gene may have arbitrarily many transcripts, but this data layer isn't set up to render them yet.\n * Stash a transcript_idx to point to the first transcript and use that for all transcript refs.\n * @member {number}\n * @type {number}\n */\n this.transcript_idx = 0;\n\n /**\n * An internal counter for the number of tracks in the data layer. Used as an internal counter for looping\n * over positions / assignments\n * @protected\n * @member {number}\n */\n this.tracks = 1;\n\n /**\n * Store information about genes in dataset, in a hash indexed by track number: {track_number: [gene_indices]}\n * @member {Object.}\n */\n this.gene_track_index = { 1: [] };\n\n /**\n * Ensure that genes in overlapping chromosome regions are positioned so that parts of different genes do not\n * overlap in the view. A track is a row used to vertically separate overlapping genes.\n * @returns {LocusZoom.DataLayer}\n */\n this.assignTracks = function() {\n /**\n * Function to get the width in pixels of a label given the text and layout attributes\n * TODO: Move to outer scope?\n * @param {String} gene_name\n * @param {number|string} font_size\n * @returns {number}\n */\n this.getLabelWidth = function(gene_name, font_size) {\n try {\n var temp_text = this.svg.group.append('text')\n .attr('x', 0).attr('y', 0).attr('class', 'lz-data_layer-genes lz-label')\n .style('font-size', font_size)\n .text(gene_name + '→');\n var label_width = temp_text.node().getBBox().width;\n temp_text.remove();\n return label_width;\n } catch (e) {\n return 0;\n }\n };\n\n // Reinitialize some metadata\n this.tracks = 1;\n this.gene_track_index = { 1: [] };\n\n this.data.map(function(d, g) {\n\n // If necessary, split combined gene id / version fields into discrete fields.\n // NOTE: this may be an issue with CSG's genes data source that may eventually be solved upstream.\n if (this.data[g].gene_id && this.data[g].gene_id.indexOf('.')) {\n var split = this.data[g].gene_id.split('.');\n this.data[g].gene_id = split[0];\n this.data[g].gene_version = split[1];\n }\n\n // Stash the transcript ID on the parent gene\n this.data[g].transcript_id = this.data[g].transcripts[this.transcript_idx].transcript_id;\n\n // Determine display range start and end, based on minimum allowable gene display width, bounded by what we can see\n // (range: values in terms of pixels on the screen)\n this.data[g].display_range = {\n start: this.parent.x_scale(Math.max(d.start, this.state.start)),\n end: this.parent.x_scale(Math.min(d.end, this.state.end))\n };\n this.data[g].display_range.label_width = this.getLabelWidth(this.data[g].gene_name, this.layout.label_font_size);\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n // Determine label text anchor (default to middle)\n this.data[g].display_range.text_anchor = 'middle';\n if (this.data[g].display_range.width < this.data[g].display_range.label_width) {\n if (d.start < this.state.start) {\n this.data[g].display_range.end = this.data[g].display_range.start\n + this.data[g].display_range.label_width\n + this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'start';\n } else if (d.end > this.state.end) {\n this.data[g].display_range.start = this.data[g].display_range.end\n - this.data[g].display_range.label_width\n - this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n var centered_margin = ((this.data[g].display_range.label_width - this.data[g].display_range.width) / 2)\n + this.layout.label_font_size;\n if ((this.data[g].display_range.start - centered_margin) < this.parent.x_scale(this.state.start)) {\n this.data[g].display_range.start = this.parent.x_scale(this.state.start);\n this.data[g].display_range.end = this.data[g].display_range.start + this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'start';\n } else if ((this.data[g].display_range.end + centered_margin) > this.parent.x_scale(this.state.end)) {\n this.data[g].display_range.end = this.parent.x_scale(this.state.end);\n this.data[g].display_range.start = this.data[g].display_range.end - this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n this.data[g].display_range.start -= centered_margin;\n this.data[g].display_range.end += centered_margin;\n }\n }\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n }\n // Add bounding box padding to the calculated display range start, end, and width\n this.data[g].display_range.start -= this.layout.bounding_box_padding;\n this.data[g].display_range.end += this.layout.bounding_box_padding;\n this.data[g].display_range.width += 2 * this.layout.bounding_box_padding;\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[g].display_domain = {\n start: this.parent.x_scale.invert(this.data[g].display_range.start),\n end: this.parent.x_scale.invert(this.data[g].display_range.end)\n };\n this.data[g].display_domain.width = this.data[g].display_domain.end - this.data[g].display_domain.start;\n\n // Using display range/domain data generated above cast each gene to tracks such that none overlap\n this.data[g].track = null;\n var potential_track = 1;\n while (this.data[g].track === null) {\n var collision_on_potential_track = false;\n this.gene_track_index[potential_track].map(function(placed_gene) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_gene.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_gene.display_range.end, this.display_range.end);\n if ((max_end - min_start) < (placed_gene.display_range.width + this.display_range.width)) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[g]));\n if (!collision_on_potential_track) {\n this.data[g].track = potential_track;\n this.gene_track_index[potential_track].push(this.data[g]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.gene_track_index[potential_track] = [];\n }\n }\n }\n\n // Stash parent references on all genes, trascripts, and exons\n this.data[g].parent = this;\n this.data[g].transcripts.map(function(d, t) {\n this.data[g].transcripts[t].parent = this.data[g];\n this.data[g].transcripts[t].exons.map(function(d, e) {\n this.data[g].transcripts[t].exons[e].parent = this.data[g].transcripts[t];\n }.bind(this));\n }.bind(this));\n\n }.bind(this));\n return this;\n };\n\n /**\n * Main render function\n */\n this.render = function() {\n\n var self = this;\n this.assignTracks();\n\n var width, height, x, y;\n\n // Render gene groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-genes')\n .data(this.data, function(d) { return d.gene_name; });\n\n selection.enter().append('g')\n .attr('class', 'lz-data_layer-genes');\n\n selection.attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .each(function(gene) {\n\n var data_layer = gene.parent;\n\n // Render gene bounding boxes (status nodes to show selected/highlighted)\n var bboxes = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-data_layer-genes-statusnode')\n .data([gene], function(d) { return data_layer.getElementStatusNodeId(d); });\n\n bboxes.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-data_layer-genes-statusnode');\n\n bboxes\n .attr('id', function(d) {\n return data_layer.getElementStatusNodeId(d);\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n bboxes\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n bboxes\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n bboxes.exit().remove();\n\n // Render gene boundaries\n var boundary_fill = function(d) { return self.resolveScalableParameter(self.layout.color, d); };\n var boundary_stroke = function(d) { return self.resolveScalableParameter(self.layout.stroke, d); };\n var boundaries = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-boundary')\n .data([gene], function(d) { return d.gene_name + '_boundary'; })\n .style({ fill: boundary_fill, stroke: boundary_stroke });\n\n boundaries.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-boundary');\n\n width = function(d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function() {\n return 1; // TODO: scale dynamically?\n };\n x = function(d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size\n + data_layer.layout.label_exon_spacing\n + (Math.max(data_layer.layout.exon_height, 3) / 2);\n };\n if (data_layer.canTransition()) {\n boundaries\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n boundaries\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n boundaries.exit().remove();\n\n // Render gene labels\n var labels = d3.select(this).selectAll('text.lz-data_layer-genes.lz-label')\n .data([gene], function(d) { return d.gene_name + '_label'; });\n\n labels.enter().append('text')\n .attr('class', 'lz-data_layer-genes lz-label');\n\n labels\n .attr('text-anchor', function(d) {\n return d.display_range.text_anchor;\n })\n .text(function(d) {\n return (d.strand === '+') ? d.gene_name + '→' : '←' + d.gene_name;\n })\n .style('font-size', gene.parent.layout.label_font_size);\n\n x = function(d) {\n if (d.display_range.text_anchor === 'middle') {\n return d.display_range.start + (d.display_range.width / 2);\n } else if (d.display_range.text_anchor === 'start') {\n return d.display_range.start + data_layer.layout.bounding_box_padding;\n } else if (d.display_range.text_anchor === 'end') {\n return d.display_range.end - data_layer.layout.bounding_box_padding;\n }\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size;\n };\n if (data_layer.canTransition()) {\n labels\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('x', x).attr('y', y);\n } else {\n labels\n .attr('x', x).attr('y', y);\n }\n\n labels.exit().remove();\n\n // Render exon rects (first transcript only, for now)\n // Exons: by default color on gene properties for consistency with the gene boundary track- hence color uses d.parent.parent\n var exon_fill = function(d) { return self.resolveScalableParameter(self.layout.color, d.parent.parent); };\n var exon_stroke = function(d) { return self.resolveScalableParameter(self.layout.stroke, d.parent.parent); };\n\n var exons = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-exon')\n .data(gene.transcripts[gene.parent.transcript_idx].exons, function(d) { return d.exon_id; });\n\n exons.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-exon');\n\n exons\n .style({ fill: exon_fill, stroke: exon_stroke });\n\n width = function(d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function() {\n return data_layer.layout.exon_height;\n };\n x = function(d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function() {\n return ((gene.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size\n + data_layer.layout.label_exon_spacing;\n };\n if (data_layer.canTransition()) {\n exons\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n exons\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n exons.exit().remove();\n\n // Render gene click area\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-clickarea')\n .data([gene], function(d) { return d.gene_name + '_clickarea'; });\n\n clickareas.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-clickarea');\n\n clickareas\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '_clickarea';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n clickareas\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n // Remove old clickareas as needed\n clickareas.exit().remove();\n\n // Apply default event emitters to clickareas\n clickareas.on('click.event_emitter', function(element) {\n element.parent.parent.emit('element_clicked', element, true);\n });\n\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n\n });\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n /**\n * Reimplement the positionTooltip() method to be gene-specific\n * @param {String} id\n */\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var gene_bbox_id = this.getElementStatusNodeId(tooltip.data);\n var gene_bbox = d3.select('#' + gene_bbox_id).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the gene that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var gene_center_x = ((tooltip.data.display_range.start + tooltip.data.display_range.end) / 2) - (this.layout.bounding_box_padding / 2);\n var offset_right = Math.max((tooltip_box.width / 2) - gene_center_x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + gene_center_x - data_layer_width, 0);\n var left = page_origin.x + gene_center_x - (tooltip_box.width / 2) - offset_left + offset_right;\n var arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right;\n // Position vertically below the gene unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (gene_bbox.y + gene_bbox.height)) {\n top = page_origin.y + gene_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + gene_bbox.y + gene_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n return this;\n\n});\n","'use strict';\n\n/*********************\n Genome Legend Data Layer\n Implements a data layer that will render a genome legend\n*/\n\n// Build a custom data layer for a genome legend\nLocusZoom.DataLayers.add('genome_legend', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n chromosome_fill_colors: {\n light: 'rgb(155, 155, 188)',\n dark: 'rgb(95, 95, 128)'\n },\n chromosome_label_colors: {\n light: 'rgb(120, 120, 186)',\n dark: 'rgb(0, 0, 66)'\n }\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Implement the main render function\n this.render = function() {\n\n // Iterate over data to generate genome-wide start/end values for each chromosome\n var position = 0;\n this.data.forEach(function(d, i) {\n this.data[i].genome_start = position;\n this.data[i].genome_end = position + d['genome:base_pairs'];\n position += d['genome:base_pairs'];\n }.bind(this));\n\n var chromosomes = this.svg.group\n .selectAll('rect.lz-data_layer-genome_legend')\n .data(this.data, function(d) { return d['genome:chr']; });\n\n // Create chromosome elements, apply class\n chromosomes.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-genome_legend');\n\n // Position and fill chromosome rects\n var data_layer = this;\n var panel = this.parent;\n\n chromosomes\n .attr('fill', function(d) { return (d['genome:chr'] % 2 ? data_layer.layout.chromosome_fill_colors.light : data_layer.layout.chromosome_fill_colors.dark); })\n .attr('x', function(d) { return panel.x_scale(d.genome_start); })\n .attr('y', 0)\n .attr('width', function(d) { return panel.x_scale(d['genome:base_pairs']); })\n .attr('height', panel.layout.cliparea.height);\n\n // Remove old elements as needed\n chromosomes.exit().remove();\n\n // Parse current state variant into a position\n // Assumes that variant string is of the format 10:123352136_C/T or 10:123352136\n var variant_parts = /([^:]+):(\\d+)(?:_.*)?/.exec(this.state.variant);\n if (!variant_parts) {\n throw new Error('Genome legend cannot understand the specified variant position');\n }\n var chr = variant_parts[1];\n var offset = variant_parts[2];\n // TODO: How does this handle representation of X or Y chromosomes?\n position = +this.data[chr - 1].genome_start + +offset;\n\n // Render the position\n var region = this.svg.group\n .selectAll('rect.lz-data_layer-genome_legend-marker')\n .data([{ start: position, end: position + 1 }]);\n\n region.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-genome_legend-marker');\n\n region\n .transition()\n .duration(500)\n .style({\n 'fill': 'rgba(255, 250, 50, 0.8)',\n 'stroke': 'rgba(255, 250, 50, 0.8)',\n 'stroke-width': '3px'\n })\n .attr('x', function(d) { return panel.x_scale(d.start); })\n .attr('y', 0)\n .attr('width', function(d) { return panel.x_scale(d.end - d.start); })\n .attr('height', panel.layout.cliparea.height);\n\n region.exit().remove();\n\n };\n\n return this;\n\n});\n","'use strict';\n\n/**\n * Intervals Data Layer\n * Implements a data layer that will render interval annotation tracks (intervals must provide start and end values)\n * @class LocusZoom.DataLayers.intervals\n * @augments LocusZoom.DataLayer\n */\nLocusZoom.DataLayers.add('intervals', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n start_field: 'start',\n end_field: 'end',\n track_split_field: 'state_id',\n track_split_order: 'DESC',\n track_split_legend_to_y_axis: 2,\n split_tracks: true,\n track_height: 15,\n track_vertical_spacing: 3,\n bounding_box_padding: 2,\n always_hide_legend: false,\n color: '#B8B8B8',\n fill_opacity: 1\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * To define shared highlighting on the track split field define the status node id override\n * to generate an ID common to the track when we're actively splitting data out to separate tracks\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function(element) {\n if (this.layout.split_tracks) {\n return (this.getBaseId() + '-statusnode-' + element[this.layout.track_split_field]).replace(/[:.[\\],]/g, '_');\n }\n return this.getElementId(element) + '-statusnode';\n }.bind(this);\n\n // Helper function to sum layout values to derive total height for a single interval track\n this.getTrackHeight = function() {\n return this.layout.track_height\n + this.layout.track_vertical_spacing\n + (2 * this.layout.bounding_box_padding);\n };\n\n this.tracks = 1;\n this.previous_tracks = 1;\n\n // track-number-indexed object with arrays of interval indexes in the dataset\n this.interval_track_index = { 1: [] };\n\n // After we've loaded interval data interpret it to assign\n // each to a track so that they do not overlap in the view\n this.assignTracks = function() {\n\n // Reinitialize some metadata\n this.previous_tracks = this.tracks;\n this.tracks = 0;\n this.interval_track_index = { 1: [] };\n this.track_split_field_index = {};\n\n // If splitting tracks by a field's value then do a first pass determine\n // a value/track mapping that preserves the order of possible values\n if (this.layout.track_split_field && this.layout.split_tracks) {\n this.data.map(function(d) {\n this.track_split_field_index[d[this.layout.track_split_field]] = null;\n }.bind(this));\n var index = Object.keys(this.track_split_field_index);\n if (this.layout.track_split_order === 'DESC') { index.reverse(); }\n index.forEach(function(val) {\n this.track_split_field_index[val] = this.tracks + 1;\n this.interval_track_index[this.tracks + 1] = [];\n this.tracks++;\n }.bind(this));\n }\n\n this.data.map(function(d, i) {\n\n // Stash a parent reference on the interval\n this.data[i].parent = this;\n\n // Determine display range start and end, based on minimum allowable interval display width,\n // bounded by what we can see (range: values in terms of pixels on the screen)\n this.data[i].display_range = {\n start: this.parent.x_scale(Math.max(d[this.layout.start_field], this.state.start)),\n end: this.parent.x_scale(Math.min(d[this.layout.end_field], this.state.end))\n };\n this.data[i].display_range.width = this.data[i].display_range.end - this.data[i].display_range.start;\n\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[i].display_domain = {\n start: this.parent.x_scale.invert(this.data[i].display_range.start),\n end: this.parent.x_scale.invert(this.data[i].display_range.end)\n };\n this.data[i].display_domain.width = this.data[i].display_domain.end - this.data[i].display_domain.start;\n\n // If splitting to tracks based on the value of the designated track split field\n // then don't bother with collision detection (intervals will be grouped on tracks\n // solely by the value of track_split_field)\n if (this.layout.track_split_field && this.layout.split_tracks) {\n var val = this.data[i][this.layout.track_split_field];\n this.data[i].track = this.track_split_field_index[val];\n this.interval_track_index[this.data[i].track].push(i);\n } else {\n // If not splitting to tracks based on a field value then do so based on collision\n // detection (as how it's done for genes). Use display range/domain data generated\n // above and cast each interval to tracks such that none overlap\n this.tracks = 1;\n this.data[i].track = null;\n var potential_track = 1;\n while (this.data[i].track === null) {\n var collision_on_potential_track = false;\n this.interval_track_index[potential_track].map(function(placed_interval) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_interval.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_interval.display_range.end, this.display_range.end);\n if ((max_end - min_start) < (placed_interval.display_range.width + this.display_range.width)) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[i]));\n if (!collision_on_potential_track) {\n this.data[i].track = potential_track;\n this.interval_track_index[potential_track].push(this.data[i]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.interval_track_index[potential_track] = [];\n }\n }\n }\n\n }\n\n }.bind(this));\n\n return this;\n };\n\n // Implement the main render function\n this.render = function() {\n\n this.assignTracks();\n\n // Remove any shared highlight nodes and re-render them if we're splitting on tracks\n // At most there will only be dozen or so nodes here (one per track) and each time\n // we render data we may have new tracks, so wiping/redrawing all is reasonable.\n this.svg.group.selectAll('.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-shared').remove();\n Object.keys(this.track_split_field_index).forEach(function(key) {\n // Make a psuedo-element so that we can generate an id for the shared node\n var psuedoElement = {};\n psuedoElement[this.layout.track_split_field] = key;\n // Insert the shared node\n var sharedstatusnode_style = {display: (this.layout.split_tracks ? null : 'none')};\n this.svg.group.insert('rect', ':first-child')\n .attr('id', this.getElementStatusNodeId(psuedoElement))\n .attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-shared')\n .attr('rx', this.layout.bounding_box_padding).attr('ry', this.layout.bounding_box_padding)\n .attr('width', this.parent.layout.cliparea.width)\n .attr('height', this.getTrackHeight() - this.layout.track_vertical_spacing)\n .attr('x', 0)\n .attr('y', (this.track_split_field_index[key] - 1) * this.getTrackHeight())\n .style(sharedstatusnode_style);\n }.bind(this));\n\n var width, height, x, y, fill, fill_opacity;\n\n // Render interval groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-intervals')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n selection.enter().append('g')\n .attr('class', 'lz-data_layer-intervals');\n\n selection.attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .each(function(interval) {\n\n var data_layer = interval.parent;\n\n // Render interval status nodes (displayed behind intervals to show highlight\n // without needing to modify interval display element(s))\n var statusnode_style = {display: (data_layer.layout.split_tracks ? 'none' : null)};\n var statusnodes = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-statusnode-discrete')\n .data([interval], function(d) { return data_layer.getElementId(d) + '-statusnode'; });\n statusnodes.enter().insert('rect', ':first-child')\n .attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-statusnode-discrete');\n statusnodes\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '-statusnode';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .style(statusnode_style);\n width = function(d) {\n return d.display_range.width + (2 * data_layer.layout.bounding_box_padding);\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start - data_layer.layout.bounding_box_padding;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n statusnodes\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n statusnodes\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n statusnodes.exit().remove();\n\n // Render primary interval rects\n var rects = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-interval_rect')\n .data([interval], function(d) { return d[data_layer.layout.id_field] + '_interval_rect'; });\n\n rects.enter().append('rect')\n .attr('class', 'lz-data_layer-intervals lz-interval_rect');\n\n height = data_layer.layout.track_height;\n width = function(d) {\n return d.display_range.width;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding;\n };\n fill = function(d) {\n return data_layer.resolveScalableParameter(data_layer.layout.color, d);\n };\n fill_opacity = function(d) {\n return data_layer.resolveScalableParameter(data_layer.layout.fill_opacity, d);\n };\n\n\n if (data_layer.canTransition()) {\n rects\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height)\n .attr('x', x).attr('y', y)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity);\n } else {\n rects\n .attr('width', width).attr('height', height)\n .attr('x', x).attr('y', y)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity);\n }\n\n rects.exit().remove();\n\n // Render interval click areas\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-clickarea')\n .data([interval], function(d) { return d.interval_name + '_clickarea'; });\n\n clickareas.enter().append('rect')\n .attr('class', 'lz-data_layer-intervals lz-clickarea');\n\n clickareas\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '_clickarea';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n clickareas\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n // Remove old clickareas as needed\n clickareas.exit().remove();\n\n // Apply default event emitters to clickareas\n clickareas.on('click', function(element_data) {\n element_data.parent.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n\n });\n\n // Remove old elements as needed\n selection.exit().remove();\n\n // Update the legend axis if the number of ticks changed\n if (this.previous_tracks !== this.tracks) {\n this.updateSplitTrackAxis();\n }\n\n return this;\n\n };\n\n // Reimplement the positionTooltip() method to be interval-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var interval_bbox = d3.select('#' + this.getElementStatusNodeId(tooltip.data)).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the interval that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var interval_center_x = ((tooltip.data.display_range.start + tooltip.data.display_range.end) / 2) - (this.layout.bounding_box_padding / 2);\n var offset_right = Math.max((tooltip_box.width / 2) - interval_center_x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + interval_center_x - data_layer_width, 0);\n var left = page_origin.x + interval_center_x - (tooltip_box.width / 2) - offset_left + offset_right;\n var arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right;\n // Position vertically below the interval unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (interval_bbox.y + interval_bbox.height)) {\n top = page_origin.y + interval_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + interval_bbox.y + interval_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Redraw split track axis or hide it, and show/hide the legend, as determined\n // by current layout parameters and data\n this.updateSplitTrackAxis = function() {\n var legend_axis = this.layout.track_split_legend_to_y_axis ? 'y' + this.layout.track_split_legend_to_y_axis : false;\n if (this.layout.split_tracks) {\n var tracks = +this.tracks || 0;\n var track_height = +this.layout.track_height || 0;\n var track_spacing = 2 * (+this.layout.bounding_box_padding || 0) + (+this.layout.track_vertical_spacing || 0);\n var target_height = (tracks * track_height) + ((tracks - 1) * track_spacing);\n this.parent.scaleHeightToData(target_height);\n if (legend_axis && this.parent.legend) {\n this.parent.legend.hide();\n this.parent.layout.axes[legend_axis] = {\n render: true,\n ticks: [],\n range: {\n start: (target_height - (this.layout.track_height / 2)),\n end: (this.layout.track_height / 2)\n }\n };\n this.layout.legend.forEach(function(element) {\n var key = element[this.layout.track_split_field];\n var track = this.track_split_field_index[key];\n if (track) {\n if (this.layout.track_split_order === 'DESC') {\n track = Math.abs(track - tracks - 1);\n }\n this.parent.layout.axes[legend_axis].ticks.push({\n y: track,\n text: element.label\n });\n }\n }.bind(this));\n this.layout.y_axis = {\n axis: this.layout.track_split_legend_to_y_axis,\n floor: 1,\n ceiling: tracks\n };\n this.parent.render();\n }\n this.parent_plot.positionPanels();\n } else {\n if (legend_axis && this.parent.legend) {\n if (!this.layout.always_hide_legend) { this.parent.legend.show(); }\n this.parent.layout.axes[legend_axis] = { render: false };\n this.parent.render();\n }\n }\n return this;\n };\n\n // Method to not only toggle the split tracks boolean but also update\n // necessary display values to animate a complete merge/split\n this.toggleSplitTracks = function() {\n this.layout.split_tracks = !this.layout.split_tracks;\n if (this.parent.legend && !this.layout.always_hide_legend) {\n this.parent.layout.margin.bottom = 5 + (this.layout.split_tracks ? 0 : this.parent.legend.layout.height + 5);\n }\n this.render();\n this.updateSplitTrackAxis();\n return this;\n };\n\n return this;\n\n});\n","'use strict';\n\n/*********************\n * Line Data Layer\n * Implements a standard line plot, representing either a trace or a filled curve.\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('line', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n /** @member {Object} */\n this.DefaultLayout = {\n style: {\n fill: 'none',\n 'stroke-width': '2px'\n },\n interpolate: 'linear',\n x_axis: { field: 'x' },\n y_axis: { field: 'y', axis: 1 },\n hitarea_width: 5\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Var for storing mouse events for use in tool tip positioning\n /** @member {String} */\n this.mouse_event = null;\n\n /**\n * Var for storing the generated line function itself\n * @member {d3.svg.line}\n * */\n this.line = null;\n\n /**\n * The timeout identifier returned by setTimeout\n * @member {Number}\n */\n this.tooltip_timeout = null;\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n\n /**\n * Helper function to get display and data objects representing\n * the x/y coordinates of the current mouse event with respect to the line in terms of the display\n * and the interpolated values of the x/y fields with respect to the line\n * @returns {{display: {x: *, y: null}, data: {}, slope: null}}\n */\n this.getMouseDisplayAndData = function() {\n var ret = {\n display: {\n x: d3.mouse(this.mouse_event)[0],\n y: null\n },\n data: {},\n slope: null\n };\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n ret.data[x_field] = this.parent[x_scale].invert(ret.display.x);\n var bisect = d3.bisector(function(datum) { return +datum[x_field]; }).left;\n var index = bisect(this.data, ret.data[x_field]) - 1;\n var startDatum = this.data[index];\n var endDatum = this.data[index + 1];\n var interpolate = d3.interpolateNumber(+startDatum[y_field], +endDatum[y_field]);\n var range = +endDatum[x_field] - +startDatum[x_field];\n ret.data[y_field] = interpolate((ret.data[x_field] % range) / range);\n ret.display.y = this.parent[y_scale](ret.data[y_field]);\n if (this.layout.tooltip.x_precision) {\n ret.data[x_field] = ret.data[x_field].toPrecision(this.layout.tooltip.x_precision);\n }\n if (this.layout.tooltip.y_precision) {\n ret.data[y_field] = ret.data[y_field].toPrecision(this.layout.tooltip.y_precision);\n }\n ret.slope = (this.parent[y_scale](endDatum[y_field]) - this.parent[y_scale](startDatum[y_field]))\n / (this.parent[x_scale](endDatum[x_field]) - this.parent[x_scale](startDatum[x_field]));\n return ret;\n };\n\n /**\n * Reimplement the positionTooltip() method to be line-specific\n * @param {String} id Identify the tooltip to be positioned\n */\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var arrow_width = 7; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var stroke_width = parseFloat(this.layout.style['stroke-width']) || 1;\n var page_origin = this.getPageOrigin();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n var top, left, arrow_top, arrow_left, arrow_type;\n\n // Determine x/y coordinates for display and data\n var dd = this.getMouseDisplayAndData();\n\n // If the absolute value of the slope of the line at this point is above 1 (including Infinity)\n // then position the tool tip left/right. Otherwise position top/bottom.\n if (Math.abs(dd.slope) > 1) {\n\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (dd.display.x <= this.parent.layout.width / 2) {\n left = page_origin.x + dd.display.x + stroke_width + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + dd.display.x - tooltip_box.width - stroke_width - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n if (dd.display.y - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + dd.display.y - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (dd.display.y + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + dd.display.y + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + dd.display.y - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n\n } else {\n\n // Position horizontally: attempt to center on the mouse's x coordinate\n // pad to either side if bumping up against the edge of the data layer\n var offset_right = Math.max((tooltip_box.width / 2) - dd.display.x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + dd.display.x - data_layer_width, 0);\n left = page_origin.x + dd.display.x - (tooltip_box.width / 2) - offset_left + offset_right;\n var min_arrow_left = arrow_width / 2;\n var max_arrow_left = tooltip_box.width - (2.5 * arrow_width);\n arrow_left = (tooltip_box.width / 2) - arrow_width + offset_left - offset_right;\n arrow_left = Math.min(Math.max(arrow_left, min_arrow_left), max_arrow_left);\n\n // Position vertically above the line unless there's insufficient space\n if (tooltip_box.height + stroke_width + arrow_width > dd.display.y) {\n top = page_origin.y + dd.display.y + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n } else {\n top = page_origin.y + dd.display.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n }\n }\n\n // Apply positions to the main div\n tooltip.selector.style({ left: left + 'px', top: top + 'px' });\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style({ 'left': arrow_left + 'px', top: arrow_top + 'px' });\n\n };\n\n /**\n * Implement the main render function\n */\n this.render = function() {\n\n // Several vars needed to be in scope\n var data_layer = this;\n var panel = this.parent;\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n // Join data to the line selection\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-line')\n .data([this.data]);\n\n // Create path element, apply class\n this.path = selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line');\n\n // Generate the line\n if (this.layout.style.fill && this.layout.style.fill !== 'none') {\n // Filled curve: define the line as a filled boundary\n this.line = d3.svg.area()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y0(function(d) {return parseFloat(panel[y_scale](0));})\n .y1(function(d) { return parseFloat(panel[y_scale](d[y_field])); });\n } else {\n // Basic line\n this.line = d3.svg.line()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y(function(d) { return parseFloat(panel[y_scale](d[y_field])); })\n .interpolate(this.layout.interpolate);\n }\n\n // Apply line and style\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('d', this.line)\n .style(this.layout.style);\n } else {\n selection\n .attr('d', this.line)\n .style(this.layout.style);\n }\n\n // Apply tooltip, etc\n if (this.layout.tooltip) {\n // Generate an overlaying transparent \"hit area\" line for more intuitive mouse events\n var hitarea_width = parseFloat(this.layout.hitarea_width).toString() + 'px';\n var hitarea = this.svg.group\n .selectAll('path.lz-data_layer-line-hitarea')\n .data([this.data]);\n hitarea.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line-hitarea')\n .style('stroke-width', hitarea_width);\n var hitarea_line = d3.svg.line()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y(function(d) { return parseFloat(panel[y_scale](d[y_field])); })\n .interpolate(this.layout.interpolate);\n hitarea\n .attr('d', hitarea_line)\n .on('mouseover', function() {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.createTooltip(dd.data);\n })\n .on('mousemove', function() {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.updateTooltip(dd.data);\n data_layer.positionTooltip(data_layer.getElementId());\n })\n .on('mouseout', function() {\n data_layer.tooltip_timeout = setTimeout(function() {\n data_layer.mouse_event = null;\n data_layer.destroyTooltip(data_layer.getElementId());\n }, 300);\n });\n hitarea.exit().remove();\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n /**\n * Redefine setElementStatus family of methods as line data layers will only ever have a single path element\n * @param {String} status A member of `LocusZoom.DataLayer.Statuses.adjectives`\n * @param {String|Object} element\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\n this.setElementStatus = function(status, element, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setElementStatusByFilters = function(status, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setAllElementStatus = function(status, toggle) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; }\n\n // Update global status flag\n this.global_statuses[status] = toggle;\n\n // Apply class to path based on global status flags\n var path_class = 'lz-data_layer-line';\n Object.keys(this.global_statuses).forEach(function(global_status) {\n if (this.global_statuses[global_status]) { path_class += ' lz-data_layer-line-' + global_status; }\n }.bind(this));\n this.path.attr('class', path_class);\n\n // Trigger layout changed event hook\n this.parent.emit('layout_changed', true);\n return this;\n };\n\n return this;\n\n});\n\n\n/***************************\n * Orthogonal Line Data Layer\n * Implements a horizontal or vertical line given an orientation and an offset in the layout\n * Does not require a data source\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('orthogonal_line', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n style: {\n 'stroke': '#D3D3D3',\n 'stroke-width': '3px',\n 'stroke-dasharray': '10px 10px'\n },\n orientation: 'horizontal',\n x_axis: {\n axis: 1,\n decoupled: true\n },\n y_axis: {\n axis: 1,\n decoupled: true\n },\n offset: 0\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Require that orientation be \"horizontal\" or \"vertical\" only\n if (['horizontal','vertical'].indexOf(layout.orientation) === -1) {\n layout.orientation = 'horizontal';\n }\n\n // Vars for storing the data generated line\n /** @member {Array} */\n this.data = [];\n /** @member {d3.svg.line} */\n this.line = null;\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * Implement the main render function\n */\n this.render = function() {\n\n // Several vars needed to be in scope\n var panel = this.parent;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var x_extent = 'x_extent';\n var y_extent = 'y' + this.layout.y_axis.axis + '_extent';\n var x_range = 'x_range';\n\n // Generate data using extents depending on orientation\n if (this.layout.orientation === 'horizontal') {\n this.data = [\n { x: panel[x_extent][0], y: this.layout.offset },\n { x: panel[x_extent][1], y: this.layout.offset }\n ];\n } else if (this.layout.orientation === 'vertical') {\n this.data = [\n { x: this.layout.offset, y: panel[y_extent][0] },\n { x: this.layout.offset, y: panel[y_extent][1] }\n ];\n } else {\n throw new Error('Unrecognized vertical line type. Must be \"vertical\" or \"horizontal\"');\n }\n\n // Join data to the line selection\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-line')\n .data([this.data]);\n\n // Create path element, apply class\n this.path = selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line');\n\n // In some cases, a vertical line may overlay a track that has no inherent y-values (extent)\n // When that happens, provide a default height based on the current panel dimensions (accounting\n // for any resizing that happened after the panel was created)\n var default_y = [panel.layout.cliparea.height, 0];\n\n // Generate the line\n this.line = d3.svg.line()\n .x(function(d, i) {\n var x = parseFloat(panel[x_scale](d['x']));\n return isNaN(x) ? panel[x_range][i] : x;\n })\n .y(function(d, i) {\n var y = parseFloat(panel[y_scale](d['y']));\n return isNaN(y) ? default_y[i] : y;\n })\n .interpolate('linear');\n\n // Apply line and style\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('d', this.line)\n .style(this.layout.style);\n } else {\n selection\n .attr('d', this.line)\n .style(this.layout.style);\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n return this;\n\n});\n","'use strict';\n\n/**\n * Scatter Data Layer\n * Implements a standard scatter plot\n * @class LocusZoom.DataLayers.scatter\n */\nLocusZoom.DataLayers.add('scatter', function(layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'circle',\n tooltip_positioning: 'horizontal',\n color: '#888888',\n fill_opacity: 1,\n y_axis: {\n axis: 1\n },\n id_field: 'id'\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Extra default for layout spacing\n // Not in default layout since that would make the label attribute always present\n if (layout.label && isNaN(layout.label.spacing)) {\n layout.label.spacing = 4;\n }\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Reimplement the positionTooltip() method to be scatter-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var offset = Math.sqrt(point_size / Math.PI);\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n if (this.layout.tooltip_positioning === 'vertical') {\n // Position horizontally centered above the point\n var offset_right = Math.max((tooltip_box.width / 2) - x_center, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - (tooltip_box.width / 2) - offset_left + offset_right;\n arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right - offset;\n // Position vertically above the point unless there's insufficient space, then go below\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (y_center + offset)) {\n top = page_origin.y + y_center - (offset + tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + y_center + offset + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n } else {\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n if (y_center - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + y_center - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (y_center + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + y_center - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Function to flip labels from being anchored at the start of the text to the end\n // Both to keep labels from running outside the data layer and also as a first\n // pass on recursive separation\n this.flip_labels = function() {\n var data_layer = this;\n var point_size = data_layer.resolveScalableParameter(data_layer.layout.point_size, {});\n var spacing = data_layer.layout.label.spacing;\n var handle_lines = Boolean(data_layer.layout.label.lines);\n var min_x = 2 * spacing;\n var max_x = data_layer.parent.layout.width - data_layer.parent.layout.margin.left - data_layer.parent.layout.margin.right - (2 * spacing);\n var flip = function(dn, dnl) {\n var dnx = +dn.attr('x');\n var text_swing = (2 * spacing) + (2 * Math.sqrt(point_size));\n if (handle_lines) {\n var dnlx2 = +dnl.attr('x2');\n var line_swing = spacing + (2 * Math.sqrt(point_size));\n }\n if (dn.style('text-anchor') === 'start') {\n dn.style('text-anchor', 'end');\n dn.attr('x', dnx - text_swing);\n if (handle_lines) { dnl.attr('x2', dnlx2 - line_swing); }\n } else {\n dn.style('text-anchor', 'start');\n dn.attr('x', dnx + text_swing);\n if (handle_lines) { dnl.attr('x2', dnlx2 + line_swing); }\n }\n };\n // Flip any going over the right edge from the right side to the left side\n // (all labels start on the right side)\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n if (dax + abound.width + spacing > max_x) {\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n flip(da, dal);\n }\n });\n // Second pass to flip any others that haven't flipped yet if they collide with another label\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n if (da.style('text-anchor') === 'end') {\n return;\n }\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n data_layer.label_texts.each(function () {\n var b = this;\n var db = d3.select(b);\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + (2 * spacing) &&\n abound.left + abound.width + (2 * spacing) > bbound.left &&\n abound.top < bbound.top + bbound.height + (2 * spacing) &&\n abound.height + abound.top + (2 * spacing) > bbound.top;\n if (collision) {\n flip(da, dal);\n // Double check that this flip didn't push the label past min_x. If it did, immediately flip back.\n dax = +da.attr('x');\n if (dax - abound.width - spacing < min_x) {\n flip(da, dal);\n }\n }\n return;\n });\n });\n };\n\n // Recursive function to space labels apart immediately after initial render\n // Adapted from thudfactor's fiddle here: https://jsfiddle.net/thudfactor/HdwTH/\n // TODO: Make labels also aware of data elements\n this.separate_labels = function() {\n this.seperate_iterations++;\n var data_layer = this;\n var alpha = 0.5;\n if (!this.layout.label) {\n // Guard against layout changing in the midst of iterative rerender\n return;\n }\n var spacing = this.layout.label.spacing;\n var again = false;\n data_layer.label_texts.each(function () {\n var a = this;\n var da = d3.select(a);\n var y1 = da.attr('y');\n data_layer.label_texts.each(function () {\n var b = this;\n // a & b are the same element and don't collide.\n if (a === b) {\n return;\n }\n var db = d3.select(b);\n // a & b are on opposite sides of the chart and\n // don't collide\n if (da.attr('text-anchor') !== db.attr('text-anchor')) {\n return;\n }\n // Determine if the bounding rects for the two text elements collide\n var abound = da.node().getBoundingClientRect();\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + (2 * spacing) &&\n abound.left + abound.width + (2 * spacing) > bbound.left &&\n abound.top < bbound.top + bbound.height + (2 * spacing) &&\n abound.height + abound.top + (2 * spacing) > bbound.top;\n if (!collision) {\n return;\n }\n again = true;\n // If the labels collide, we'll push each\n // of the two labels up and down a little bit.\n var y2 = db.attr('y');\n var sign = abound.top < bbound.top ? 1 : -1;\n var adjust = sign * alpha;\n var new_a_y = +y1 - adjust;\n var new_b_y = +y2 + adjust;\n // Keep new values from extending outside the data layer\n var min_y = 2 * spacing;\n var max_y = data_layer.parent.layout.height - data_layer.parent.layout.margin.top - data_layer.parent.layout.margin.bottom - (2 * spacing);\n var delta;\n if (new_a_y - (abound.height / 2) < min_y) {\n delta = +y1 - new_a_y;\n new_a_y = +y1;\n new_b_y += delta;\n } else if (new_b_y - (bbound.height / 2) < min_y) {\n delta = +y2 - new_b_y;\n new_b_y = +y2;\n new_a_y += delta;\n }\n if (new_a_y + (abound.height / 2) > max_y) {\n delta = new_a_y - +y1;\n new_a_y = +y1;\n new_b_y -= delta;\n } else if (new_b_y + (bbound.height / 2) > max_y) {\n delta = new_b_y - +y2;\n new_b_y = +y2;\n new_a_y -= delta;\n }\n da.attr('y',new_a_y);\n db.attr('y',new_b_y);\n });\n });\n if (again) {\n // Adjust lines to follow the labels\n if (data_layer.layout.label.lines) {\n var label_elements = data_layer.label_texts[0];\n data_layer.label_lines.attr('y2',function(d,i) {\n var label_line = d3.select(label_elements[i]);\n return label_line.attr('y');\n });\n }\n // After ~150 iterations we're probably beyond diminising returns, so stop recursing\n if (this.seperate_iterations < 150) {\n setTimeout(function() {\n this.separate_labels();\n }.bind(this), 1);\n }\n }\n };\n\n // Implement the main render function\n this.render = function() {\n\n var data_layer = this;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n if (this.layout.label) {\n // Apply filters to generate a filtered data set\n var filtered_data = this.data.filter(function(d) {\n if (!data_layer.layout.label.filters) {\n return true;\n } else {\n // Start by assuming a match, run through all filters to test if not a match on any one\n var match = true;\n data_layer.layout.label.filters.forEach(function(filter) {\n var field_value = (new LocusZoom.Data.Field(filter.field)).resolve(d);\n if (['!=', '='].indexOf(filter.operator) === -1 && isNaN(field_value)) {\n // If the filter can only be used with numbers, then the value must be numeric.\n match = false;\n } else {\n switch (filter.operator) {\n case '<':\n if (!(field_value < filter.value)) { match = false; }\n break;\n case '<=':\n if (!(field_value <= filter.value)) { match = false; }\n break;\n case '>':\n if (!(field_value > filter.value)) { match = false; }\n break;\n case '>=':\n if (!(field_value >= filter.value)) { match = false; }\n break;\n case '=':\n if (!(field_value === filter.value)) { match = false; }\n break;\n case '!=':\n // Deliberately allow weak comparisons to test for \"anything with a value present\" (null or undefined)\n // eslint-disable-next-line eqeqeq\n if (field_value == filter.value) { match = false; }\n break;\n default:\n // If we got here the operator is not valid, so the filter should fail\n match = false;\n break;\n }\n }\n });\n return match;\n }\n });\n // Render label groups\n var self = this;\n this.label_groups = this.svg.group\n .selectAll('g.lz-data_layer-' + this.layout.type + '-label')\n .data(filtered_data, function(d) { return d[self.layout.id_field] + '_label'; });\n this.label_groups.enter()\n .append('g')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n // Render label texts\n if (this.label_texts) { this.label_texts.remove(); }\n this.label_texts = this.label_groups.append('text')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_texts\n .text(function(d) {\n return LocusZoom.parseFields(d, data_layer.layout.label.text || '');\n })\n .style(data_layer.layout.label.style || {})\n .attr({\n 'x': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field])\n + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d))\n + data_layer.layout.label.spacing;\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n },\n 'text-anchor': function() {\n return 'start';\n }\n });\n // Render label lines\n if (data_layer.layout.label.lines) {\n if (this.label_lines) { this.label_lines.remove(); }\n this.label_lines = this.label_groups.append('line')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_lines\n .style(data_layer.layout.label.lines.style || {})\n .attr({\n 'x1': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]);\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y1': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n },\n 'x2': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field])\n + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d))\n + (data_layer.layout.label.spacing / 2);\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y2': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n }\n });\n }\n // Remove labels when they're no longer in the filtered data set\n this.label_groups.exit().remove();\n } else {\n // If the layout definition has changed (& no longer specifies labels), strip any previously rendered\n if (this.label_groups) { this.label_groups.remove(); }\n if (this.label_lines) { this.label_lines.remove(); }\n }\n\n // Generate main scatter data elements\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-' + this.layout.type)\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .attr('transform', 'translate(0,' + initial_y + ')');\n\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n\n var fill = function(d) { return this.resolveScalableParameter(this.layout.color, d); }.bind(this);\n var fill_opacity = function(d) { return this.resolveScalableParameter(this.layout.fill_opacity, d); }.bind(this);\n\n var shape = d3.svg.symbol()\n .size(function(d) { return this.resolveScalableParameter(this.layout.point_size, d); }.bind(this))\n .type(function(d) { return this.resolveScalableParameter(this.layout.point_shape, d); }.bind(this));\n\n // Apply position and color, using a transition if necessary\n\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n } else {\n selection\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n // Apply default event emitters to selection\n selection.on('click.event_emitter', function(element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n\n // Apply mouse behaviors\n this.applyBehaviors(selection);\n\n // Apply method to keep labels from overlapping each other\n if (this.layout.label) {\n this.flip_labels();\n this.seperate_iterations = 0;\n this.separate_labels();\n // Apply default event emitters to selection\n this.label_texts.on('click.event_emitter', function(element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n // Extend mouse behaviors to labels\n this.applyBehaviors(this.label_texts);\n }\n\n };\n\n // Method to set a passed element as the LD reference in the plot-level state\n this.makeLDReference = function(element) {\n var ref = null;\n if (typeof element == 'undefined') {\n throw new Error('makeLDReference requires one argument of any type');\n } else if (typeof element == 'object') {\n if (this.layout.id_field && typeof element[this.layout.id_field] != 'undefined') {\n ref = element[this.layout.id_field].toString();\n } else if (typeof element['id'] != 'undefined') {\n ref = element['id'].toString();\n } else {\n ref = element.toString();\n }\n } else {\n ref = element.toString();\n }\n this.parent_plot.applyState({ ldrefvar: ref });\n };\n\n return this;\n\n});\n\n/**\n * A scatter plot in which the x-axis represents categories, rather than individual positions.\n * For example, this can be used by PheWAS plots to show related groups. This plot allows the categories to be\n * determined dynamically when data is first loaded.\n *\n * @class LocusZoom.DataLayers.category_scatter\n * @augments LocusZoom.DataLayers.scatter\n */\nLocusZoom.DataLayers.extend('scatter', 'category_scatter', {\n /**\n * This plot layer makes certain assumptions about the data passed in. Transform the raw array of records from\n * the datasource to prepare it for plotting, as follows:\n * 1. The scatter plot assumes that all records are given in sequence (pre-grouped by `category_field`)\n * 2. It assumes that all records have an x coordinate for individual plotting\n * @private\n */\n _prepareData: function() {\n var xField = this.layout.x_axis.field || 'x';\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n // Sort the data so that things in the same category are adjacent (case-insensitive by specified field)\n var sourceData = this.data\n .sort(function(a, b) {\n var ak = a[category_field];\n var bk = b[category_field];\n var av = (typeof ak === 'string') ? ak.toLowerCase() : ak;\n var bv = (typeof bk === 'string') ? bk.toLowerCase() : bk;\n return (av === bv) ? 0 : (av < bv ? -1 : 1);});\n sourceData.forEach(function(d, i) {\n // Implementation detail: Scatter plot requires specifying an x-axis value, and most datasources do not\n // specify plotting positions. If a point is missing this field, fill in a synthetic value.\n d[xField] = d[xField] || i;\n });\n return sourceData;\n },\n\n /**\n * Identify the unique categories on the plot, and update the layout with an appropriate color scheme.\n * Also identify the min and max x value associated with the category, which will be used to generate ticks\n * @private\n * @returns {Object.} Series of entries used to build category name ticks {category_name: [min_x, max_x]}\n */\n _generateCategoryBounds: function() {\n // TODO: API may return null values in category_field; should we add placeholder category label?\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n var xField = this.layout.x_axis.field || 'x';\n var uniqueCategories = {};\n this.data.forEach(function(item) {\n var category = item[category_field];\n var x = item[xField];\n var bounds = uniqueCategories[category] || [x, x];\n uniqueCategories[category] = [Math.min(bounds[0], x), Math.max(bounds[1], x)];\n });\n\n var categoryNames = Object.keys(uniqueCategories);\n this._setDynamicColorScheme(categoryNames);\n\n return uniqueCategories;\n },\n\n /**\n * This layer relies on defining its own category-based color scheme. Find the correct color config object to\n * be modified.\n * @param [from_source]\n * @returns {Object} A mutable reference to the layout configuration object\n * @private\n */\n _getColorScale: function(from_source) {\n from_source = from_source || this.layout;\n // If the layout does not use a supported coloring scheme, or is already complete, this method should do nothing\n\n // For legacy reasons, layouts can specify color as an object (only one way to set color), as opposed to the\n // preferred mechanism of array (multiple coloring options)\n var color_params = from_source.color || []; // Object or scalar, no other options allowed\n if (Array.isArray(color_params)) {\n color_params = color_params.find(function(item) { return item.scale_function === 'categorical_bin'; });\n }\n if (!color_params || color_params.scale_function !== 'categorical_bin') {\n throw new Error('This layer requires that color options be provided as a `categorical_bin`');\n }\n return color_params;\n },\n\n /**\n * Automatically define a color scheme for the layer based on data returned from the server.\n * If part of the color scheme has been specified, it will fill in remaining missing information.\n *\n * There are three scenarios:\n * 1. The layout does not specify either category names or (color) values. Dynamically build both based on\n * the data and update the layout.\n * 2. The layout specifies colors, but not categories. Use that exact color information provided, and dynamically\n * determine what categories are present in the data. (cycle through the available colors, reusing if there\n * are a lot of categories)\n * 3. The layout specifies exactly what colors and categories to use (and they match the data!). This is useful to\n * specify an explicit mapping between color scheme and category names, when you want to be sure that the\n * plot matches a standard color scheme.\n * (If the layout specifies categories that do not match the data, the user specified categories will be ignored)\n *\n * This method will only act if the layout defines a `categorical_bin` scale function for coloring. It may be\n * overridden in a subclass to suit other types of coloring methods.\n *\n * @param {String[]} categoryNames\n * @private\n */\n _setDynamicColorScheme: function(categoryNames) {\n var colorParams = this._getColorScale(this.layout).parameters;\n var baseParams = this._getColorScale(this._base_layout).parameters;\n\n if (baseParams.categories.length && baseParams.values.length) {\n // If there are preset category/color combos, make sure that they apply to the actual dataset\n var parameters_categories_hash = {};\n baseParams.categories.forEach(function (category) { parameters_categories_hash[category] = 1; });\n if (categoryNames.every(function (name) { return parameters_categories_hash.hasOwnProperty(name); })) {\n // The layout doesn't have to specify categories in order, but make sure they are all there\n colorParams.categories = baseParams.categories;\n } else {\n colorParams.categories = categoryNames;\n }\n } else {\n colorParams.categories = categoryNames;\n }\n // Prefer user-specified colors if provided. Make sure that there are enough colors for all the categories.\n var colors;\n if (baseParams.values.length) {\n colors = baseParams.values;\n } else {\n var color_scale = categoryNames.length <= 10 ? d3.scale.category10 : d3.scale.category20;\n colors = color_scale().range();\n }\n while (colors.length < categoryNames.length) { colors = colors.concat(colors); }\n colors = colors.slice(0, categoryNames.length); // List of hex values, should be of same length as categories array\n colorParams.values = colors;\n },\n\n /**\n *\n * @param dimension\n * @param {Object} [config] Parameters that customize how ticks are calculated (not style)\n * @param {('left'|'center'|'right')} [config.position='left'] Align ticks with the center or edge of category\n * @returns {Array}\n */\n getTicks: function(dimension, config) { // Overrides parent method\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier');\n }\n var position = config.position || 'left';\n if (['left', 'center', 'right'].indexOf(position) === -1) {\n throw new Error('Invalid tick position');\n }\n\n var categoryBounds = this._categories;\n if (!categoryBounds || !Object.keys(categoryBounds).length) {\n return [];\n }\n\n if (dimension === 'y') {\n return [];\n }\n\n if (dimension === 'x') {\n // If colors have been defined by this layer, use them to make tick colors match scatterplot point colors\n var colors = this._getColorScale(this.layout);\n var knownCategories = colors.parameters.categories || [];\n var knownColors = colors.parameters.values || [];\n\n return Object.keys(categoryBounds).map(function (category, index) {\n var bounds = categoryBounds[category];\n var xPos;\n\n switch(position) {\n case 'left':\n xPos = bounds[0];\n break;\n case 'center':\n // Center tick under one or many elements as appropriate\n var diff = bounds[1] - bounds[0];\n xPos = bounds[0] + (diff !== 0 ? diff : bounds[0]) / 2;\n break;\n case 'right':\n xPos = bounds[1];\n break;\n }\n return {\n x: xPos,\n text: category,\n style: {\n 'fill': knownColors[knownCategories.indexOf(category)] || '#000000'\n }\n };\n });\n }\n },\n\n applyCustomDataMethods: function() {\n this.data = this._prepareData();\n /**\n * Define category names and extents (boundaries) for plotting. TODO: properties in constructor\n * @member {Object.} Category names and extents, in the form {category_name: [min_x, max_x]}\n */\n this._categories = this._generateCategoryBounds();\n return this;\n }\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * An SVG object used to display contextual information about a panel.\n * Panel layouts determine basic features of a legend - its position in the panel, orientation, title, etc.\n * Layouts of child data layers of the panel determine the actual content of the legend.\n *\n * @class\n * @param {LocusZoom.Panel} parent\n*/\nLocusZoom.Legend = function(parent) {\n if (!(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create legend, parent must be a locuszoom panel');\n }\n /** @member {LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.legend';\n\n this.parent.layout.legend = LocusZoom.Layouts.merge(this.parent.layout.legend || {}, LocusZoom.Legend.DefaultLayout);\n /** @member {Object} */\n this.layout = this.parent.layout.legend;\n\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {d3.selection} */\n this.background_rect = null;\n /** @member {d3.selection[]} */\n this.elements = [];\n /**\n * SVG selector for the group containing all elements in the legend\n * @protected\n * @member {d3.selection|null}\n */\n this.elements_group = null;\n\n /**\n * TODO: Not sure if this property is used; the external-facing methods are setting `layout.hidden` instead. Tentatively mark deprecated.\n * @deprecated\n * @protected\n * @member {Boolean}\n */\n this.hidden = false;\n\n // TODO Revisit constructor return value; see https://stackoverflow.com/a/3350364/1422268\n return this.render();\n};\n\n/**\n * The default layout used by legends (used internally)\n * @protected\n * @member {Object}\n */\nLocusZoom.Legend.DefaultLayout = {\n orientation: 'vertical',\n origin: { x: 0, y: 0 },\n width: 10,\n height: 10,\n padding: 5,\n label_size: 12,\n hidden: false\n};\n\n/**\n * Render the legend in the parent panel\n */\nLocusZoom.Legend.prototype.render = function() {\n\n // Get a legend group selector if not yet defined\n if (!this.selector) {\n this.selector = this.parent.svg.group.append('g')\n .attr('id', this.parent.getBaseId() + '.legend').attr('class', 'lz-legend');\n }\n\n // Get a legend background rect selector if not yet defined\n if (!this.background_rect) {\n this.background_rect = this.selector.append('rect')\n .attr('width', 100).attr('height', 100).attr('class', 'lz-legend-background');\n }\n\n // Get a legend elements group selector if not yet defined\n if (!this.elements_group) {\n this.elements_group = this.selector.append('g');\n }\n\n // Remove all elements from the document and re-render from scratch\n this.elements.forEach(function(element) {\n element.remove();\n });\n this.elements = [];\n\n // Gather all elements from data layers in order (top to bottom) and render them\n var padding = +this.layout.padding || 1;\n var x = padding;\n var y = padding;\n var line_height = 0;\n this.parent.data_layer_ids_by_z_index.slice().reverse().forEach(function(id) {\n if (Array.isArray(this.parent.data_layers[id].layout.legend)) {\n this.parent.data_layers[id].layout.legend.forEach(function(element) {\n var selector = this.elements_group.append('g')\n .attr('transform', 'translate(' + x + ',' + y + ')');\n var label_size = +element.label_size || +this.layout.label_size || 12;\n var label_x = 0;\n var label_y = (label_size / 2) + (padding / 2);\n line_height = Math.max(line_height, label_size + padding);\n // Draw the legend element symbol (line, rect, shape, etc)\n if (element.shape === 'line') {\n // Line symbol\n var length = +element.length || 16;\n var path_y = (label_size / 4) + (padding / 2);\n selector.append('path').attr('class', element.class || '')\n .attr('d', 'M0,' + path_y + 'L' + length + ',' + path_y)\n .style(element.style || {});\n label_x = length + padding;\n } else if (element.shape === 'rect') {\n // Rect symbol\n var width = +element.width || 16;\n var height = +element.height || width;\n selector.append('rect').attr('class', element.class || '')\n .attr('width', width).attr('height', height)\n .attr('fill', element.color || {})\n .style(element.style || {});\n label_x = width + padding;\n line_height = Math.max(line_height, height + padding);\n } else if (d3.svg.symbolTypes.indexOf(element.shape) !== -1) {\n // Shape symbol (circle, diamond, etc.)\n var size = +element.size || 40;\n var radius = Math.ceil(Math.sqrt(size / Math.PI));\n selector.append('path').attr('class', element.class || '')\n .attr('d', d3.svg.symbol().size(size).type(element.shape))\n .attr('transform', 'translate(' + radius + ',' + (radius + (padding / 2)) + ')')\n .attr('fill', element.color || {})\n .style(element.style || {});\n label_x = (2 * radius) + padding;\n label_y = Math.max((2 * radius) + (padding / 2), label_y);\n line_height = Math.max(line_height, (2 * radius) + padding);\n }\n // Draw the legend element label\n selector.append('text').attr('text-anchor', 'left').attr('class', 'lz-label')\n .attr('x', label_x).attr('y', label_y).style({'font-size': label_size}).text(element.label);\n // Position the legend element group based on legend layout orientation\n var bcr = selector.node().getBoundingClientRect();\n if (this.layout.orientation === 'vertical') {\n y += bcr.height + padding;\n line_height = 0;\n } else {\n // Ensure this element does not exceed the panel width\n // (E.g. drop to the next line if it does, but only if it's not the only element on this line)\n var right_x = this.layout.origin.x + x + bcr.width;\n if (x > padding && right_x > this.parent.layout.width) {\n y += line_height;\n x = padding;\n selector.attr('transform', 'translate(' + x + ',' + y + ')');\n }\n x += bcr.width + (3 * padding);\n }\n // Store the element\n this.elements.push(selector);\n }.bind(this));\n }\n }.bind(this));\n\n // Scale the background rect to the elements in the legend\n var bcr = this.elements_group.node().getBoundingClientRect();\n this.layout.width = bcr.width + (2 * this.layout.padding);\n this.layout.height = bcr.height + (2 * this.layout.padding);\n this.background_rect\n .attr('width', this.layout.width)\n .attr('height', this.layout.height);\n\n // Set the visibility on the legend from the \"hidden\" flag\n // TODO: `show()` and `hide()` call a full rerender; might be able to make this more lightweight?\n this.selector.style({ visibility: this.layout.hidden ? 'hidden' : 'visible' });\n\n // TODO: Annotate return type and make consistent\n return this.position();\n};\n\n/**\n * Place the legend in position relative to the panel, as specified in the layout configuration\n * @returns {LocusZoom.Legend | null}\n * TODO: should this always be chainable?\n */\nLocusZoom.Legend.prototype.position = function() {\n if (!this.selector) { return this; }\n var bcr = this.selector.node().getBoundingClientRect();\n if (!isNaN(+this.layout.pad_from_bottom)) {\n this.layout.origin.y = this.parent.layout.height - bcr.height - +this.layout.pad_from_bottom;\n }\n if (!isNaN(+this.layout.pad_from_right)) {\n this.layout.origin.x = this.parent.layout.width - bcr.width - +this.layout.pad_from_right;\n }\n this.selector.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n};\n\n/**\n * Hide the legend (triggers a re-render)\n * @public\n */\nLocusZoom.Legend.prototype.hide = function() {\n this.layout.hidden = true;\n this.render();\n};\n\n/**\n * Show the legend (triggers a re-render)\n * @public\n */\nLocusZoom.Legend.prototype.show = function() {\n this.layout.hidden = false;\n this.render();\n};\n","/* global LocusZoom */\n'use strict';\n\n/**\n * An independent LocusZoom object that renders a unique set of data and subpanels.\n * Many such LocusZoom objects can exist simultaneously on a single page, each having its own layout.\n *\n * This creates a new plot instance, but does not immediately render it. For practical use, it may be more convenient\n * to use the `LocusZoom.populate` helper method.\n *\n * @class\n * @param {String} id The ID of the plot. Often corresponds to the ID of the container element on the page\n * where the plot is rendered..\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n*/\nLocusZoom.Plot = function(id, datasource, layout) {\n /** @member Boolean} */\n this.initialized = false;\n // TODO: This makes sense for all other locuszoom elements to have; determine whether this is interface boilerplate or something that can be removed\n this.parent_plot = this;\n\n /** @member {String} */\n this.id = id;\n\n /** @member {Element} */\n this.container = null;\n /**\n * Selector for a node that will contain the plot. (set externally by populate methods)\n * @member {d3.selection}\n */\n this.svg = null;\n\n /** @member {Object.} */\n this.panels = {};\n /**\n * TODO: This is currently used by external classes that manipulate the parent and may indicate room for a helper method in the api to coordinate boilerplate\n * @protected\n * @member {String[]}\n */\n this.panel_ids_by_y_index = [];\n\n /**\n * Notify each child panel of the plot of changes in panel ordering/ arrangement\n */\n this.applyPanelYIndexesToPanelLayouts = function() {\n this.panel_ids_by_y_index.forEach(function(pid, idx) {\n this.panels[pid].layout.y_index = idx;\n }.bind(this));\n };\n\n /**\n * Get the qualified ID pathname for the plot\n * @returns {String}\n */\n this.getBaseId = function() {\n return this.id;\n };\n\n /**\n * Track update operations (reMap) performed on all child panels, and notify the parent plot when complete\n * TODO: Reconsider whether we need to be tracking this as global state outside of context of specific operations\n * @protected\n * @member {Promise[]}\n */\n this.remap_promises = [];\n\n if (typeof layout == 'undefined') {\n /**\n * The layout is a serializable object used to describe the composition of the Plot\n * If no layout was passed, use the Standard Association Layout\n * Otherwise merge whatever was passed with the Default Layout\n * TODO: Review description; we *always* merge with default layout?\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge({}, LocusZoom.Layouts.get('plot', 'standard_association'));\n } else {\n this.layout = layout;\n }\n LocusZoom.Layouts.merge(this.layout, LocusZoom.Plot.DefaultLayout);\n\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original plot state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n\n\n /**\n * Create a shortcut to the state in the layout on the Plot. Tracking in the layout allows the plot to be created\n * with initial state/setup.\n *\n * Tracks state of the plot, eg start and end position\n * @member {Object}\n */\n this.state = this.layout.state;\n\n /** @member {LocusZoom.Data.Requester} */\n this.lzd = new LocusZoom.Data.Requester(datasource);\n\n /**\n * Window.onresize listener (responsive layouts only)\n * TODO: .on appears to return a selection, not a listener? Check logic here\n * https://github.com/d3/d3-selection/blob/00b904b9bcec4dfaf154ae0bbc777b1fc1d7bc08/test/selection/on-test.js#L11\n * @deprecated\n * @member {d3.selection}\n */\n this.window_onresize = null;\n\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [], // Select or unselect\n 'element_selection': [], // Element becomes active (only)\n 'match_requested': [], // A data layer is attempting to highlight matching points (internal use only)\n 'panel_removed': [],\n 'state_changed': [] // Only triggered when a state change causes rerender\n };\n\n /**\n * @callback eventCallback\n * @param {object} eventData A description of the event\n * @param {String|null} eventData.sourceID The unique identifier (eg plot or parent name) of the element that\n * triggered the event. Will be automatically filled in if not explicitly provided.\n * @param {Object|null} eventData.context Any additional information to be passed to the callback, eg the data\n * associated with a clicked plot element\n */\n\n /**\n * There are several events that a LocusZoom plot can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following plot-level events are currently supported:\n * - `layout_changed` - context: plot - Any aspect of the plot's layout (including dimensions or state) has changed.\n * - `data_requested` - context: plot - A request for new data from any data source used in the plot has been made.\n * - `data_rendered` - context: plot - Data from a request has been received and rendered in the plot.\n * - `element_clicked` - context: plot - A data element in any of the plot's data layers has been clicked.\n * - `element_selection` - context: plot - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `plot.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * plot itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} hook\n * @returns {function} The registered event listener\n */\n this.on = function(event, hook) {\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Plot}\n */\n this.off = function(event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n * @param {string} event A known event name\n * @param {*} eventData Data or event description that will be passed to the event listener\n * @returns {LocusZoom.Plot}\n */\n this.emit = function(event, eventData) {\n // TODO: there are small differences between the emit implementation between plots and panels. In the future,\n // DRY this code via mixins, and make sure to keep the interfaces compatible when refactoring.\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n var sourceID = this.getBaseId();\n var self = this;\n this.event_hooks[event].forEach(function(hookToRun) {\n var eventContext;\n if (eventData && eventData.sourceID) {\n // If we detect that an event originated elsewhere (via bubbling or externally), preserve the context\n // when re-emitting the event to plot-level listeners\n eventContext = eventData;\n } else {\n eventContext = {sourceID: sourceID, data: eventData || null};\n }\n // By default, any handlers fired here (either directly, or bubbled) will see the plot as the\n // value of `this`. If a bound function is registered as a handler, the previously bound `this` will\n // override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n return this;\n };\n\n /**\n * Get an object with the x and y coordinates of the plot's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the plot\n * @returns {{x: Number, y: Number, width: Number, height: Number}}\n */\n this.getPageOrigin = function() {\n var bounding_client_rect = this.svg.node().getBoundingClientRect();\n var x_offset = document.documentElement.scrollLeft || document.body.scrollLeft;\n var y_offset = document.documentElement.scrollTop || document.body.scrollTop;\n var container = this.svg.node();\n while (container.parentNode !== null) {\n container = container.parentNode;\n if (container !== document && d3.select(container).style('position') !== 'static') {\n x_offset = -1 * container.getBoundingClientRect().left;\n y_offset = -1 * container.getBoundingClientRect().top;\n break;\n }\n }\n return {\n x: x_offset + bounding_client_rect.left,\n y: y_offset + bounding_client_rect.top,\n width: bounding_client_rect.width,\n height: bounding_client_rect.height\n };\n };\n\n /**\n * Get the top and left offset values for the plot's container element (the div that was populated)\n * @returns {{top: number, left: number}}\n */\n this.getContainerOffset = function() {\n var offset = { top: 0, left: 0 };\n var container = this.container.offsetParent || null;\n while (container !== null) {\n offset.top += container.offsetTop;\n offset.left += container.offsetLeft;\n container = container.offsetParent || null;\n }\n return offset;\n };\n\n //\n /**\n * Event information describing interaction (e.g. panning and zooming) is stored on the plot\n * TODO: Add/ document details of interaction structure as we expand\n * @member {{panel_id: String, linked_panel_ids: Array, x_linked: *, dragging: *, zooming: *}}\n * @returns {LocusZoom.Plot}\n */\n this.interaction = {};\n\n /**\n * Track whether the target panel can respond to mouse interaction events\n * @param {String} panel_id\n * @returns {boolean}\n */\n this.canInteract = function(panel_id) {\n panel_id = panel_id || null;\n if (panel_id) {\n return ((typeof this.interaction.panel_id == 'undefined' || this.interaction.panel_id === panel_id) && !this.loading_data);\n } else {\n return !(this.interaction.dragging || this.interaction.zooming || this.loading_data);\n }\n };\n\n // Initialize the layout\n this.initializeLayout();\n return this;\n};\n\n/**\n * Default/ expected configuration parameters for basic plotting; most plots will override\n *\n * @protected\n * @static\n * @type {Object}\n */\nLocusZoom.Plot.DefaultLayout = {\n state: {},\n width: 1,\n height: 1,\n min_width: 1,\n min_height: 1,\n responsive_resize: false, // Allowed values: false, \"width_only\", \"both\" (synonym for true)\n aspect_ratio: 1,\n panels: [],\n dashboard: {\n components: []\n },\n panel_boundaries: true,\n mouse_guide: true\n};\n\n/**\n * Helper method to sum the proportional dimensions of panels, a value that's checked often as panels are added/removed\n * @param {('Height'|'Width')} dimension\n * @returns {number}\n */\nLocusZoom.Plot.prototype.sumProportional = function(dimension) {\n if (dimension !== 'height' && dimension !== 'width') {\n throw new Error('Bad dimension value passed to LocusZoom.Plot.prototype.sumProportional');\n }\n var total = 0;\n for (var id in this.panels) {\n // Ensure every panel contributing to the sum has a non-zero proportional dimension\n if (!this.panels[id].layout['proportional_' + dimension]) {\n this.panels[id].layout['proportional_' + dimension] = 1 / Object.keys(this.panels).length;\n }\n total += this.panels[id].layout['proportional_' + dimension];\n }\n return total;\n};\n\n/**\n * Resize the plot to fit the bounding container\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.rescaleSVG = function() {\n var clientRect = this.svg.node().getBoundingClientRect();\n this.setDimensions(clientRect.width, clientRect.height);\n return this;\n};\n\n/**\n * Prepare the plot for first use by performing parameter validation, setting up panels, and calculating dimensions\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.initializeLayout = function() {\n\n // Sanity check layout values\n if (isNaN(this.layout.width) || this.layout.width <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.height) || this.layout.height <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.aspect_ratio) || this.layout.aspect_ratio <= 0) {\n throw new Error('Plot layout parameter `aspect_ratio` must be a positive number');\n }\n if (this.layout.responsive_resize === true) {\n // Backwards compatible support\n console.warn('LocusZoom \"responsive_resize\" specifies a deprecated value. The new value should be \"both\". Please update your layout.');\n this.layout.responsive_resize = 'both';\n }\n var RESIZE_MODES = [false, 'both', 'width_only'];\n if (RESIZE_MODES.indexOf(this.layout.responsive_resize) === -1) {\n throw new Error('LocusZoom option \"responsive_resize\" should specify one of the following modes: ' + RESIZE_MODES.join(', '));\n }\n\n // If this is a responsive layout then set a namespaced/unique onresize event listener on the window\n if (this.layout.responsive_resize) {\n this.window_onresize = d3.select(window).on('resize.lz-' + this.id, function() {\n this.rescaleSVG();\n }.bind(this));\n // Forcing one additional setDimensions() call after the page is loaded clears up\n // any disagreements between the initial layout and the loaded responsive container's size\n d3.select(window).on('load.lz-' + this.id, function() {\n this.setDimensions();\n }.bind(this));\n }\n\n // Add panels\n this.layout.panels.forEach(function(panel_layout) {\n this.addPanel(panel_layout);\n }.bind(this));\n\n return this;\n};\n\n/**\n * Set the dimensions for a plot, and ensure that panels are sized and positioned correctly.\n *\n * If dimensions are provided, resizes each panel proportionally to match the new plot dimensions. Otherwise,\n * calculates the appropriate plot dimensions based on all panels.\n * @param {Number} [width] If provided and larger than minimum size, set plot to this width\n * @param {Number} [height] If provided and larger than minimum size, set plot to this height\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.setDimensions = function(width, height) {\n\n var id;\n\n // Update minimum allowable width and height by aggregating minimums from panels, then apply minimums to containing element.\n var min_width = parseFloat(this.layout.min_width) || 0;\n var min_height = parseFloat(this.layout.min_height) || 0;\n for (id in this.panels) {\n min_width = Math.max(min_width, this.panels[id].layout.min_width);\n if (parseFloat(this.panels[id].layout.min_height) > 0 && parseFloat(this.panels[id].layout.proportional_height) > 0) {\n min_height = Math.max(min_height, (this.panels[id].layout.min_height / this.panels[id].layout.proportional_height));\n }\n }\n this.layout.min_width = Math.max(min_width, 1);\n this.layout.min_height = Math.max(min_height, 1);\n d3.select(this.svg.node().parentNode).style({\n 'min-width': this.layout.min_width + 'px',\n 'min-height': this.layout.min_height + 'px'\n });\n\n // If width and height arguments were passed then adjust them against plot minimums if necessary.\n // Then resize the plot and proportionally resize panels to fit inside the new plot dimensions.\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n // Override discrete values if resizing responsively\n if (this.layout.responsive_resize) {\n // All resize modes will affect width\n if (this.svg) {\n this.layout.width = Math.max(this.svg.node().parentNode.getBoundingClientRect().width, this.layout.min_width);\n }\n\n if (this.layout.responsive_resize === 'both') { // Then also change the height\n this.layout.height = this.layout.width / this.layout.aspect_ratio;\n if (this.layout.height < this.layout.min_height) {\n this.layout.height = this.layout.min_height;\n this.layout.width = this.layout.height * this.layout.aspect_ratio;\n }\n }\n }\n // Resize/reposition panels to fit, update proportional origins if necessary\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n var panel_width = this.layout.width;\n var panel_height = this.panels[panel_id].layout.proportional_height * this.layout.height;\n this.panels[panel_id].setDimensions(panel_width, panel_height);\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n this.panels[panel_id].layout.proportional_origin.y = y_offset / this.layout.height;\n y_offset += panel_height;\n this.panels[panel_id].dashboard.update();\n }.bind(this));\n }\n\n // If width and height arguments were NOT passed (and panels exist) then determine the plot dimensions\n // by making it conform to panel dimensions, assuming panels are already positioned correctly.\n else if (Object.keys(this.panels).length) {\n this.layout.width = 0;\n this.layout.height = 0;\n for (id in this.panels) {\n this.layout.width = Math.max(this.panels[id].layout.width, this.layout.width);\n this.layout.height += this.panels[id].layout.height;\n }\n this.layout.width = Math.max(this.layout.width, this.layout.min_width);\n this.layout.height = Math.max(this.layout.height, this.layout.min_height);\n }\n\n // Keep aspect ratio in agreement with dimensions\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n\n // Apply layout width and height as discrete values or viewbox values\n if (this.svg !== null) {\n if (this.layout.responsive_resize === 'both') {\n this.svg\n .attr('viewBox', '0 0 ' + this.layout.width + ' ' + this.layout.height)\n .attr('preserveAspectRatio', 'xMinYMin meet');\n } else {\n this.svg.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n }\n\n // If the plot has been initialized then trigger some necessary render functions\n if (this.initialized) {\n this.panel_boundaries.position();\n this.dashboard.update();\n this.curtain.update();\n this.loader.update();\n }\n\n return this.emit('layout_changed');\n};\n\n/**\n * Create a new panel from a layout, and handle the work of initializing and placing the panel on the plot\n * @param {Object} layout\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Plot.prototype.addPanel = function(layout) {\n\n // Sanity checks\n if (typeof layout !== 'object') {\n throw new Error('Invalid panel layout passed to LocusZoom.Plot.prototype.addPanel()');\n }\n\n // Create the Panel and set its parent\n var panel = new LocusZoom.Panel(layout, this);\n\n // Store the Panel on the Plot\n this.panels[panel.id] = panel;\n\n // If a discrete y_index was set in the layout then adjust other panel y_index values to accommodate this one\n if (panel.layout.y_index !== null && !isNaN(panel.layout.y_index)\n && this.panel_ids_by_y_index.length > 0) {\n // Negative y_index values should count backwards from the end, so convert negatives to appropriate values here\n if (panel.layout.y_index < 0) {\n panel.layout.y_index = Math.max(this.panel_ids_by_y_index.length + panel.layout.y_index, 0);\n }\n this.panel_ids_by_y_index.splice(panel.layout.y_index, 0, panel.id);\n this.applyPanelYIndexesToPanelLayouts();\n } else {\n var length = this.panel_ids_by_y_index.push(panel.id);\n this.panels[panel.id].layout.y_index = length - 1;\n }\n\n // Determine if this panel was already in the layout.panels array.\n // If it wasn't, add it. Either way store the layout.panels array index on the panel.\n var layout_idx = null;\n this.layout.panels.forEach(function(panel_layout, idx) {\n if (panel_layout.id === panel.id) { layout_idx = idx; }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.panels.push(this.panels[panel.id].layout) - 1;\n }\n this.panels[panel.id].layout_idx = layout_idx;\n\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n this.positionPanels();\n // Initialize and load data into the new panel\n this.panels[panel.id].initialize();\n this.panels[panel.id].reMap();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n\n return this.panels[panel.id];\n};\n\n\n/**\n * Clear all state, tooltips, and other persisted data associated with one (or all) panel(s) in the plot\n *\n * This is useful when reloading an existing plot with new data, eg \"click for genome region\" links.\n * This is a utility method for custom usage. It is not fired automatically during normal rerender of existing panels\n * @param {String} [panelId] If provided, clear state for only this panel. Otherwise, clear state for all panels.\n * @param {('wipe'|'reset')} [mode='wipe'] Optionally specify how state should be cleared. `wipe` deletes all data\n * and is useful for when the panel is being removed; `reset` is best when the panel will be reused in place.\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.clearPanelData = function(panelId, mode) {\n mode = mode || 'wipe';\n\n // TODO: Add unit tests for this method\n var panelsList;\n if (panelId) {\n panelsList = [panelId];\n } else {\n panelsList = Object.keys(this.panels);\n }\n var self = this;\n panelsList.forEach(function(pid) {\n self.panels[pid].data_layer_ids_by_z_index.forEach(function(dlid) {\n var layer = self.panels[pid].data_layers[dlid];\n layer.destroyAllTooltips();\n\n delete self.layout.state[pid + '.' + dlid];\n if(mode === 'reset') {\n layer.setDefaultState();\n }\n });\n });\n return this;\n};\n\n/**\n * Remove the panel from the plot, and clear any state, tooltips, or other visual elements belonging to nested content\n * @param {String} id\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.removePanel = function(id) {\n if (!this.panels[id]) {\n throw new Error('Unable to remove panel, ID not found: ' + id);\n }\n\n // Hide all panel boundaries\n this.panel_boundaries.hide();\n\n // Destroy all tooltips and state vars for all data layers on the panel\n this.clearPanelData(id);\n\n // Remove all panel-level HTML overlay elements\n this.panels[id].loader.hide();\n this.panels[id].dashboard.destroy(true);\n this.panels[id].curtain.hide();\n\n // Remove the svg container for the panel if it exists\n if (this.panels[id].svg.container) {\n this.panels[id].svg.container.remove();\n }\n\n // Delete the panel and its presence in the plot layout and state\n this.layout.panels.splice(this.panels[id].layout_idx, 1);\n delete this.panels[id];\n delete this.layout.state[id];\n\n // Update layout_idx values for all remaining panels\n this.layout.panels.forEach(function(panel_layout, idx) {\n this.panels[panel_layout.id].layout_idx = idx;\n }.bind(this));\n\n // Remove the panel id from the y_index array\n this.panel_ids_by_y_index.splice(this.panel_ids_by_y_index.indexOf(id), 1);\n this.applyPanelYIndexesToPanelLayouts();\n\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n // Allow the plot to shrink when panels are removed, by forcing it to recalculate min dimensions from scratch\n this.layout.min_height = this._base_layout.min_height;\n this.layout.min_width = this._base_layout.min_width;\n\n this.positionPanels();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n\n this.emit('panel_removed', id);\n\n return this;\n};\n\n\n/**\n * Automatically position panels based on panel positioning rules and values.\n * Keep panels from overlapping vertically by adjusting origins, and keep the sum of proportional heights at 1.\n *\n * TODO: This logic currently only supports dynamic positioning of panels to prevent overlap in a VERTICAL orientation.\n * Some framework exists for positioning panels in horizontal orientations as well (width, proportional_width, origin.x, etc.)\n * but the logic for keeping these user-definable values straight approaches the complexity of a 2D box-packing algorithm.\n * That's complexity we don't need right now, and may not ever need, so it's on hiatus until a use case materializes.\n */\nLocusZoom.Plot.prototype.positionPanels = function() {\n\n var id;\n\n // We want to enforce that all x-linked panels have consistent horizontal margins\n // (to ensure that aligned items stay aligned despite inconsistent initial layout parameters)\n // NOTE: This assumes panels have consistent widths already. That should probably be enforced too!\n var x_linked_margins = { left: 0, right: 0 };\n\n // Proportional heights for newly added panels default to null unless explicitly set, so determine appropriate\n // proportional heights for all panels with a null value from discretely set dimensions.\n // Likewise handle default nulls for proportional widths, but instead just force a value of 1 (full width)\n for (id in this.panels) {\n if (this.panels[id].layout.proportional_height === null) {\n this.panels[id].layout.proportional_height = this.panels[id].layout.height / this.layout.height;\n }\n if (this.panels[id].layout.proportional_width === null) {\n this.panels[id].layout.proportional_width = 1;\n }\n if (this.panels[id].layout.interaction.x_linked) {\n x_linked_margins.left = Math.max(x_linked_margins.left, this.panels[id].layout.margin.left);\n x_linked_margins.right = Math.max(x_linked_margins.right, this.panels[id].layout.margin.right);\n }\n }\n\n // Sum the proportional heights and then adjust all proportionally so that the sum is exactly 1\n var total_proportional_height = this.sumProportional('height');\n if (!total_proportional_height) {\n return this;\n }\n var proportional_adjustment = 1 / total_proportional_height;\n for (id in this.panels) {\n this.panels[id].layout.proportional_height *= proportional_adjustment;\n }\n\n // Update origins on all panels without changing plot-level dimensions yet\n // Also apply x-linked margins to x-linked panels, updating widths as needed\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n y_offset += this.panels[panel_id].layout.height;\n if (this.panels[panel_id].layout.interaction.x_linked) {\n var delta = Math.max(x_linked_margins.left - this.panels[panel_id].layout.margin.left, 0)\n + Math.max(x_linked_margins.right - this.panels[panel_id].layout.margin.right, 0);\n this.panels[panel_id].layout.width += delta;\n this.panels[panel_id].layout.margin.left = x_linked_margins.left;\n this.panels[panel_id].layout.margin.right = x_linked_margins.right;\n this.panels[panel_id].layout.cliparea.origin.x = x_linked_margins.left;\n }\n }.bind(this));\n var calculated_plot_height = y_offset;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].layout.proportional_origin.y = this.panels[panel_id].layout.origin.y / calculated_plot_height;\n }.bind(this));\n\n // Update dimensions on the plot to accommodate repositioned panels\n this.setDimensions();\n\n // Set dimensions on all panels using newly set plot-level dimensions and panel-level proportional dimensions\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].setDimensions(this.layout.width * this.panels[panel_id].layout.proportional_width,\n this.layout.height * this.panels[panel_id].layout.proportional_height);\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Prepare the first rendering of the plot. This includes initializing the individual panels, but also creates shared\n * elements such as mouse events, panel guides/boundaries, and loader/curtain.\n *\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.initialize = function() {\n\n // Ensure proper responsive class is present on the containing node if called for\n if (this.layout.responsive_resize) {\n d3.select(this.container).classed('lz-container-responsive', true);\n }\n\n // Create an element/layer for containing mouse guides\n if (this.layout.mouse_guide) {\n var mouse_guide_svg = this.svg.append('g')\n .attr('class', 'lz-mouse_guide').attr('id', this.id + '.mouse_guide');\n var mouse_guide_vertical_svg = mouse_guide_svg.append('rect')\n .attr('class', 'lz-mouse_guide-vertical').attr('x',-1);\n var mouse_guide_horizontal_svg = mouse_guide_svg.append('rect')\n .attr('class', 'lz-mouse_guide-horizontal').attr('y',-1);\n this.mouse_guide = {\n svg: mouse_guide_svg,\n vertical: mouse_guide_vertical_svg,\n horizontal: mouse_guide_horizontal_svg\n };\n }\n\n // Add curtain and loader prototpyes to the plot\n this.curtain = LocusZoom.generateCurtain.call(this);\n this.loader = LocusZoom.generateLoader.call(this);\n\n // Create the panel_boundaries object with show/position/hide methods\n this.panel_boundaries = {\n parent: this,\n hide_timeout: null,\n showing: false,\n dragging: false,\n selectors: [],\n corner_selector: null,\n show: function() {\n // Generate panel boundaries\n if (!this.showing && !this.parent.curtain.showing) {\n this.showing = true;\n // Loop through all panels to create a horizontal boundary for each\n this.parent.panel_ids_by_y_index.forEach(function(panel_id, panel_idx) {\n var selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip')\n .attr('class', 'lz-panel-boundary')\n .attr('title', 'Resize panel');\n selector.append('span');\n var panel_resize_drag = d3.behavior.drag();\n panel_resize_drag.on('dragstart', function() { this.dragging = true; }.bind(this));\n panel_resize_drag.on('dragend', function() { this.dragging = false; }.bind(this));\n panel_resize_drag.on('drag', function() {\n // First set the dimensions on the panel we're resizing\n var this_panel = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]];\n var original_panel_height = this_panel.layout.height;\n this_panel.setDimensions(this_panel.layout.width, this_panel.layout.height + d3.event.dy);\n var panel_height_change = this_panel.layout.height - original_panel_height;\n var new_calculated_plot_height = this.parent.layout.height + panel_height_change;\n // Next loop through all panels.\n // Update proportional dimensions for all panels including the one we've resized using discrete heights.\n // Reposition panels with a greater y-index than this panel to their appropriate new origin.\n this.parent.panel_ids_by_y_index.forEach(function(loop_panel_id, loop_panel_idx) {\n var loop_panel = this.parent.panels[this.parent.panel_ids_by_y_index[loop_panel_idx]];\n loop_panel.layout.proportional_height = loop_panel.layout.height / new_calculated_plot_height;\n if (loop_panel_idx > panel_idx) {\n loop_panel.setOrigin(loop_panel.layout.origin.x, loop_panel.layout.origin.y + panel_height_change);\n loop_panel.dashboard.position();\n }\n }.bind(this));\n // Reset dimensions on the entire plot and reposition panel boundaries\n this.parent.positionPanels();\n this.position();\n }.bind(this));\n selector.call(panel_resize_drag);\n this.parent.panel_boundaries.selectors.push(selector);\n }.bind(this));\n // Create a corner boundary / resize element on the bottom-most panel that resizes the entire plot\n var corner_selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip')\n .attr('class', 'lz-panel-corner-boundary')\n .attr('title', 'Resize plot');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-outer');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-inner');\n var corner_drag = d3.behavior.drag();\n corner_drag.on('dragstart', function() { this.dragging = true; }.bind(this));\n corner_drag.on('dragend', function() { this.dragging = false; }.bind(this));\n corner_drag.on('drag', function() {\n this.setDimensions(this.layout.width + d3.event.dx, this.layout.height + d3.event.dy);\n }.bind(this.parent));\n corner_selector.call(corner_drag);\n this.parent.panel_boundaries.corner_selector = corner_selector;\n }\n return this.position();\n },\n position: function() {\n if (!this.showing) { return this; }\n // Position panel boundaries\n var plot_page_origin = this.parent.getPageOrigin();\n this.selectors.forEach(function(selector, panel_idx) {\n var panel_page_origin = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].getPageOrigin();\n var left = plot_page_origin.x;\n var top = panel_page_origin.y + this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].layout.height - 12;\n var width = this.parent.layout.width - 1;\n selector.style({\n top: top + 'px',\n left: left + 'px',\n width: width + 'px'\n });\n selector.select('span').style({\n width: width + 'px'\n });\n }.bind(this));\n // Position corner selector\n var corner_padding = 10;\n var corner_size = 16;\n this.corner_selector.style({\n top: (plot_page_origin.y + this.parent.layout.height - corner_padding - corner_size) + 'px',\n left: (plot_page_origin.x + this.parent.layout.width - corner_padding - corner_size) + 'px'\n });\n return this;\n },\n hide: function() {\n if (!this.showing) { return this; }\n this.showing = false;\n // Remove panel boundaries\n this.selectors.forEach(function(selector) { selector.remove(); });\n this.selectors = [];\n // Remove corner boundary\n this.corner_selector.remove();\n this.corner_selector = null;\n return this;\n }\n };\n\n // Show panel boundaries stipulated by the layout (basic toggle, only show on mouse over plot)\n if (this.layout.panel_boundaries) {\n d3.select(this.svg.node().parentNode).on('mouseover.' + this.id + '.panel_boundaries', function() {\n clearTimeout(this.panel_boundaries.hide_timeout);\n this.panel_boundaries.show();\n }.bind(this));\n d3.select(this.svg.node().parentNode).on('mouseout.' + this.id + '.panel_boundaries', function() {\n this.panel_boundaries.hide_timeout = setTimeout(function() {\n this.panel_boundaries.hide();\n }.bind(this), 300);\n }.bind(this));\n }\n\n // Create the dashboard object and immediately show it\n this.dashboard = new LocusZoom.Dashboard(this).show();\n\n // Initialize all panels\n for (var id in this.panels) {\n this.panels[id].initialize();\n }\n\n // Define plot-level mouse events\n var namespace = '.' + this.id;\n if (this.layout.mouse_guide) {\n var mouseout_mouse_guide = function() {\n this.mouse_guide.vertical.attr('x', -1);\n this.mouse_guide.horizontal.attr('y', -1);\n }.bind(this);\n var mousemove_mouse_guide = function() {\n var coords = d3.mouse(this.svg.node());\n this.mouse_guide.vertical.attr('x', coords[0]);\n this.mouse_guide.horizontal.attr('y', coords[1]);\n }.bind(this);\n this.svg\n .on('mouseout' + namespace + '-mouse_guide', mouseout_mouse_guide)\n .on('touchleave' + namespace + '-mouse_guide', mouseout_mouse_guide)\n .on('mousemove' + namespace + '-mouse_guide', mousemove_mouse_guide);\n }\n var mouseup = function() {\n this.stopDrag();\n }.bind(this);\n var mousemove = function() {\n if (this.interaction.dragging) {\n var coords = d3.mouse(this.svg.node());\n if (d3.event) { d3.event.preventDefault(); }\n this.interaction.dragging.dragged_x = coords[0] - this.interaction.dragging.start_x;\n this.interaction.dragging.dragged_y = coords[1] - this.interaction.dragging.start_y;\n this.panels[this.interaction.panel_id].render();\n this.interaction.linked_panel_ids.forEach(function(panel_id) {\n this.panels[panel_id].render();\n }.bind(this));\n }\n }.bind(this);\n this.svg\n .on('mouseup' + namespace, mouseup)\n .on('touchend' + namespace, mouseup)\n .on('mousemove' + namespace, mousemove)\n .on('touchmove' + namespace, mousemove);\n\n // Add an extra namespaced mouseup handler to the containing body, if there is one\n // This helps to stop interaction events gracefully when dragging outside of the plot element\n if (!d3.select('body').empty()) {\n d3.select('body')\n .on('mouseup' + namespace, mouseup)\n .on('touchend' + namespace, mouseup);\n }\n\n this.on('match_requested', function(eventData) {\n // Layers can broadcast that a specific point has been selected, and the plot will tell every other layer\n // to look for that value. Whenever a point is de-selected, it clears the match.\n var data = eventData.data;\n var to_send = (data.active ? data.value : null);\n this.applyState({ lz_match_value: to_send });\n }.bind(this));\n\n this.initialized = true;\n\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n var client_rect = this.svg.node().getBoundingClientRect();\n var width = client_rect.width ? client_rect.width : this.layout.width;\n var height = client_rect.height ? client_rect.height : this.layout.height;\n this.setDimensions(width, height);\n\n return this;\n\n};\n\n/**\n * Refresh (or fetch) a plot's data from sources, regardless of whether position or state has changed\n * @returns {Promise}\n */\nLocusZoom.Plot.prototype.refresh = function() {\n return this.applyState();\n};\n\n\n/**\n * A user-defined callback function that can receive (and potentially act on) new plot data.\n * @callback externalDataCallback\n * @param {Object} new_data The body resulting from a data request. This represents the same information that would be passed to\n * a data layer making an equivalent request.\n */\n\n/**\n * A user-defined callback function that can respond to errors received during a previous operation\n * @callback externalErrorCallback\n * @param err A representation of the error that occurred\n */\n\n/**\n * Allow newly fetched data to be made available outside the LocusZoom plot. For example, a callback could be\n * registered to draw an HTML table of top GWAS hits, and update that table whenever the plot region changes.\n *\n * This is a convenience method for external hooks. It registers an event listener and returns parsed data,\n * using the same fields syntax and underlying methods as data layers.\n *\n * @param {String[]} fields An array of field names and transforms, in the same syntax used by a data layer.\n * Different data sources should be prefixed by the source name.\n * @param {externalDataCallback} success_callback Used defined function that is automatically called any time that\n * new data is received by the plot.\n * @param {Object} [opts] Options\n * @param {externalErrorCallback} [opts.onerror] User defined function that is automatically called if a problem\n * occurs during the data request or subsequent callback operations\n * @param {boolean} [opts.discrete=false] Normally the callback will subscribe to the combined body from the chain,\n * which may not be in a format that matches what the external callback wants to do. If discrete=true, returns the\n * uncombined record info\n * @return {function} The newly created event listener, to allow for later cleanup/removal\n */\nLocusZoom.Plot.prototype.subscribeToData = function(fields, success_callback, opts) {\n opts = opts || {};\n\n // Register an event listener that is notified whenever new data has been rendered\n var error_callback = opts.onerror || function(err) {\n console.log('An error occurred while acting on an external callback', err);\n };\n var self = this;\n\n var listener = function() {\n try {\n self.lzd.getData(self.state, fields)\n .then(function (new_data) {\n success_callback(opts.discrete ? new_data.discrete : new_data.body);\n }).catch(error_callback);\n } catch (error) {\n // In certain cases, errors are thrown before a promise can be generated, and LZ error display seems to rely on these errors bubbling up\n error_callback(error);\n }\n };\n this.on('data_rendered', listener);\n return listener;\n};\n\n/**\n * Update state values and trigger a pull for fresh data on all data sources for all data layers\n * @param state_changes\n * @returns {Promise} A promise that resolves when all data fetch and update operations are complete\n */\nLocusZoom.Plot.prototype.applyState = function(state_changes) {\n state_changes = state_changes || {};\n if (typeof state_changes != 'object') {\n throw new Error('LocusZoom.applyState only accepts an object; ' + (typeof state_changes) + ' given');\n }\n\n // First make a copy of the current (old) state to work with\n var new_state = JSON.parse(JSON.stringify(this.state));\n\n // Apply changes by top-level property to the new state\n for (var property in state_changes) {\n new_state[property] = state_changes[property];\n }\n\n // Validate the new state (may do nothing, may do a lot, depends on how the user has things set up)\n new_state = LocusZoom.validateState(new_state, this.layout);\n\n // Apply new state to the actual state\n for (property in new_state) {\n this.state[property] = new_state[property];\n }\n\n // Generate requests for all panels given new state\n this.emit('data_requested');\n this.remap_promises = [];\n this.loading_data = true;\n for (var id in this.panels) {\n this.remap_promises.push(this.panels[id].reMap());\n }\n\n return Promise.all(this.remap_promises)\n .catch(function(error) {\n console.error(error);\n this.curtain.show(error.message || error);\n this.loading_data = false;\n }.bind(this))\n .then(function() {\n // Update dashboard / components\n this.dashboard.update();\n\n // Apply panel-level state values\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n var panel = this.panels[panel_id];\n panel.dashboard.update();\n // Apply data-layer-level state values\n panel.data_layer_ids_by_z_index.forEach(function(data_layer_id) {\n var data_layer = this.data_layers[data_layer_id];\n var state_id = panel_id + '.' + data_layer_id;\n for (var property in this.state[state_id]) {\n if (!this.state[state_id].hasOwnProperty(property)) { continue; }\n if (Array.isArray(this.state[state_id][property])) {\n this.state[state_id][property].forEach(function(element_id) {\n try {\n this.setElementStatus(property, this.getElementById(element_id), true);\n } catch (e) {\n console.warn('Unable to apply state: ' + state_id + ', ' + property);\n console.error(e);\n }\n }.bind(data_layer));\n }\n }\n }.bind(panel));\n }.bind(this));\n\n // Emit events\n this.emit('layout_changed');\n this.emit('data_rendered');\n this.emit('state_changed', state_changes);\n\n this.loading_data = false;\n\n }.bind(this));\n};\n\n/**\n * Register interactions along the specified axis, provided that the target panel allows interaction.\n *\n * @param {LocusZoom.Panel} panel\n * @param {('x_tick'|'y1_tick'|'y2_tick')} method The direction (axis) along which dragging is being performed.\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.startDrag = function(panel, method) {\n\n panel = panel || null;\n method = method || null;\n\n var axis = null;\n switch (method) {\n case 'background':\n case 'x_tick':\n axis = 'x';\n break;\n case 'y1_tick':\n axis = 'y1';\n break;\n case 'y2_tick':\n axis = 'y2';\n break;\n }\n\n if (!(panel instanceof LocusZoom.Panel) || !axis || !this.canInteract()) { return this.stopDrag(); }\n\n var coords = d3.mouse(this.svg.node());\n this.interaction = {\n panel_id: panel.id,\n linked_panel_ids: panel.getLinkedPanelIds(axis),\n dragging: {\n method: method,\n start_x: coords[0],\n start_y: coords[1],\n dragged_x: 0,\n dragged_y: 0,\n axis: axis\n }\n };\n\n this.svg.style('cursor', 'all-scroll');\n\n return this;\n\n};\n\n/**\n * Process drag interactions across the target panel and synchronize plot state across other panels in sync;\n * clear the event when complete\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.stopDrag = function() {\n\n if (!this.interaction.dragging) { return this; }\n\n if (typeof this.panels[this.interaction.panel_id] != 'object') {\n this.interaction = {};\n return this;\n }\n var panel = this.panels[this.interaction.panel_id];\n\n // Helper function to find the appropriate axis layouts on child data layers\n // Once found, apply the extent as floor/ceiling and remove all other directives\n // This forces all associated axes to conform to the extent generated by a drag action\n var overrideAxisLayout = function(axis, axis_number, extent) {\n panel.data_layer_ids_by_z_index.forEach(function(id) {\n if (panel.data_layers[id].layout[axis + '_axis'].axis === axis_number) {\n panel.data_layers[id].layout[axis + '_axis'].floor = extent[0];\n panel.data_layers[id].layout[axis + '_axis'].ceiling = extent[1];\n delete panel.data_layers[id].layout[axis + '_axis'].lower_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].upper_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].min_extent;\n delete panel.data_layers[id].layout[axis + '_axis'].ticks;\n }\n });\n };\n\n switch(this.interaction.dragging.method) {\n case 'background':\n case 'x_tick':\n if (this.interaction.dragging.dragged_x !== 0) {\n overrideAxisLayout('x', 1, panel.x_extent);\n this.applyState({ start: panel.x_extent[0], end: panel.x_extent[1] });\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n if (this.interaction.dragging.dragged_y !== 0) {\n // TODO: Hardcoded assumption of only two possible axes with single-digit #s (switch/case)\n var y_axis_number = parseInt(this.interaction.dragging.method[1]);\n overrideAxisLayout('y', y_axis_number, panel['y' + y_axis_number + '_extent']);\n }\n break;\n }\n\n this.interaction = {};\n this.svg.style('cursor', null);\n\n return this;\n\n};\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A panel is an abstract class representing a subdivision of the LocusZoom stage\n * to display a distinct data representation as a collection of data layers.\n * @class\n * @param {Object} layout\n * @param {LocusZoom.Plot|null} parent\n*/\nLocusZoom.Panel = function(layout, parent) {\n\n if (typeof layout !== 'object') {\n throw new Error('Unable to create panel, invalid layout');\n }\n\n /** @member {LocusZoom.Plot|null} */\n this.parent = parent || null;\n /** @member {LocusZoom.Plot|null} */\n this.parent_plot = parent;\n\n // Ensure a valid ID is present. If there is no valid ID then generate one\n if (typeof layout.id !== 'string' || !layout.id.length) {\n if (!this.parent) {\n layout.id = 'p' + Math.floor(Math.random() * Math.pow(10,8));\n } else {\n var id = null;\n var generateID = function() {\n id = 'p' + Math.floor(Math.random() * Math.pow(10,8));\n if (id == null || typeof this.parent.panels[id] != 'undefined') {\n id = generateID();\n }\n }.bind(this);\n layout.id = id;\n }\n } else if (this.parent) {\n if (typeof this.parent.panels[layout.id] !== 'undefined') {\n throw new Error('Cannot create panel with id [' + layout.id + ']; panel with that id already exists');\n }\n }\n /** @member {String} */\n this.id = layout.id;\n\n /** @member {Boolean} */\n this.initialized = false;\n /**\n * The index of this panel in the parent plot's `layout.panels`\n * @member {number}\n * */\n this.layout_idx = null;\n /** @member {Object} */\n this.svg = {};\n\n /**\n * A JSON-serializable object used to describe the composition of the Panel\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.Panel.DefaultLayout);\n\n // Define state parameters specific to this panel\n if (this.parent) {\n /** @member {Object} */\n this.state = this.parent.state;\n\n /** @member {String} */\n this.state_id = this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n } else {\n this.state = null;\n this.state_id = null;\n }\n\n /** @member {Object} */\n this.data_layers = {};\n /** @member {String[]} */\n this.data_layer_ids_by_z_index = [];\n\n /** @protected */\n this.applyDataLayerZIndexesToDataLayerLayouts = function() {\n this.data_layer_ids_by_z_index.forEach(function(dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n }.bind(this);\n\n /**\n * Track data requests in progress\n * @member {Promise[]}\n * @protected\n */\n this.data_promises = [];\n\n /** @member {d3.scale} */\n this.x_scale = null;\n /** @member {d3.scale} */\n this.y1_scale = null;\n /** @member {d3.scale} */\n this.y2_scale = null;\n\n /** @member {d3.extent} */\n this.x_extent = null;\n /** @member {d3.extent} */\n this.y1_extent = null;\n /** @member {d3.extent} */\n this.y2_extent = null;\n\n /** @member {Number[]} */\n this.x_ticks = [];\n /** @member {Number[]} */\n this.y1_ticks = [];\n /** @member {Number[]} */\n this.y2_ticks = [];\n\n /**\n * A timeout ID as returned by setTimeout\n * @protected\n * @member {number}\n */\n this.zoom_timeout = null;\n\n /** @returns {string} */\n this.getBaseId = function() {\n return this.parent.id + '.' + this.id;\n };\n\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [],\n 'element_selection': [],\n 'match_requested': [] // A data layer is attempting to highlight matching points (internal use only)\n };\n\n /**\n * There are several events that a LocusZoom panel can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following panel-level events are currently supported:\n * - `layout_changed` - context: panel - Any aspect of the panel's layout (including dimensions or state) has changed.\n * - `data_requested` - context: panel - A request for new data from any data source used in the panel has been made.\n * - `data_rendered` - context: panel - Data from a request has been received and rendered in the panel.\n * - `element_clicked` - context: panel - A data element in any of the panel's data layers has been clicked.\n * - `element_selection` - context: panel - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `panel.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * panel itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of the event (as defined in `event_hooks`)\n * @param {function} hook\n * @returns {function} The registered event listener\n */\n this.on = function(event, hook) {\n // TODO: Dry plot and panel event code into a shared mixin\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Panel}\n */\n this.off = function(event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n *\n * There is a shorter overloaded form of this method: if the event does not have any data, the second\n * argument can be a boolean to control bubbling\n *\n * @param {string} event A known event name\n * @param {*} [eventData] Data or event description that will be passed to the event listener\n * @param {boolean} [bubble=false] Whether to bubble the event to the parent\n * @returns {LocusZoom.Panel}\n */\n this.emit = function(event, eventData, bubble) {\n bubble = bubble || false;\n\n // TODO: DRY this with the parent plot implementation. Ensure interfaces remain compatible.\n // TODO: Improve documentation for overloaded method signature (JSDoc may have trouble here)\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n if (typeof eventData === 'boolean' && arguments.length === 2) {\n // Overloaded method signature: emit(event, bubble)\n bubble = eventData;\n eventData = null;\n }\n var sourceID = this.getBaseId();\n var self = this;\n var eventContext = {sourceID: sourceID, data: eventData || null};\n this.event_hooks[event].forEach(function(hookToRun) {\n // By default, any handlers fired here will see the panel as the value of `this`. If a bound function is\n // registered as a handler, the previously bound `this` will override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n if (bubble && this.parent) {\n this.parent.emit(event, eventContext);\n }\n return this;\n };\n\n /**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\n this.getPageOrigin = function() {\n var plot_origin = this.parent.getPageOrigin();\n return {\n x: plot_origin.x + this.layout.origin.x,\n y: plot_origin.y + this.layout.origin.y\n };\n };\n\n // Initialize the layout\n this.initializeLayout();\n\n return this;\n\n};\n\n/**\n * Default panel layout\n * @static\n * @type {Object}\n */\nLocusZoom.Panel.DefaultLayout = {\n title: { text: '', style: {}, x: 10, y: 22 },\n y_index: null,\n width: 0,\n height: 0,\n origin: { x: 0, y: null },\n min_width: 1,\n min_height: 1,\n proportional_width: null,\n proportional_height: null,\n proportional_origin: { x: 0, y: null },\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n background_click: 'clear_selections',\n dashboard: {\n components: []\n },\n cliparea: {\n height: 0,\n width: 0,\n origin: { x: 0, y: 0 }\n },\n axes: { // These are the only axes supported!!\n x: {},\n y1: {},\n y2: {}\n },\n legend: null,\n interaction: {\n drag_background_to_pan: false,\n drag_x_ticks_to_scale: false,\n drag_y1_ticks_to_scale: false,\n drag_y2_ticks_to_scale: false,\n scroll_to_zoom: false,\n x_linked: false,\n y1_linked: false,\n y2_linked: false\n },\n data_layers: []\n};\n\n/**\n * Prepare the panel for first use by performing parameter validation, creating axes, setting default dimensions,\n * and preparing / positioning data layers as appropriate.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.initializeLayout = function() {\n\n // If the layout is missing BOTH width and proportional width then set the proportional width to 1.\n // This will default the panel to taking up the full width of the plot.\n if (this.layout.width === 0 && this.layout.proportional_width === null) {\n this.layout.proportional_width = 1;\n }\n\n // If the layout is missing BOTH height and proportional height then set the proportional height to\n // an equal share of the plot's current height.\n if (this.layout.height === 0 && this.layout.proportional_height === null) {\n var panel_count = Object.keys(this.parent.panels).length;\n if (panel_count > 0) {\n this.layout.proportional_height = (1 / panel_count);\n } else {\n this.layout.proportional_height = 1;\n }\n }\n\n // Set panel dimensions, origin, and margin\n this.setDimensions();\n this.setOrigin();\n this.setMargin();\n\n // Set ranges\n // TODO: Define stub values in constructor\n this.x_range = [0, this.layout.cliparea.width];\n this.y1_range = [this.layout.cliparea.height, 0];\n this.y2_range = [this.layout.cliparea.height, 0];\n\n // Initialize panel axes\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (!Object.keys(this.layout.axes[axis]).length || this.layout.axes[axis].render === false) {\n // The default layout sets the axis to an empty object, so set its render boolean here\n this.layout.axes[axis].render = false;\n } else {\n this.layout.axes[axis].render = true;\n this.layout.axes[axis].label = this.layout.axes[axis].label || null;\n this.layout.axes[axis].label_function = this.layout.axes[axis].label_function || null;\n }\n }.bind(this));\n\n // Add data layers (which define x and y extents)\n this.layout.data_layers.forEach(function(data_layer_layout) {\n this.addDataLayer(data_layer_layout);\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Set the dimensions for the panel. If passed with no arguments will calculate optimal size based on layout\n * directives and the available area within the plot. If passed discrete width (number) and height (number) will\n * attempt to resize the panel to them, but may be limited by minimum dimensions defined on the plot or panel.\n *\n * @public\n * @param {number} [width]\n * @param {number} [height]\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setDimensions = function(width, height) {\n if (typeof width != 'undefined' && typeof height != 'undefined') {\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n }\n } else {\n if (this.layout.proportional_width !== null) {\n this.layout.width = Math.max(this.layout.proportional_width * this.parent.layout.width, this.layout.min_width);\n }\n if (this.layout.proportional_height !== null) {\n this.layout.height = Math.max(this.layout.proportional_height * this.parent.layout.height, this.layout.min_height);\n }\n }\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n if (this.svg.clipRect) {\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n if (this.initialized) {\n this.render();\n this.curtain.update();\n this.loader.update();\n this.dashboard.update();\n if (this.legend) { this.legend.position(); }\n }\n return this;\n};\n\n/**\n * Set panel origin on the plot, and re-render as appropriate\n *\n * @public\n * @param {number} x\n * @param {number} y\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setOrigin = function(x, y) {\n if (!isNaN(x) && x >= 0) { this.layout.origin.x = Math.max(Math.round(+x), 0); }\n if (!isNaN(y) && y >= 0) { this.layout.origin.y = Math.max(Math.round(+y), 0); }\n if (this.initialized) { this.render(); }\n return this;\n};\n\n/**\n * Set margins around this panel\n * @public\n * @param {number} top\n * @param {number} right\n * @param {number} bottom\n * @param {number} left\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setMargin = function(top, right, bottom, left) {\n var extra;\n if (!isNaN(top) && top >= 0) { this.layout.margin.top = Math.max(Math.round(+top), 0); }\n if (!isNaN(right) && right >= 0) { this.layout.margin.right = Math.max(Math.round(+right), 0); }\n if (!isNaN(bottom) && bottom >= 0) { this.layout.margin.bottom = Math.max(Math.round(+bottom), 0); }\n if (!isNaN(left) && left >= 0) { this.layout.margin.left = Math.max(Math.round(+left), 0); }\n if (this.layout.margin.top + this.layout.margin.bottom > this.layout.height) {\n extra = Math.floor(((this.layout.margin.top + this.layout.margin.bottom) - this.layout.height) / 2);\n this.layout.margin.top -= extra;\n this.layout.margin.bottom -= extra;\n }\n if (this.layout.margin.left + this.layout.margin.right > this.layout.width) {\n extra = Math.floor(((this.layout.margin.left + this.layout.margin.right) - this.layout.width) / 2);\n this.layout.margin.left -= extra;\n this.layout.margin.right -= extra;\n }\n ['top', 'right', 'bottom', 'left'].forEach(function(m) {\n this.layout.margin[m] = Math.max(this.layout.margin[m], 0);\n }.bind(this));\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n this.layout.cliparea.origin.x = this.layout.margin.left;\n this.layout.cliparea.origin.y = this.layout.margin.top;\n\n if (this.initialized) { this.render(); }\n return this;\n};\n\n/**\n * Set the title for the panel. If passed an object, will merge the object with the existing layout configuration, so\n * that all or only some of the title layout object's parameters can be customized. If passed null, false, or an empty\n * string, the title DOM element will be set to display: none.\n *\n * @param {string|object|null} title The title text, or an object with additional configuration\n * @param {string} title.text Text to display. Since titles are rendered as SVG text, HTML and newlines will not be rendered.\n * @param {number} title.x X-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n * @param {number} title.y Y-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n NOTE: SVG y values go from the top down, so the SVG origin of (0,0) is in the top left corner.\n * @param {object} title.style CSS styles object to be applied to the title's DOM element.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setTitle = function(title) {\n if (typeof this.layout.title == 'string') {\n var text = this.layout.title;\n this.layout.title = { text: text, x: 0, y: 0, style: {} };\n }\n if (typeof title == 'string') {\n this.layout.title.text = title;\n } else if (typeof title == 'object' && title !== null) {\n this.layout.title = LocusZoom.Layouts.merge(title, this.layout.title);\n }\n if (this.layout.title.text.length) {\n this.title.attr('display', null)\n .attr('x', parseFloat(this.layout.title.x))\n .attr('y', parseFloat(this.layout.title.y))\n .style(this.layout.title.style)\n .text(this.layout.title.text);\n } else {\n this.title.attr('display', 'none');\n }\n return this;\n};\n\n\n/**\n * Prepare the first rendering of the panel. This includes drawing the individual data layers, but also creates shared\n * elements such as axes, title, and loader/curtain.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.initialize = function() {\n\n // Append a container group element to house the main panel group element and the clip path\n // Position with initial layout parameters\n this.svg.container = this.parent.svg.append('g')\n .attr('id', this.getBaseId() + '.panel_container')\n .attr('transform', 'translate(' + (this.layout.origin.x || 0) + ',' + (this.layout.origin.y || 0) + ')');\n\n // Append clip path to the parent svg element, size with initial layout parameters\n var clipPath = this.svg.container.append('clipPath')\n .attr('id', this.getBaseId() + '.clip');\n this.svg.clipRect = clipPath.append('rect')\n .attr('width', this.layout.width).attr('height', this.layout.height);\n\n // Append svg group for rendering all panel child elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g')\n .attr('id', this.getBaseId() + '.panel')\n .attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n\n // Add curtain and loader prototypes to the panel\n /** @member {Object} */\n this.curtain = LocusZoom.generateCurtain.call(this);\n /** @member {Object} */\n this.loader = LocusZoom.generateLoader.call(this);\n\n /**\n * Create the dashboard object and hang components on it as defined by panel layout\n * @member {LocusZoom.Dashboard}\n */\n this.dashboard = new LocusZoom.Dashboard(this);\n\n // Inner border\n this.inner_border = this.svg.group.append('rect')\n .attr('class', 'lz-panel-background')\n .on('click', function() {\n if (this.layout.background_click === 'clear_selections') { this.clearSelections(); }\n }.bind(this));\n\n // Add the title\n /** @member {Element} */\n this.title = this.svg.group.append('text').attr('class', 'lz-panel-title');\n if (typeof this.layout.title != 'undefined') { this.setTitle(); }\n\n // Initialize Axes\n this.svg.x_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.x_axis').attr('class', 'lz-x lz-axis');\n if (this.layout.axes.x.render) {\n this.svg.x_axis_label = this.svg.x_axis.append('text')\n .attr('class', 'lz-x lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n this.svg.y1_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.y1_axis').attr('class', 'lz-y lz-y1 lz-axis');\n if (this.layout.axes.y1.render) {\n this.svg.y1_axis_label = this.svg.y1_axis.append('text')\n .attr('class', 'lz-y1 lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n this.svg.y2_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.y2_axis').attr('class', 'lz-y lz-y2 lz-axis');\n if (this.layout.axes.y2.render) {\n this.svg.y2_axis_label = this.svg.y2_axis.append('text')\n .attr('class', 'lz-y2 lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n\n // Initialize child Data Layers\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].initialize();\n }.bind(this));\n\n /**\n * Legend object, as defined by panel layout and child data layer layouts\n * @member {LocusZoom.Legend}\n * */\n this.legend = null;\n if (this.layout.legend) {\n this.legend = new LocusZoom.Legend(this);\n }\n\n // Establish panel background drag interaction mousedown event handler (on the panel background)\n if (this.layout.interaction.drag_background_to_pan) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var mousedown = function() {\n this.parent.startDrag(this, 'background');\n }.bind(this);\n this.svg.container.select('.lz-panel-background')\n .on('mousedown' + namespace + '.background', mousedown)\n .on('touchstart' + namespace + '.background', mousedown);\n }\n\n return this;\n\n};\n\n/**\n * Refresh the sort order of all data layers (called by data layer moveUp and moveDown methods)\n */\nLocusZoom.Panel.prototype.resortDataLayers = function() {\n var sort = [];\n this.data_layer_ids_by_z_index.forEach(function(id) {\n sort.push(this.data_layers[id].layout.z_index);\n }.bind(this));\n this.svg.group.selectAll('g.lz-data_layer-container').data(sort).sort(d3.ascending);\n this.applyDataLayerZIndexesToDataLayerLayouts();\n};\n\n/**\n * Get an array of panel IDs that are axis-linked to this panel\n * @param {('x'|'y1'|'y2')} axis\n * @returns {Array}\n */\nLocusZoom.Panel.prototype.getLinkedPanelIds = function(axis) {\n axis = axis || null;\n var linked_panel_ids = [];\n if (['x','y1','y2'].indexOf(axis) === -1) { return linked_panel_ids; }\n if (!this.layout.interaction[axis + '_linked']) { return linked_panel_ids; }\n this.parent.panel_ids_by_y_index.forEach(function(panel_id) {\n if (panel_id !== this.id && this.parent.panels[panel_id].layout.interaction[axis + '_linked']) {\n linked_panel_ids.push(panel_id);\n }\n }.bind(this));\n return linked_panel_ids;\n};\n\n/**\n * Move a panel up relative to others by y-index\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.moveUp = function() {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index - 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index - 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index - 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n};\n\n/**\n * Move a panel down (y-axis) relative to others in the plot\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.moveDown = function() {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index + 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index + 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index + 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n};\n\n/**\n * Create a new data layer from a provided layout object. Should have the keys specified in `DefaultLayout`\n * Will automatically add at the top (depth/z-index) of the panel unless explicitly directed differently\n * in the layout provided.\n * @param {object} layout\n * @returns {*}\n */\nLocusZoom.Panel.prototype.addDataLayer = function(layout) {\n\n // Sanity checks\n if (typeof layout !== 'object' || typeof layout.id !== 'string' || !layout.id.length) {\n throw new Error('Invalid data layer layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n if (typeof this.data_layers[layout.id] !== 'undefined') {\n throw new Error('Cannot create data_layer with id [' + layout.id + ']; data layer with that id already exists in the panel');\n }\n if (typeof layout.type !== 'string') {\n throw new Error('Invalid data layer type in layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n\n // If the layout defines a y axis make sure the axis number is set and is 1 or 2 (default to 1)\n if (typeof layout.y_axis == 'object' && (typeof layout.y_axis.axis == 'undefined' || [1,2].indexOf(layout.y_axis.axis) === -1)) {\n layout.y_axis.axis = 1;\n }\n\n // Create the Data Layer\n var data_layer = LocusZoom.DataLayers.get(layout.type, layout, this);\n\n // Store the Data Layer on the Panel\n this.data_layers[data_layer.id] = data_layer;\n\n // If a discrete z_index was set in the layout then adjust other data layer z_index values to accommodate this one\n if (data_layer.layout.z_index !== null && !isNaN(data_layer.layout.z_index)\n && this.data_layer_ids_by_z_index.length > 0) {\n // Negative z_index values should count backwards from the end, so convert negatives to appropriate values here\n if (data_layer.layout.z_index < 0) {\n data_layer.layout.z_index = Math.max(this.data_layer_ids_by_z_index.length + data_layer.layout.z_index, 0);\n }\n this.data_layer_ids_by_z_index.splice(data_layer.layout.z_index, 0, data_layer.id);\n this.data_layer_ids_by_z_index.forEach(function(dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n } else {\n var length = this.data_layer_ids_by_z_index.push(data_layer.id);\n this.data_layers[data_layer.id].layout.z_index = length - 1;\n }\n\n // Determine if this data layer was already in the layout.data_layers array.\n // If it wasn't, add it. Either way store the layout.data_layers array index on the data_layer.\n var layout_idx = null;\n this.layout.data_layers.forEach(function(data_layer_layout, idx) {\n if (data_layer_layout.id === data_layer.id) { layout_idx = idx; }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.data_layers.push(this.data_layers[data_layer.id].layout) - 1;\n }\n this.data_layers[data_layer.id].layout_idx = layout_idx;\n\n return this.data_layers[data_layer.id];\n};\n\n/**\n * Remove a data layer by id\n * @param {string} id\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.removeDataLayer = function(id) {\n if (!this.data_layers[id]) {\n throw new Error('Unable to remove data layer, ID not found: ' + id);\n }\n\n // Destroy all tooltips for the data layer\n this.data_layers[id].destroyAllTooltips();\n\n // Remove the svg container for the data layer if it exists\n if (this.data_layers[id].svg.container) {\n this.data_layers[id].svg.container.remove();\n }\n\n // Delete the data layer and its presence in the panel layout and state\n this.layout.data_layers.splice(this.data_layers[id].layout_idx, 1);\n delete this.state[this.data_layers[id].state_id];\n delete this.data_layers[id];\n\n // Remove the data_layer id from the z_index array\n this.data_layer_ids_by_z_index.splice(this.data_layer_ids_by_z_index.indexOf(id), 1);\n\n // Update layout_idx and layout.z_index values for all remaining data_layers\n this.applyDataLayerZIndexesToDataLayerLayouts();\n this.layout.data_layers.forEach(function(data_layer_layout, idx) {\n this.data_layers[data_layer_layout.id].layout_idx = idx;\n }.bind(this));\n\n return this;\n};\n\n/**\n * Clear all selections on all data layers\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.clearSelections = function() {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setAllElementStatus('selected', false);\n }.bind(this));\n return this;\n};\n\n/**\n * When the parent plot changes state, adjust the panel accordingly. For example, this may include fetching new data\n * from the API as the viewing region changes\n * @returns {Promise}\n */\nLocusZoom.Panel.prototype.reMap = function() {\n this.emit('data_requested');\n this.data_promises = [];\n\n // Remove any previous error messages before attempting to load new data\n this.curtain.hide();\n // Trigger reMap on each Data Layer\n for (var id in this.data_layers) {\n try {\n this.data_promises.push(this.data_layers[id].reMap());\n } catch (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }\n }\n // When all finished trigger a render\n return Promise.all(this.data_promises)\n .then(function() {\n this.initialized = true;\n this.render();\n this.emit('layout_changed', true);\n this.emit('data_rendered');\n }.bind(this))\n .catch(function(error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }.bind(this));\n};\n\n/**\n * Iterate over data layers to generate panel axis extents\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.generateExtents = function() {\n\n // Reset extents\n ['x', 'y1', 'y2'].forEach(function(axis) {\n this[axis + '_extent'] = null;\n }.bind(this));\n\n // Loop through the data layers\n for (var id in this.data_layers) {\n\n var data_layer = this.data_layers[id];\n\n // If defined and not decoupled, merge the x extent of the data layer with the panel's x extent\n if (data_layer.layout.x_axis && !data_layer.layout.x_axis.decoupled) {\n this.x_extent = d3.extent((this.x_extent || []).concat(data_layer.getAxisExtent('x')));\n }\n\n // If defined and not decoupled, merge the y extent of the data layer with the panel's appropriate y extent\n if (data_layer.layout.y_axis && !data_layer.layout.y_axis.decoupled) {\n var y_axis = 'y' + data_layer.layout.y_axis.axis;\n this[y_axis + '_extent'] = d3.extent((this[y_axis + '_extent'] || []).concat(data_layer.getAxisExtent('y')));\n }\n\n }\n\n // Override x_extent from state if explicitly defined to do so\n if (this.layout.axes.x && this.layout.axes.x.extent === 'state') {\n this.x_extent = [ this.state.start, this.state.end ];\n }\n\n return this;\n\n};\n\n/**\n * Generate an array of ticks for an axis. These ticks are generated in one of three ways (highest wins):\n * 1. An array of specific tick marks\n * 2. Query each data layer for what ticks are appropriate, and allow a panel-level tick configuration parameter\n * object to override the layer's default presentation settings\n * 3. Generate generic tick marks based on the extent of the data\n * @param {('x'|'y1'|'y2')} axis The string identifier of the axis\n * @returns {Number[]|Object[]} TODO: number format?\n * An array of numbers: interpreted as an array of axis value offsets for positioning.\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\nLocusZoom.Panel.prototype.generateTicks = function(axis) {\n\n // Parse an explicit 'ticks' attribute in the axis layout\n if (this.layout.axes[axis].ticks) {\n var layout = this.layout.axes[axis];\n\n var baseTickConfig = layout.ticks;\n if (Array.isArray(baseTickConfig)) {\n // Array of specific ticks hard-coded into a panel will override any ticks that an individual layer might specify\n return baseTickConfig;\n }\n\n if (typeof baseTickConfig === 'object') {\n // If the layout specifies base configuration for ticks- but without specific positions- then ask each\n // data layer to report the tick marks that it thinks it needs\n // TODO: Few layers currently need to specify custom ticks (which is ok!). But if it becomes common, consider adding mechanisms to deduplicate ticks across layers\n var self = this;\n\n // Pass any layer-specific customizations for how ticks are calculated. (styles are overridden separately)\n var config = { position: baseTickConfig.position };\n\n var combinedTicks = this.data_layer_ids_by_z_index.reduce(function(acc, data_layer_id) {\n var nextLayer = self.data_layers[data_layer_id];\n return acc.concat(nextLayer.getTicks(axis, config));\n }, []);\n\n return combinedTicks.map(function(item) {\n // The layer makes suggestions, but tick configuration params specified on the panel take precedence\n var itemConfig = {};\n itemConfig = LocusZoom.Layouts.merge(itemConfig, baseTickConfig);\n return LocusZoom.Layouts.merge(itemConfig, item);\n });\n }\n }\n\n // If no other configuration is provided, attempt to generate ticks from the extent\n if (this[axis + '_extent']) {\n return LocusZoom.prettyTicks(this[axis + '_extent'], 'both');\n }\n return [];\n};\n\n/**\n * Update rendering of this panel whenever an event triggers a redraw. Assumes that the panel has already been\n * prepared the first time via `initialize`\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.render = function() {\n\n // Position the panel container\n this.svg.container.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n\n // Set size on the clip rect\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n\n // Set and position the inner border, style if necessary\n this.inner_border\n .attr('x', this.layout.margin.left).attr('y', this.layout.margin.top)\n .attr('width', this.layout.width - (this.layout.margin.left + this.layout.margin.right))\n .attr('height', this.layout.height - (this.layout.margin.top + this.layout.margin.bottom));\n if (this.layout.inner_border) {\n this.inner_border.style({ 'stroke-width': 1, 'stroke': this.layout.inner_border });\n }\n\n // Set/update panel title if necessary\n this.setTitle();\n\n // Regenerate all extents\n this.generateExtents();\n\n // Helper function to constrain any procedurally generated vectors (e.g. ranges, extents)\n // Constraints applied here keep vectors from going to infinity or beyond a definable power of ten\n var constrain = function(value, limit_exponent) {\n var neg_min = Math.pow(-10, limit_exponent);\n var neg_max = Math.pow(-10, -limit_exponent);\n var pos_min = Math.pow(10, -limit_exponent);\n var pos_max = Math.pow(10, limit_exponent);\n if (value === Infinity) { value = pos_max; }\n if (value === -Infinity) { value = neg_min; }\n if (value === 0) { value = pos_min; }\n if (value > 0) { value = Math.max(Math.min(value, pos_max), pos_min); }\n if (value < 0) { value = Math.max(Math.min(value, neg_max), neg_min); }\n return value;\n };\n\n // Define default and shifted ranges for all axes\n var ranges = {};\n if (this.x_extent) {\n var base_x_range = { start: 0, end: this.layout.cliparea.width };\n if (this.layout.axes.x.range) {\n base_x_range.start = this.layout.axes.x.range.start || base_x_range.start;\n base_x_range.end = this.layout.axes.x.range.end || base_x_range.end;\n }\n ranges.x = [base_x_range.start, base_x_range.end];\n ranges.x_shifted = [base_x_range.start, base_x_range.end];\n }\n if (this.y1_extent) {\n var base_y1_range = { start: this.layout.cliparea.height, end: 0 };\n if (this.layout.axes.y1.range) {\n base_y1_range.start = this.layout.axes.y1.range.start || base_y1_range.start;\n base_y1_range.end = this.layout.axes.y1.range.end || base_y1_range.end;\n }\n ranges.y1 = [base_y1_range.start, base_y1_range.end];\n ranges.y1_shifted = [base_y1_range.start, base_y1_range.end];\n }\n if (this.y2_extent) {\n var base_y2_range = { start: this.layout.cliparea.height, end: 0 };\n if (this.layout.axes.y2.range) {\n base_y2_range.start = this.layout.axes.y2.range.start || base_y2_range.start;\n base_y2_range.end = this.layout.axes.y2.range.end || base_y2_range.end;\n }\n ranges.y2 = [base_y2_range.start, base_y2_range.end];\n ranges.y2_shifted = [base_y2_range.start, base_y2_range.end];\n }\n\n // Shift ranges based on any drag or zoom interactions currently underway\n if (this.parent.interaction.panel_id && (this.parent.interaction.panel_id === this.id || this.parent.interaction.linked_panel_ids.indexOf(this.id) !== -1)) {\n var anchor, scalar = null;\n if (this.parent.interaction.zooming && typeof this.x_scale == 'function') {\n var current_extent_size = Math.abs(this.x_extent[1] - this.x_extent[0]);\n var current_scaled_extent_size = Math.round(this.x_scale.invert(ranges.x_shifted[1])) - Math.round(this.x_scale.invert(ranges.x_shifted[0]));\n var zoom_factor = this.parent.interaction.zooming.scale;\n var potential_extent_size = Math.floor(current_scaled_extent_size * (1 / zoom_factor));\n if (zoom_factor < 1 && !isNaN(this.parent.layout.max_region_scale)) {\n zoom_factor = 1 / (Math.min(potential_extent_size, this.parent.layout.max_region_scale) / current_scaled_extent_size);\n } else if (zoom_factor > 1 && !isNaN(this.parent.layout.min_region_scale)) {\n zoom_factor = 1 / (Math.max(potential_extent_size, this.parent.layout.min_region_scale) / current_scaled_extent_size);\n }\n var new_extent_size = Math.floor(current_extent_size * zoom_factor);\n anchor = this.parent.interaction.zooming.center - this.layout.margin.left - this.layout.origin.x;\n var offset_ratio = anchor / this.layout.cliparea.width;\n var new_x_extent_start = Math.max(Math.floor(this.x_scale.invert(ranges.x_shifted[0]) - ((new_extent_size - current_scaled_extent_size) * offset_ratio)), 1);\n ranges.x_shifted = [ this.x_scale(new_x_extent_start), this.x_scale(new_x_extent_start + new_extent_size) ];\n } else if (this.parent.interaction.dragging) {\n switch (this.parent.interaction.dragging.method) {\n case 'background':\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n break;\n case 'x_tick':\n if (d3.event && d3.event.shiftKey) {\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n } else {\n anchor = this.parent.interaction.dragging.start_x - this.layout.margin.left - this.layout.origin.x;\n scalar = constrain(anchor / (anchor + this.parent.interaction.dragging.dragged_x), 3);\n ranges.x_shifted[0] = 0;\n ranges.x_shifted[1] = Math.max(this.layout.cliparea.width * (1 / scalar), 1);\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n var y_shifted = 'y' + this.parent.interaction.dragging.method[1] + '_shifted';\n if (d3.event && d3.event.shiftKey) {\n ranges[y_shifted][0] = this.layout.cliparea.height + this.parent.interaction.dragging.dragged_y;\n ranges[y_shifted][1] = +this.parent.interaction.dragging.dragged_y;\n } else {\n anchor = this.layout.cliparea.height - (this.parent.interaction.dragging.start_y - this.layout.margin.top - this.layout.origin.y);\n scalar = constrain(anchor / (anchor - this.parent.interaction.dragging.dragged_y), 3);\n ranges[y_shifted][0] = this.layout.cliparea.height;\n ranges[y_shifted][1] = this.layout.cliparea.height - (this.layout.cliparea.height * (1 / scalar));\n }\n }\n }\n }\n\n // Generate scales and ticks for all axes, then render them\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (!this[axis + '_extent']) { return; }\n\n // Base Scale\n this[axis + '_scale'] = d3.scale.linear()\n .domain(this[axis + '_extent'])\n .range(ranges[axis + '_shifted']);\n\n // Shift the extent\n this[axis + '_extent'] = [\n this[axis + '_scale'].invert(ranges[axis][0]),\n this[axis + '_scale'].invert(ranges[axis][1])\n ];\n\n // Finalize Scale\n this[axis + '_scale'] = d3.scale.linear()\n .domain(this[axis + '_extent']).range(ranges[axis]);\n\n // Render axis (and generate ticks as needed)\n this.renderAxis(axis);\n }.bind(this));\n\n // Establish mousewheel zoom event handers on the panel (namespacing not passed through by d3, so not used here)\n if (this.layout.interaction.scroll_to_zoom) {\n var zoom_handler = function() {\n // Look for a shift key press while scrolling to execute.\n // If not present, gracefully raise a notification and allow conventional scrolling\n if (!d3.event.shiftKey) {\n if (this.parent.canInteract(this.id)) {\n this.loader.show('Press [SHIFT] while scrolling to zoom').hide(1000);\n }\n return;\n }\n d3.event.preventDefault();\n if (!this.parent.canInteract(this.id)) { return; }\n var coords = d3.mouse(this.svg.container.node());\n var delta = Math.max(-1, Math.min(1, (d3.event.wheelDelta || -d3.event.detail || -d3.event.deltaY)));\n if (delta === 0) { return; }\n this.parent.interaction = {\n panel_id: this.id,\n linked_panel_ids: this.getLinkedPanelIds('x'),\n zooming: {\n scale: (delta < 1) ? 0.9 : 1.1,\n center: coords[0]\n }\n };\n this.render();\n this.parent.interaction.linked_panel_ids.forEach(function(panel_id) {\n this.parent.panels[panel_id].render();\n }.bind(this));\n if (this.zoom_timeout !== null) { clearTimeout(this.zoom_timeout); }\n this.zoom_timeout = setTimeout(function() {\n this.parent.interaction = {};\n this.parent.applyState({ start: this.x_extent[0], end: this.x_extent[1] });\n }.bind(this), 500);\n }.bind(this);\n this.zoom_listener = d3.behavior.zoom();\n this.svg.container.call(this.zoom_listener)\n .on('wheel.zoom', zoom_handler)\n .on('mousewheel.zoom', zoom_handler)\n .on('DOMMouseScroll.zoom', zoom_handler);\n }\n\n // Render data layers in order by z-index\n this.data_layer_ids_by_z_index.forEach(function(data_layer_id) {\n this.data_layers[data_layer_id].draw().render();\n }.bind(this));\n\n return this;\n};\n\n\n/**\n * Render ticks for a particular axis\n * @param {('x'|'y1'|'y2')} axis The identifier of the axes\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.renderAxis = function(axis) {\n\n if (['x', 'y1', 'y2'].indexOf(axis) === -1) {\n throw new Error('Unable to render axis; invalid axis identifier: ' + axis);\n }\n\n var canRender = this.layout.axes[axis].render\n && typeof this[axis + '_scale'] == 'function'\n && !isNaN(this[axis + '_scale'](0));\n\n // If the axis has already been rendered then check if we can/can't render it\n // Make sure the axis element is shown/hidden to suit\n if (this[axis + '_axis']) {\n this.svg.container.select('g.lz-axis.lz-' + axis).style('display', canRender ? null : 'none');\n }\n\n if (!canRender) { return this; }\n\n // Axis-specific values to plug in where needed\n var axis_params = {\n x: {\n position: 'translate(' + this.layout.margin.left + ',' + (this.layout.height - this.layout.margin.bottom) + ')',\n orientation: 'bottom',\n label_x: this.layout.cliparea.width / 2,\n label_y: (this.layout.axes[axis].label_offset || 0),\n label_rotate: null\n },\n y1: {\n position: 'translate(' + this.layout.margin.left + ',' + this.layout.margin.top + ')',\n orientation: 'left',\n label_x: -1 * (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n },\n y2: {\n position: 'translate(' + (this.layout.width - this.layout.margin.right) + ',' + this.layout.margin.top + ')',\n orientation: 'right',\n label_x: (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n }\n };\n\n // Generate Ticks\n this[axis + '_ticks'] = this.generateTicks(axis);\n\n // Determine if the ticks are all numbers (d3-automated tick rendering) or not (manual tick rendering)\n var ticksAreAllNumbers = (function(ticks) {\n for (var i = 0; i < ticks.length; i++) {\n if (isNaN(ticks[i])) {\n return false;\n }\n }\n return true;\n })(this[axis + '_ticks']);\n\n // Initialize the axis; set scale and orientation\n this[axis + '_axis'] = d3.svg.axis().scale(this[axis + '_scale']).orient(axis_params[axis].orientation).tickPadding(3);\n\n // Set tick values and format\n if (ticksAreAllNumbers) {\n this[axis + '_axis'].tickValues(this[axis + '_ticks']);\n if (this.layout.axes[axis].tick_format === 'region') {\n this[axis + '_axis'].tickFormat(function(d) { return LocusZoom.positionIntToString(d, 6); });\n }\n } else {\n var ticks = this[axis + '_ticks'].map(function(t) {\n return(t[axis.substr(0,1)]);\n });\n this[axis + '_axis'].tickValues(ticks)\n .tickFormat(function(t, i) { return this[axis + '_ticks'][i].text; }.bind(this));\n }\n\n // Position the axis in the SVG and apply the axis construct\n this.svg[axis + '_axis']\n .attr('transform', axis_params[axis].position)\n .call(this[axis + '_axis']);\n\n // If necessary manually apply styles and transforms to ticks as specified by the layout\n if (!ticksAreAllNumbers) {\n var tick_selector = d3.selectAll('g#' + this.getBaseId().replace('.','\\\\.') + '\\\\.' + axis + '_axis g.tick');\n var panel = this;\n tick_selector.each(function(d, i) {\n var selector = d3.select(this).select('text');\n if (panel[axis + '_ticks'][i].style) {\n selector.style(panel[axis + '_ticks'][i].style);\n }\n if (panel[axis + '_ticks'][i].transform) {\n selector.attr('transform', panel[axis + '_ticks'][i].transform);\n }\n });\n }\n\n // Render the axis label if necessary\n var label = this.layout.axes[axis].label || null;\n if (label !== null) {\n this.svg[axis + '_axis_label']\n .attr('x', axis_params[axis].label_x).attr('y', axis_params[axis].label_y)\n .text(LocusZoom.parseFields(this.state, label));\n if (axis_params[axis].label_rotate !== null) {\n this.svg[axis + '_axis_label']\n .attr('transform', 'rotate(' + axis_params[axis].label_rotate + ' ' + axis_params[axis].label_x + ',' + axis_params[axis].label_y + ')');\n }\n }\n\n // Attach interactive handlers to ticks as needed\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (this.layout.interaction['drag_' + axis + '_ticks_to_scale']) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var tick_mouseover = function() {\n if (typeof d3.select(this).node().focus == 'function') { d3.select(this).node().focus(); }\n var cursor = (axis === 'x') ? 'ew-resize' : 'ns-resize';\n if (d3.event && d3.event.shiftKey) { cursor = 'move'; }\n d3.select(this)\n .style({'font-weight': 'bold', 'cursor': cursor})\n .on('keydown' + namespace, tick_mouseover)\n .on('keyup' + namespace, tick_mouseover);\n };\n this.svg.container.selectAll('.lz-axis.lz-' + axis + ' .tick text')\n .attr('tabindex', 0) // necessary to make the tick focusable so keypress events can be captured\n .on('mouseover' + namespace, tick_mouseover)\n .on('mouseout' + namespace, function() {\n d3.select(this).style({'font-weight': 'normal'});\n d3.select(this).on('keydown' + namespace, null).on('keyup' + namespace, null);\n })\n .on('mousedown' + namespace, function() {\n this.parent.startDrag(this, axis + '_tick');\n }.bind(this));\n }\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Force the height of this panel to the largest absolute height of the data in\n * all child data layers (if not null for any child data layers)\n * @param {number|null} [target_height] A target height, which will be used in situations when the expected height can be\n * pre-calculated (eg when the layers are transitioning)\n */\nLocusZoom.Panel.prototype.scaleHeightToData = function(target_height) {\n target_height = +target_height || null;\n if (target_height === null) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n var dh = this.data_layers[id].getAbsoluteDataHeight();\n if (+dh) {\n if (target_height === null) {\n target_height = +dh;\n }\n else {\n target_height = Math.max(target_height, +dh);\n }\n }\n }.bind(this));\n }\n if (+target_height) {\n target_height += +this.layout.margin.top + +this.layout.margin.bottom;\n this.setDimensions(this.layout.width, target_height);\n this.parent.setDimensions();\n this.parent.panel_ids_by_y_index.forEach(function(id) {\n this.parent.panels[id].layout.proportional_height = null;\n }.bind(this));\n this.parent.positionPanels();\n }\n};\n\n/**\n * Methods to set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n */\nLocusZoom.Panel.prototype.setElementStatusByFilters = function(status, toggle, filters, exclusive) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setElementStatusByFilters(status, toggle, filters, exclusive);\n }.bind(this));\n};\n/**\n * Set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n */\nLocusZoom.Panel.prototype.setAllElementStatus = function(status, toggle) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setAllElementStatus(status, toggle);\n }.bind(this));\n};\n// TODO: Capture documentation for dynamically generated methods\nLocusZoom.DataLayer.Statuses.verbs.forEach(function(verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.Panel.prototype[verb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.Panel.prototype[antiverb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.Panel.prototype[verb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.Panel.prototype[antiverb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n});\n\n\n/**\n * Add a \"basic\" loader to a panel\n * This method is just a shortcut for adding the most commonly used type of loading indicator, which appears when\n * data is requested, animates (e.g. shows an infinitely cycling progress bar as opposed to one that loads from\n * 0-100% based on actual load progress), and disappears when new data is loaded and rendered.\n *\n *\n * @param {Boolean} show_immediately\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.addBasicLoader = function(show_immediately) {\n if (typeof show_immediately != 'undefined') { show_immediately = true; }\n if (show_immediately) {\n this.loader.show('Loading...').animate();\n }\n this.on('data_requested', function() {\n this.loader.show('Loading...').animate();\n }.bind(this));\n this.on('data_rendered', function() {\n this.loader.hide();\n }.bind(this));\n return this;\n};\n"]} \ No newline at end of file +{"version":3,"sources":["locuszoom.app.min.js","Dashboard.js","Singletons.js","DataLayer.js","Layouts.js","LocusZoom.js","Data.js","annotation_track.js","forest.js","genes.js","genome_legend.js","intervals.js","line.js","scatter.js","Legend.js","Plot.js","Panel.js"],"names":["root","factory","this","d3","obj","components","functions","transformations","parseTrans","sources","findSourceByName","datalayers","l","region_nav_plot_dashboard","covariates_model_plot_dashboard","covariates_model_association","layouts","minimum_d3_version","Error","minimum_version","current_version","minimum_version_array","split","current_version_array","version_is_ok","forEach","d","i","semanticVersionIsOk","version","LocusZoom","selector","datasource","layout","plot","select","html","call","node","id","iterator","empty","attr","Plot","container","dataset","region","parsed_state","parsePositionQuery","Object","keys","key","state","svg","append","style","setDimensions","positionPanels","initialize","length","refresh","plots","selectAll","each","populate","pos","exp","suffix","exp_symbols","0","3","6","9","isNaN","log","Math","LN10","min","max","places_exp","floor","toFixed","min_exp","places","ret","pow","p","val","toUpperCase","replace","suffixre","exec","mult","Number","x","match","center","positionStringToInt","offset","chr","start","end","position","range","clip_range","target_tick_count","parseInt","min_n","abs","c","base","base_toFixed","round","unit","ticks","parseFloat","push","indexOf","slice","pop","method","url","body","headers","timeout","Promise","resolve","reject","xhr","XMLHttpRequest","open","XDomainRequest","onreadystatechange","readyState","status","response","setTimeout","header","setRequestHeader","send","new_state","validated_region","attempted_scale","attempted_midpoint","temp","min_region_scale","max_region_scale","data","tokens","regex","m","index","text","condition","variable","close","console","error","JSON","stringify","astify","token","shift","then","ast","cache","hasOwnProperty","Data","Field","render_node","value","map","join","parentNode","classed","getToolTipData","getDataLayer","data_layer","getToolTipDataLayer","parent","panel","getToolTipPanel","showing","content_selector","hide_delay","show","content","css","curtain","parent_plot","insert","on","hide","bind","update","clearTimeout","page_origin","getPageOrigin","top","y","left","width","height","max-width","max-height","delay","remove","progress_selector","cancel_selector","loader","percent","loader_boundrect","getBoundingClientRect","animate","setPercentCompleted","extra","Sub","constructor","apply","arguments","prototype","create","k","LZ_SIG_THRESHOLD_LOGP","validateBuildSource","class_name","build","source","Layouts","dashboard","dashboard_components","tooltip","get","type","name","modifications","merge","unnamespaced","parse","default_namespace","namespace","default","toString","applyNamespaces","element","resolved_namespace","re","r","merge_namespace","namespaced_element","namespaced_property","property","set","add","list","custom_layout","default_layout","custom_type","default_type","Array","isArray","assoc","closable","or","and","intervals","catalog","orientation","recomb","fields","z_index","stroke","stroke-width","x_axis","field","y_axis","axis","ceiling","ld","point_shape","scale_function","parameters","field_value","else","point_size","color","breaks","values","legend","shape","size","label","class","id_field","upper_buffer","min_extent","behaviors","onmouseover","action","onmouseout","onclick","exclusive","onshiftclick","fill_opacity","phewas","tooltip_positioning","category_field","lower_buffer","categories","null_value","spacing","lines","stroke-dasharray","filters","operator","font-size","font-weight","fill","gene","constraint","genome","start_field","end_field","track_split_field","split_tracks","always_hide_legend","{{namespace[intervals]}}state_id","button_html","show_selected","button_title","state_field","options","display_name","group_position","margin-left","title","subtitle","step","min_width","min_height","proportional_width","margin","right","bottom","inner_border","axes","label_offset","tick_format","extent","y1","y2","origin","hidden","interaction","drag_background_to_pan","drag_x_ticks_to_scale","drag_y1_ticks_to_scale","drag_y2_ticks_to_scale","scroll_to_zoom","x_linked","data_layers","layer_name","default_config_display_name","display","text-anchor","transform","data_layer_id","pad_from_bottom","responsive_resize","panels","proportional_height","StandardLayout","mouse_guide","DataLayer","initialized","layout_idx","Panel","DefaultLayout","_base_layout","state_id","setDefaultState","tooltips","global_statuses","highlighted","selected","faded","addField","fieldName","fieldString","layer_state","Statuses","adjectives","verbs","menu_antiverbs","getBaseId","getAbsoluteDataHeight","group","canTransition","transition","panel_boundaries","dragging","panel_id","getElementId","element_id","getElementStatusNodeId","getElementById","applyDataMethods","field_to_match","receive","broadcast_value","lz_match_value","lz_highlight_match","toHTML","deselect","unselectElement","applyCustomDataMethods","clipRect","moveUp","data_layer_ids_by_z_index","resortDataLayers","moveDown","resolveScalableParameter","idx","f","ScaleFunctions","_getDataExtent","axis_config","getAxisExtent","dimension","axis_name","axis_layout","data_extent","original_extent_span","range_min","range_max","getTicks","config","createTooltip","arrow","updateTooltip","positionTooltip","parseFields","destroyTooltip","element_or_id","temporary","label_mark_position","splice","destroyAllTooltips","event","pageX","pageY","positionAllTooltips","showOrHideTooltip","first_time","resolveStatus","statuses","directive","reduce","previousValue","currentValue","sub_status","sub_operator","show_directive","hide_directive","antistatus","show_resolved","hide_resolved","has_tooltip","filter","return_type","matches","operators","=","a","b","!=","<","<=",">",">=","%","filterIndexes","filterElements","verb","adjective","antiverb","setElementStatus","setElementStatusByFilters","setAllElementStatus","active","get_element_id_error","element_status_node_id","element_status_idx","added_status","emit","is_selected","value_to_broadcast","toggle","applyBehaviors","selection","event_match","executeBehaviors","requiredKeyStates","ctrlKey","shiftKey","behavior","current_status_boolean","href","target","window","location","panel_origin","exportData","format","default_format","toLowerCase","e","warn","jsonified","delimiter","record","draw","cliparea","reMap","promise","lzd","getData","new_data","DataLayers","datalayer","extend","parent_name","overrides","child","subclass","hit_area_width","render","self","trackData","visible_lines_group","enter","exit","hit_areas_group","hit_areas_selection","_getX","x_center","x_left","left_node","left_node_x_center","crds","arrow_type","arrow_top","arrow_left","tooltip_box","data_layer_height","data_layer_width","x_scale","y_center","offset_right","offset_left","stroke_width","top_offset","mouse","confidence_intervals","show_no_significance_line","y_scale","sqrt","PI","ci_selection","ci_transform","ci_width","duration","ease","points_selection","initial_y","symbol","element_data","ci_config","item","field_to_add","label_font_size","label_exon_spacing","exon_height","bounding_box_padding","track_vertical_spacing","getTrackHeight","transcript_idx","tracks","gene_track_index","1","assignTracks","getLabelWidth","gene_name","font_size","temp_text","label_width","getBBox","g","gene_id","gene_version","transcript_id","transcripts","display_range","text_anchor","centered_margin","display_domain","invert","track","potential_track","collision_on_potential_track","placed_gene","min_start","t","exons","bboxes","boundaries","labels","strand","exon_id","clickareas","gene_bbox_id","gene_bbox","gene_center_x","arrow_width","chromosome_fill_colors","light","dark","chromosome_label_colors","genome_start","genome_end","chromosomes","variant_parts","variant","track_split_order","track_split_legend_to_y_axis","track_height","previous_tracks","interval_track_index","track_split_field_index","reverse","placed_interval","psuedoElement","sharedstatusnode_style","interval","statusnode_style","statusnodes","rects","interval_name","updateSplitTrackAxis","interval_bbox","interval_center_x","legend_axis","track_spacing","target_height","scaleHeightToData","toggleSplitTracks","interpolate","hitarea_width","mouse_event","line","tooltip_timeout","getMouseDisplayAndData","slope","x_field","y_field","bisect","bisector","datum","startDatum","endDatum","interpolateNumber","x_precision","toPrecision","y_precision","dd","max_arrow_left","path","area","y0","hitarea","hitarea_line","path_class","global_status","decoupled","x_extent","y_extent","default_y","flip_labels","handle_lines","Boolean","min_x","max_x","flip","dn","dnl","dnx","text_swing","dnlx2","line_swing","label_texts","da","dal","label_lines","abound","bbound","separate_labels","seperate_iterations","again","db","delta","adjust","new_a_y","new_b_y","min_y","max_y","label_elements","filtered_data","label_groups","x1","x2","makeLDReference","ref","applyState","ldrefvar","_prepareData","xField","sourceData","sort","ak","bk","av","bv","_generateCategoryBounds","uniqueCategories","category","bounds","categoryNames","_setDynamicColorScheme","_getColorScale","from_source","color_params","find","colors","colorParams","baseParams","parameters_categories_hash","every","scale","category10","category20","concat","categoryBounds","_categories","knownCategories","knownColors","xPos","diff","KnownDataSources","SOURCE_NAME","source_name","newObj","params","Function","getAll","setAll","clear","TransformationFunctions","fun","getTrans","substring","result","funs","parseTransString","fn","ceil","toExponential","str","encodeURIComponent","s","input","threshold","prev","curr","nullval","upper_idx","brk","normalized_input","isFinite","Dashboard","hide_timeout","persist","component","Components","shouldPersist","visibility","destroy","force","Component","parent_panel","parent_svg","button","menu","Button","parent_dashboard","tag","setTag","setHtml","setText","setTitle","setColor","setStyle","getClass","permanent","setPermanent","bool","setStatus","highlight","disable","setOnMouseover","setOnMouseout","setOnclick","preUpdate","postUpdate","outer_selector","inner_selector","scroll_position","scrollTop","page_scroll_top","document","documentElement","container_offset","getContainerOffset","dashboard_client_rect","button_client_rect","menu_client_rect","total_content_height","scrollHeight","base_max_width","container_max_width","content_max_width","base_max_height","max_height","setPopulate","menu_populate_function","div_selector","title_selector","display_width","display_height","positionIntToString","stylesheet","generateBase64SVG","old","URL","revokeObjectURL","filename","css_string","styleSheets","createCORSPromise","outerHTML","dy","initial_html","style_def","insert_at","Blob","createObjectURL","suppress_confirm","confirm","removePanel","is_at_top","y_index","is_at_bottom","panel_ids_by_y_index","can_zoom","current_region_scale","new_region_scale","menu_html","model","covariates","CovariatesModel","element_reference","updateComponent","removeByIdx","removeAll","table","covariate","row","cov","scale_timeout","status_adj","status_idx","status_verb","at_top","at_bottom","td","removeDataLayer","allowed_fields","fields_whitelist","dataLayer","dataLayerLayout","defaultConfig","configSlot","undefined","_selected_item","uniqueID","random","menuLayout","renderRow","display_options","row_id","radioId","field_name","defaultName","Legend","background_rect","elements","elements_group","padding","label_size","line_height","label_x","label_y","path_y","symbolTypes","radius","bcr","right_x","pad_from_right","DataSources","addSource","ns","dsobj","source_id","getSource","removeSource","fromJSON","ds","toJSON","parts","full_name","applyTransformations","Requester","requests","raw","trans","outnames","request_handles","discrete","Source","enableCache","dependentSource","parseInit","init","getCacheKey","chain","getURL","fetchRequest","getRequest","req","cacheKey","_cachedKey","_cachedResponse","preGetData","pre","resp","parseResponse","normalizeResponse","N","records","j","prepareData","annotateData","extractFields","fieldFound","output_record","v","combineChainBody","json","standardized","one_source_body","new_body","parseArraysToObjects","standard","parseObjectsToObjects","parseData","constructorFun","uniqueName","getPrototypeOf","AssociationSource","unshift","analysis","LDSource","findMergeFields","arr","dataFields","position_field","pvalue","pvalue_field","_names_","names","nameMatch","regexes","id_match","RegExp","findRequestedFields","isrefvarin","isrefvarout","ldin","ldout","getRefvar","refVar","columns","pval_field","cmp","test","extremeVal","extremeIdx","findExtremeValue","refSource","ldrefsource","reqFields","corrField","rsquare","lfield","rfield","position2","leftJoin","refvar","idfield","outrefname","outldname","tagRefVariant","LDSource2","genome_build","ld_source","population","ld_pop","combined","chainRequests","payload","next","GwasCatalog","build_option","default_source","posMatch","decider","decider_out","n_matches","outn","chainNames","catNames","GeneSource","GeneConstraintSource","query","Content-Type","alias","RecombinationRateSource","IntervalSource","bedtracksource","StaticSource","_data","PheWASSource","ConnectorSource","_source_name_mapping","specified_ids","REQUIRED_SOURCES","chain_source_id","applyPanelYIndexesToPanelLayouts","pid","remap_promises","window_onresize","event_hooks","layout_changed","data_requested","data_rendered","element_clicked","element_selection","match_requested","panel_removed","state_changed","hook","off","theseHooks","hookMatch","eventData","sourceID","hookToRun","eventContext","bounding_client_rect","x_offset","scrollLeft","y_offset","offsetParent","offsetTop","offsetLeft","canInteract","loading_data","zooming","initializeLayout","aspect_ratio","sumProportional","total","rescaleSVG","clientRect","RESIZE_MODES","panel_layout","addPanel","min-width","min-height","panel_width","panel_height","setOrigin","proportional_origin","clearPanelData","panelId","mode","panelsList","dlid","layer","x_linked_margins","total_proportional_height","proportional_adjustment","calculated_plot_height","mouse_guide_svg","mouse_guide_vertical_svg","mouse_guide_horizontal_svg","vertical","horizontal","generateCurtain","generateLoader","selectors","corner_selector","panel_idx","panel_resize_drag","drag","this_panel","original_panel_height","panel_height_change","new_calculated_plot_height","loop_panel_id","loop_panel_idx","loop_panel","corner_drag","dx","plot_page_origin","panel_page_origin","mouseout_mouse_guide","mousemove_mouse_guide","coords","mouseup","stopDrag","mousemove","preventDefault","dragged_x","start_x","dragged_y","start_y","linked_panel_ids","to_send","client_rect","subscribeToData","success_callback","opts","error_callback","onerror","err","listener","catch","state_changes","validateState","all","message","startDrag","getLinkedPanelIds","overrideAxisLayout","axis_number","y_axis_number","generateID","applyDataLayerZIndexesToDataLayerLayouts","data_promises","y1_scale","y2_scale","y1_extent","y2_extent","x_ticks","y1_ticks","y2_ticks","zoom_timeout","bubble","plot_origin","background_click","y1_linked","y2_linked","panel_count","setMargin","x_range","y1_range","y2_range","label_function","data_layer_layout","addDataLayer","clipPath","clearSelections","x_axis_label","y1_axis","y1_axis_label","y2_axis","y2_axis_label","mousedown","ascending","generateExtents","generateTicks","baseTickConfig","acc","nextLayer","itemConfig","prettyTicks","constrain","limit_exponent","neg_min","neg_max","pos_min","pos_max","Infinity","ranges","base_x_range","x_shifted","base_y1_range","y1_shifted","base_y2_range","y2_shifted","anchor","scalar","current_extent_size","current_scaled_extent_size","zoom_factor","potential_extent_size","new_extent_size","offset_ratio","new_x_extent_start","y_shifted","linear","domain","renderAxis","zoom_handler","wheelDelta","detail","deltaY","zoom_listener","zoom","canRender","axis_params","label_rotate","ticksAreAllNumbers","orient","tickPadding","tickValues","tickFormat","substr","tick_selector","tick_mouseover","focus","cursor","dh","addBasicLoader","show_immediately","plugin_loading_error","define","amd","module","exports","require"],"mappings":"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","file":"locuszoom.app.min.js","sourcesContent":["(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n define(['d3'], function (d3) {\n // amd\n return root.LocusZoom = factory(d3);\n });\n } else if (typeof module === 'object' && module.exports) {\n // commonJS\n module.exports = root.LocusZoom = factory(require('d3'));\n } else {\n // globals\n root.LocusZoom = factory(root.d3);\n }\n}(this, function (d3) {\n var semanticVersionIsOk = function (minimum_version, current_version) {\n // handle the trivial case\n if (current_version == minimum_version) {\n return true;\n } // compare semantic versions by component as integers\n // compare semantic versions by component as integers\n var minimum_version_array = minimum_version.split('.');\n var current_version_array = current_version.split('.');\n var version_is_ok = false;\n minimum_version_array.forEach(function (d, i) {\n if (!version_is_ok && +current_version_array[i] > +minimum_version_array[i]) {\n version_is_ok = true;\n }\n });\n return version_is_ok;\n };\n try {\n // Verify dependency: d3.js\n var minimum_d3_version = '3.5.6';\n if (typeof d3 != 'object') {\n throw new Error('d3 dependency not met. Library missing.');\n }\n if (!semanticVersionIsOk(minimum_d3_version, d3.version)) {\n throw new Error('d3 dependency not met. Outdated version detected.\\nRequired d3 version: ' + minimum_d3_version + ' or higher (found: ' + d3.version + ').');\n } // ESTemplate: module content goes here\n // ESTemplate: module content goes here\n ;\n (function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n define(['d3'], function (d3) {\n // amd\n return root.LocusZoom = factory(d3);\n });\n } else if (typeof module === 'object' && module.exports) {\n // commonJS\n module.exports = root.LocusZoom = factory(require('d3'));\n } else {\n // globals\n root.LocusZoom = factory(root.d3);\n }\n }(this, function (d3) {\n var semanticVersionIsOk = function (minimum_version, current_version) {\n // handle the trivial case\n if (current_version == minimum_version) {\n return true;\n }\n // compare semantic versions by component as integers\n // compare semantic versions by component as integers\n var minimum_version_array = minimum_version.split('.');\n var current_version_array = current_version.split('.');\n var version_is_ok = false;\n minimum_version_array.forEach(function (d, i) {\n if (!version_is_ok && +current_version_array[i] > +minimum_version_array[i]) {\n version_is_ok = true;\n }\n });\n return version_is_ok;\n };\n try {\n // Verify dependency: d3.js\n var minimum_d3_version = '3.5.6';\n if (typeof d3 != 'object') {\n throw new Error('d3 dependency not met. Library missing.');\n }\n if (!semanticVersionIsOk(minimum_d3_version, d3.version)) {\n throw new Error('d3 dependency not met. Outdated version detected.\\nRequired d3 version: ' + minimum_d3_version + ' or higher (found: ' + d3.version + ').');\n }\n // ESTemplate: module content goes here\n // ESTemplate: module content goes here\n ;\n var LocusZoom = { version: '0.10.1' };\n /**\n * Populate a single element with a LocusZoom plot.\n * selector can be a string for a DOM Query or a d3 selector.\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot} The newly created plot instance\n */\n LocusZoom.populate = function (selector, datasource, layout) {\n if (typeof selector == 'undefined') {\n throw new Error('LocusZoom.populate selector not defined');\n }\n // Empty the selector of any existing content\n d3.select(selector).html('');\n var plot;\n d3.select(selector).call(function () {\n // Require each containing element have an ID. If one isn't present, create one.\n if (typeof this.node().id == 'undefined') {\n var iterator = 0;\n while (!d3.select('#lz-' + iterator).empty()) {\n iterator++;\n }\n this.attr('id', '#lz-' + iterator);\n }\n // Create the plot\n plot = new LocusZoom.Plot(this.node().id, datasource, layout);\n plot.container = this.node();\n // Detect data-region and fill in state values if present\n if (typeof this.node().dataset !== 'undefined' && typeof this.node().dataset.region !== 'undefined') {\n var parsed_state = LocusZoom.parsePositionQuery(this.node().dataset.region);\n Object.keys(parsed_state).forEach(function (key) {\n plot.state[key] = parsed_state[key];\n });\n }\n // Add an SVG to the div and set its dimensions\n plot.svg = d3.select('div#' + plot.id).append('svg').attr('version', '1.1').attr('xmlns', 'http://www.w3.org/2000/svg').attr('id', plot.id + '_svg').attr('class', 'lz-locuszoom').style(plot.layout.style);\n plot.setDimensions();\n plot.positionPanels();\n // Initialize the plot\n plot.initialize();\n // If the plot has defined data sources then trigger its first mapping based on state values\n if (typeof datasource == 'object' && Object.keys(datasource).length) {\n plot.refresh();\n }\n });\n return plot;\n };\n /**\n * Populate arbitrarily many elements each with a LocusZoom plot\n * using a common datasource and layout\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot[]}\n */\n LocusZoom.populateAll = function (selector, datasource, layout) {\n var plots = [];\n d3.selectAll(selector).each(function (d, i) {\n plots[i] = LocusZoom.populate(this, datasource, layout);\n });\n return plots;\n };\n /**\n * Convert an integer chromosome position to an SI string representation (e.g. 23423456 => \"23.42\" (Mb))\n * @param {Number} pos Position\n * @param {Number} [exp] Exponent to use for the returned string, eg 6=> MB. If not specified, will attempt to guess\n * the most appropriate SI prefix based on the number provided.\n * @param {Boolean} [suffix=false] Whether or not to append a suffix (e.g. \"Mb\") to the end of the returned string\n * @returns {string}\n */\n LocusZoom.positionIntToString = function (pos, exp, suffix) {\n var exp_symbols = {\n 0: '',\n 3: 'K',\n 6: 'M',\n 9: 'G'\n };\n suffix = suffix || false;\n if (isNaN(exp) || exp === null) {\n var log = Math.log(pos) / Math.LN10;\n exp = Math.min(Math.max(log - log % 3, 0), 9);\n }\n var places_exp = exp - Math.floor((Math.log(pos) / Math.LN10).toFixed(exp + 3));\n var min_exp = Math.min(Math.max(exp, 0), 2);\n var places = Math.min(Math.max(places_exp, min_exp), 12);\n var ret = '' + (pos / Math.pow(10, exp)).toFixed(places);\n if (suffix && typeof exp_symbols[exp] !== 'undefined') {\n ret += ' ' + exp_symbols[exp] + 'b';\n }\n return ret;\n };\n /**\n * Convert an SI string chromosome position to an integer representation (e.g. \"5.8 Mb\" => 58000000)\n * @param {String} p The chromosome position\n * @returns {Number}\n */\n LocusZoom.positionStringToInt = function (p) {\n var val = p.toUpperCase();\n val = val.replace(/,/g, '');\n var suffixre = /([KMG])[B]*$/;\n var suffix = suffixre.exec(val);\n var mult = 1;\n if (suffix) {\n if (suffix[1] === 'M') {\n mult = 1000000;\n } else if (suffix[1] === 'G') {\n mult = 1000000000;\n } else {\n mult = 1000; //K\n }\n val = val.replace(suffixre, '');\n }\n val = Number(val) * mult;\n return val;\n };\n /**\n * Parse region queries into their constituent parts\n * TODO: handle genes (or send off to API)\n * @param {String} x A chromosome position query. May be any of the forms `chr:start-end`, `chr:center+offset`,\n * or `chr:pos`\n * @returns {{chr:*, start: *, end:*} | {chr:*, position:*}}\n */\n LocusZoom.parsePositionQuery = function (x) {\n var chrposoff = /^(\\w+):([\\d,.]+[kmgbKMGB]*)([-+])([\\d,.]+[kmgbKMGB]*)$/;\n var chrpos = /^(\\w+):([\\d,.]+[kmgbKMGB]*)$/;\n var match = chrposoff.exec(x);\n if (match) {\n if (match[3] === '+') {\n var center = LocusZoom.positionStringToInt(match[2]);\n var offset = LocusZoom.positionStringToInt(match[4]);\n return {\n chr: match[1],\n start: center - offset,\n end: center + offset\n };\n } else {\n return {\n chr: match[1],\n start: LocusZoom.positionStringToInt(match[2]),\n end: LocusZoom.positionStringToInt(match[4])\n };\n }\n }\n match = chrpos.exec(x);\n if (match) {\n return {\n chr: match[1],\n position: LocusZoom.positionStringToInt(match[2])\n };\n }\n return null;\n };\n /**\n * Generate a \"pretty\" set of ticks (multiples of 1, 2, or 5 on the same order of magnitude for the range)\n * Based on R's \"pretty\" function: https://github.com/wch/r-source/blob/b156e3a711967f58131e23c1b1dc1ea90e2f0c43/src/appl/pretty.c\n * @param {Number[]} range A two-item array specifying [low, high] values for the axis range\n * @param {('low'|'high'|'both'|'neither')} [clip_range='neither'] What to do if first and last generated ticks extend\n * beyond the range. Set this to \"low\", \"high\", \"both\", or \"neither\" to clip the first (low) or last (high) tick to\n * be inside the range or allow them to extend beyond.\n * e.g. \"low\" will clip the first (low) tick if it extends beyond the low end of the range but allow the\n * last (high) tick to extend beyond the range. \"both\" clips both ends, \"neither\" allows both to extend beyond.\n * @param {Number} [target_tick_count=5] The approximate number of ticks you would like to be returned; may not be exact\n * @returns {Number[]}\n */\n LocusZoom.prettyTicks = function (range, clip_range, target_tick_count) {\n if (typeof target_tick_count == 'undefined' || isNaN(parseInt(target_tick_count))) {\n target_tick_count = 5;\n }\n target_tick_count = parseInt(target_tick_count);\n var min_n = target_tick_count / 3;\n var shrink_sml = 0.75;\n var high_u_bias = 1.5;\n var u5_bias = 0.5 + 1.5 * high_u_bias;\n var d = Math.abs(range[0] - range[1]);\n var c = d / target_tick_count;\n if (Math.log(d) / Math.LN10 < -2) {\n c = Math.max(Math.abs(d)) * shrink_sml / min_n;\n }\n var base = Math.pow(10, Math.floor(Math.log(c) / Math.LN10));\n var base_toFixed = 0;\n if (base < 1 && base !== 0) {\n base_toFixed = Math.abs(Math.round(Math.log(base) / Math.LN10));\n }\n var unit = base;\n if (2 * base - c < high_u_bias * (c - unit)) {\n unit = 2 * base;\n if (5 * base - c < u5_bias * (c - unit)) {\n unit = 5 * base;\n if (10 * base - c < high_u_bias * (c - unit)) {\n unit = 10 * base;\n }\n }\n }\n var ticks = [];\n var i = parseFloat((Math.floor(range[0] / unit) * unit).toFixed(base_toFixed));\n while (i < range[1]) {\n ticks.push(i);\n i += unit;\n if (base_toFixed > 0) {\n i = parseFloat(i.toFixed(base_toFixed));\n }\n }\n ticks.push(i);\n if (typeof clip_range == 'undefined' || [\n 'low',\n 'high',\n 'both',\n 'neither'\n ].indexOf(clip_range) === -1) {\n clip_range = 'neither';\n }\n if (clip_range === 'low' || clip_range === 'both') {\n if (ticks[0] < range[0]) {\n ticks = ticks.slice(1);\n }\n }\n if (clip_range === 'high' || clip_range === 'both') {\n if (ticks[ticks.length - 1] > range[1]) {\n ticks.pop();\n }\n }\n return ticks;\n };\n /**\n * Make an AJAX request and return a promise.\n * From http://www.html5rocks.com/en/tutorials/cors/\n * and with promises from https://gist.github.com/kriskowal/593076\n *\n * @param {String} method The HTTP verb\n * @param {String} url\n * @param {String} [body] The request body to send to the server\n * @param {Object} [headers] Object of custom request headers\n * @param {Number} [timeout] If provided, wait this long (in ms) before timing out\n * @returns {Promise}\n */\n LocusZoom.createCORSPromise = function (method, url, body, headers, timeout) {\n return new Promise(function (resolve, reject) {\n var xhr = new XMLHttpRequest();\n if ('withCredentials' in xhr) {\n // Check if the XMLHttpRequest object has a \"withCredentials\" property.\n // \"withCredentials\" only exists on XMLHTTPRequest2 objects.\n xhr.open(method, url, true);\n } else if (typeof XDomainRequest != 'undefined') {\n // Otherwise, check if XDomainRequest.\n // XDomainRequest only exists in IE, and is IE's way of making CORS requests.\n xhr = new XDomainRequest();\n xhr.open(method, url);\n } else {\n // Otherwise, CORS is not supported by the browser.\n xhr = null;\n }\n if (xhr) {\n xhr.onreadystatechange = function () {\n if (xhr.readyState === 4) {\n if (xhr.status === 200 || xhr.status === 0) {\n resolve(xhr.response);\n } else {\n reject('HTTP ' + xhr.status + ' for ' + url);\n }\n }\n };\n timeout && setTimeout(reject, timeout);\n body = typeof body !== 'undefined' ? body : '';\n if (typeof headers !== 'undefined') {\n for (var header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n }\n // Send the request\n xhr.send(body);\n }\n });\n };\n /**\n * Validate a (presumed complete) plot state object against internal rules for consistency, and ensure the plot fits\n * within any constraints imposed by the layout.\n * @param {Object} new_state\n * @param {Number} new_state.start\n * @param {Number} new_state.end\n * @param {Object} layout\n * @returns {*|{}}\n */\n LocusZoom.validateState = function (new_state, layout) {\n new_state = new_state || {};\n layout = layout || {};\n // If a \"chr\", \"start\", and \"end\" are present then resolve start and end\n // to numeric values that are not decimal, negative, or flipped\n var validated_region = false;\n if (typeof new_state.chr != 'undefined' && typeof new_state.start != 'undefined' && typeof new_state.end != 'undefined') {\n // Determine a numeric scale and midpoint for the attempted region,\n var attempted_midpoint = null;\n var attempted_scale;\n new_state.start = Math.max(parseInt(new_state.start), 1);\n new_state.end = Math.max(parseInt(new_state.end), 1);\n if (isNaN(new_state.start) && isNaN(new_state.end)) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_midpoint = 0.5;\n attempted_scale = 0;\n } else if (isNaN(new_state.start) || isNaN(new_state.end)) {\n attempted_midpoint = new_state.start || new_state.end;\n attempted_scale = 0;\n new_state.start = isNaN(new_state.start) ? new_state.end : new_state.start;\n new_state.end = isNaN(new_state.end) ? new_state.start : new_state.end;\n } else {\n attempted_midpoint = Math.round((new_state.start + new_state.end) / 2);\n attempted_scale = new_state.end - new_state.start;\n if (attempted_scale < 0) {\n var temp = new_state.start;\n new_state.end = new_state.start;\n new_state.start = temp;\n attempted_scale = new_state.end - new_state.start;\n }\n if (attempted_midpoint < 0) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_scale = 0;\n }\n }\n validated_region = true;\n }\n // Constrain w/r/t layout-defined minimum region scale\n if (!isNaN(layout.min_region_scale) && validated_region && attempted_scale < layout.min_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.min_region_scale / 2), 1);\n new_state.end = new_state.start + layout.min_region_scale;\n }\n // Constrain w/r/t layout-defined maximum region scale\n if (!isNaN(layout.max_region_scale) && validated_region && attempted_scale > layout.max_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.max_region_scale / 2), 1);\n new_state.end = new_state.start + layout.max_region_scale;\n }\n return new_state;\n };\n //\n /**\n * Replace placeholders in an html string with field values defined in a data object\n * Only works on scalar values! Will ignore non-scalars.\n *\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @param {Object} data\n * @param {String} html A placeholder string in which to substitute fields. Supports several template options:\n * `{{field_name}}` is a variable placeholder for the value of `field_name` from the provided data\n * `{{#if field_name}} Conditional text {{/if}}` will insert the contents of the tag only if the value exists.\n * Since this is only an existence check, **variables with a value of 0 will be evaluated as true**.\n * This can be used with namespaced values, `{{#if assoc:field}}`; any dynamic namespacing will be applied when the\n * layout is first retrieved.\n * @returns {string}\n */\n LocusZoom.parseFields = function (data, html) {\n if (typeof data != 'object') {\n throw new Error('LocusZoom.parseFields invalid arguments: data is not an object');\n }\n if (typeof html != 'string') {\n throw new Error('LocusZoom.parseFields invalid arguments: html is not a string');\n }\n // `tokens` is like [token,...]\n // `token` is like {text: '...'} or {variable: 'foo|bar'} or {condition: 'foo|bar'} or {close: 'if'}\n var tokens = [];\n var regex = /\\{\\{(?:(#if )?([A-Za-z0-9_:|]+)|(\\/if))\\}\\}/;\n while (html.length > 0) {\n var m = regex.exec(html);\n if (!m) {\n tokens.push({ text: html });\n html = '';\n } else if (m.index !== 0) {\n tokens.push({ text: html.slice(0, m.index) });\n html = html.slice(m.index);\n } else if (m[1] === '#if ') {\n tokens.push({ condition: m[2] });\n html = html.slice(m[0].length);\n } else if (m[2]) {\n tokens.push({ variable: m[2] });\n html = html.slice(m[0].length);\n } else if (m[3] === '/if') {\n tokens.push({ close: 'if' });\n html = html.slice(m[0].length);\n } else {\n console.error('Error tokenizing tooltip when remaining template is ' + JSON.stringify(html) + ' and previous tokens are ' + JSON.stringify(tokens) + ' and current regex match is ' + JSON.stringify([\n m[1],\n m[2],\n m[3]\n ]));\n html = html.slice(m[0].length);\n }\n }\n var astify = function () {\n var token = tokens.shift();\n if (typeof token.text !== 'undefined' || token.variable) {\n return token;\n } else if (token.condition) {\n token.then = [];\n while (tokens.length > 0) {\n if (tokens[0].close === 'if') {\n tokens.shift();\n break;\n }\n token.then.push(astify());\n }\n return token;\n } else {\n console.error('Error making tooltip AST due to unknown token ' + JSON.stringify(token));\n return { text: '' };\n }\n };\n // `ast` is like [thing,...]\n // `thing` is like {text: \"...\"} or {variable:\"foo|bar\"} or {condition: \"foo|bar\", then:[thing,...]}\n var ast = [];\n while (tokens.length > 0) {\n ast.push(astify());\n }\n var resolve = function (variable) {\n if (!resolve.cache.hasOwnProperty(variable)) {\n resolve.cache[variable] = new LocusZoom.Data.Field(variable).resolve(data);\n }\n return resolve.cache[variable];\n };\n resolve.cache = {};\n var render_node = function (node) {\n if (typeof node.text !== 'undefined') {\n return node.text;\n } else if (node.variable) {\n try {\n var value = resolve(node.variable);\n if ([\n 'string',\n 'number',\n 'boolean'\n ].indexOf(typeof value) !== -1) {\n return value;\n }\n if (value === null) {\n return '';\n }\n } catch (error) {\n console.error('Error while processing variable ' + JSON.stringify(node.variable));\n }\n return '{{' + node.variable + '}}';\n } else if (node.condition) {\n try {\n var condition = resolve(node.condition);\n if (condition || condition === 0) {\n return node.then.map(render_node).join('');\n }\n } catch (error) {\n console.error('Error while processing condition ' + JSON.stringify(node.variable));\n }\n return '';\n } else {\n console.error('Error rendering tooltip due to unknown AST node ' + JSON.stringify(node));\n }\n };\n return ast.map(render_node).join('');\n };\n /**\n * Shortcut method for getting the data bound to a tool tip.\n * @param {Element} node\n * @returns {*} The first element of data bound to the tooltip\n */\n LocusZoom.getToolTipData = function (node) {\n if (typeof node != 'object' || typeof node.parentNode == 'undefined') {\n throw new Error('Invalid node object');\n }\n // If this node is a locuszoom tool tip then return its data\n var selector = d3.select(node);\n if (selector.classed('lz-data_layer-tooltip') && typeof selector.data()[0] != 'undefined') {\n return selector.data()[0];\n } else {\n return LocusZoom.getToolTipData(node.parentNode);\n }\n };\n /**\n * Shortcut method for getting a reference to the data layer that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.getToolTipDataLayer = function (node) {\n var data = LocusZoom.getToolTipData(node);\n if (data.getDataLayer) {\n return data.getDataLayer();\n }\n return null;\n };\n /**\n * Shortcut method for getting a reference to the panel that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.getToolTipPanel = function (node) {\n var data_layer = LocusZoom.getToolTipDataLayer(node);\n if (data_layer) {\n return data_layer.parent;\n }\n return null;\n };\n /**\n * Shortcut method for getting a reference to the plot that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.getToolTipPlot = function (node) {\n var panel = LocusZoom.getToolTipPanel(node);\n if (panel) {\n return panel.parent;\n }\n return null;\n };\n /**\n * Generate a curtain object for a plot, panel, or any other subdivision of a layout\n * The panel curtain, like the plot curtain is an HTML overlay that obscures the entire panel. It can be styled\n * arbitrarily and display arbitrary messages. It is useful for reporting error messages visually to an end user\n * when the error renders the panel unusable.\n * TODO: Improve type doc here\n * @returns {object}\n */\n LocusZoom.generateCurtain = function () {\n var curtain = {\n showing: false,\n selector: null,\n content_selector: null,\n hide_delay: null,\n /**\n * Generate the curtain. Any content (string) argument passed will be displayed in the curtain as raw HTML.\n * CSS (object) can be passed which will apply styles to the curtain and its content.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n show: function (content, css) {\n if (!this.curtain.showing) {\n this.curtain.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div').attr('class', 'lz-curtain').attr('id', this.id + '.curtain');\n this.curtain.content_selector = this.curtain.selector.append('div').attr('class', 'lz-curtain-content');\n this.curtain.selector.append('div').attr('class', 'lz-curtain-dismiss').html('Dismiss').on('click', function () {\n this.curtain.hide();\n }.bind(this));\n this.curtain.showing = true;\n }\n return this.curtain.update(content, css);\n }.bind(this),\n /**\n * Update the content and css of the curtain that's currently being shown. This method also adjusts the size\n * and positioning of the curtain to ensure it still covers the entire panel with no overlap.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n update: function (content, css) {\n if (!this.curtain.showing) {\n return this.curtain;\n }\n clearTimeout(this.curtain.hide_delay);\n // Apply CSS if provided\n if (typeof css == 'object') {\n this.curtain.selector.style(css);\n }\n // Update size and position\n var page_origin = this.getPageOrigin();\n this.curtain.selector.style({\n top: page_origin.y + 'px',\n left: page_origin.x + 'px',\n width: this.layout.width + 'px',\n height: this.layout.height + 'px'\n });\n this.curtain.content_selector.style({\n 'max-width': this.layout.width - 40 + 'px',\n 'max-height': this.layout.height - 40 + 'px'\n });\n // Apply content if provided\n if (typeof content == 'string') {\n this.curtain.content_selector.html(content);\n }\n return this.curtain;\n }.bind(this),\n /**\n * Remove the curtain\n * @param {number} delay Time to wait (in ms)\n */\n hide: function (delay) {\n if (!this.curtain.showing) {\n return this.curtain;\n }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.curtain.hide_delay);\n this.curtain.hide_delay = setTimeout(this.curtain.hide, delay);\n return this.curtain;\n }\n // Remove curtain\n this.curtain.selector.remove();\n this.curtain.selector = null;\n this.curtain.content_selector = null;\n this.curtain.showing = false;\n return this.curtain;\n }.bind(this)\n };\n return curtain;\n };\n /**\n * Generate a loader object for a plot, panel, or any other subdivision of a layout\n *\n * The panel loader is a small HTML overlay that appears in the lower left corner of the panel. It cannot be styled\n * arbitrarily, but can show a custom message and show a minimalist loading bar that can be updated to specific\n * completion percentages or be animated.\n * TODO Improve type documentation\n * @returns {object}\n */\n LocusZoom.generateLoader = function () {\n var loader = {\n showing: false,\n selector: null,\n content_selector: null,\n progress_selector: null,\n cancel_selector: null,\n /**\n * Show a loading indicator\n * @param {string} [content='Loading...'] Loading message (displayed as raw HTML)\n */\n show: function (content) {\n // Generate loader\n if (!this.loader.showing) {\n this.loader.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div').attr('class', 'lz-loader').attr('id', this.id + '.loader');\n this.loader.content_selector = this.loader.selector.append('div').attr('class', 'lz-loader-content');\n this.loader.progress_selector = this.loader.selector.append('div').attr('class', 'lz-loader-progress-container').append('div').attr('class', 'lz-loader-progress');\n /* TODO: figure out how to make this cancel button work\n this.loader.cancel_selector = this.loader.selector.append(\"div\")\n .attr(\"class\", \"lz-loader-cancel\").html(\"Cancel\")\n .on(\"click\", function(){\n this.loader.hide();\n }.bind(this));\n */\n this.loader.showing = true;\n if (typeof content == 'undefined') {\n content = 'Loading...';\n }\n }\n return this.loader.update(content);\n }.bind(this),\n /**\n * Update the currently displayed loader and ensure the new content is positioned correctly.\n * @param {string} content The text to display (as raw HTML). If not a string, will be ignored.\n * @param {number} [percent] A number from 1-100. If a value is specified, it will stop all animations\n * in progress.\n */\n update: function (content, percent) {\n if (!this.loader.showing) {\n return this.loader;\n }\n clearTimeout(this.loader.hide_delay);\n // Apply content if provided\n if (typeof content == 'string') {\n this.loader.content_selector.html(content);\n }\n // Update size and position\n var padding = 6;\n // is there a better place to store/define this?\n var page_origin = this.getPageOrigin();\n var loader_boundrect = this.loader.selector.node().getBoundingClientRect();\n this.loader.selector.style({\n top: page_origin.y + this.layout.height - loader_boundrect.height - padding + 'px',\n left: page_origin.x + padding + 'px'\n });\n /* Uncomment this code when a functional cancel button can be shown\n var cancel_boundrect = this.loader.cancel_selector.node().getBoundingClientRect();\n this.loader.content_selector.style({\n \"padding-right\": (cancel_boundrect.width + padding) + \"px\"\n });\n */\n // Apply percent if provided\n if (typeof percent == 'number') {\n this.loader.progress_selector.style({ width: Math.min(Math.max(percent, 1), 100) + '%' });\n }\n return this.loader;\n }.bind(this),\n /**\n * Adds a class to the loading bar that makes it loop infinitely in a loading animation. Useful when exact\n * percent progress is not available.\n */\n animate: function () {\n this.loader.progress_selector.classed('lz-loader-progress-animated', true);\n return this.loader;\n }.bind(this),\n /**\n * Sets the loading bar in the loader to percentage width equal to the percent (number) value passed. Percents\n * will automatically be limited to a range of 1 to 100. Will stop all animations in progress.\n */\n setPercentCompleted: function (percent) {\n this.loader.progress_selector.classed('lz-loader-progress-animated', false);\n return this.loader.update(null, percent);\n }.bind(this),\n /**\n * Remove the loader\n * @param {number} delay Time to wait (in ms)\n */\n hide: function (delay) {\n if (!this.loader.showing) {\n return this.loader;\n }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.loader.hide_delay);\n this.loader.hide_delay = setTimeout(this.loader.hide, delay);\n return this.loader;\n }\n // Remove loader\n this.loader.selector.remove();\n this.loader.selector = null;\n this.loader.content_selector = null;\n this.loader.progress_selector = null;\n this.loader.cancel_selector = null;\n this.loader.showing = false;\n return this.loader;\n }.bind(this)\n };\n return loader;\n };\n /**\n * Create a new subclass following classical inheritance patterns. Some registry singletons use this internally to\n * enable code reuse and customization of known LZ core functionality.\n *\n * @param {Function} parent A parent class constructor that will be extended by the child class\n * @param {Object} extra An object of additional properties and methods to add/override behavior for the child class.\n * The special \"constructor\" property can be used to specify a custom constructor, or it will call parent by default.\n * Implementer must manage super calls when overriding the constructor.\n * @returns {Function} The constructor for the new child class\n */\n LocusZoom.subclass = function (parent, extra) {\n if (typeof parent !== 'function') {\n throw new Error('Parent must be a callable constructor');\n }\n extra = extra || {};\n var Sub = extra.hasOwnProperty('constructor') ? extra.constructor : function () {\n parent.apply(this, arguments);\n };\n Sub.prototype = Object.create(parent.prototype);\n Object.keys(extra).forEach(function (k) {\n Sub.prototype[k] = extra[k];\n });\n return Sub;\n };\n /**\n * LocusZoom optional extensions will live under this namespace.\n *\n * Extension code is not part of the core LocusZoom app.js bundle.\n * @namespace\n * @public\n */\n LocusZoom.ext = {};\n /* global LocusZoom */\n 'use strict';\n var LZ_SIG_THRESHOLD_LOGP = 7.301;\n // -log10(.05/1e6)\n /**\n * Manage known layouts for all parts of the LocusZoom plot\n *\n * This registry allows for layouts to be reused and customized many times on a page, using a common base pattern.\n * It handles the work of ensuring that each new instance of the layout has no shared state with other copies.\n *\n * @class\n */\n LocusZoom.Layouts = function () {\n var obj = {};\n var layouts = {\n 'plot': {},\n 'panel': {},\n 'data_layer': {},\n 'dashboard': {},\n 'dashboard_components': {},\n 'tooltip': {}\n };\n /**\n * Generate a layout configuration object\n * @param {('plot'|'panel'|'data_layer'|'dashboard'|'tooltip')} type The type of layout to retrieve\n * @param {string} name Identifier of the predefined layout within the specified type\n * @param {object} [modifications] Custom properties that override default settings for this layout\n * @returns {object} A JSON-serializable object representation\n */\n obj.get = function (type, name, modifications) {\n if (typeof type != 'string' || typeof name != 'string') {\n throw new Error('invalid arguments passed to LocusZoom.Layouts.get, requires string (layout type) and string (layout name)');\n } else if (layouts[type][name]) {\n // Get the base layout\n var layout = LocusZoom.Layouts.merge(modifications || {}, layouts[type][name]);\n // If \"unnamespaced\" is true then strike that from the layout and return the layout without namespacing\n if (layout.unnamespaced) {\n delete layout.unnamespaced;\n return JSON.parse(JSON.stringify(layout));\n }\n // Determine the default namespace for namespaced values\n var default_namespace = '';\n if (typeof layout.namespace == 'string') {\n default_namespace = layout.namespace;\n } else if (typeof layout.namespace == 'object' && Object.keys(layout.namespace).length) {\n if (typeof layout.namespace.default != 'undefined') {\n default_namespace = layout.namespace.default;\n } else {\n default_namespace = layout.namespace[Object.keys(layout.namespace)[0]].toString();\n }\n }\n default_namespace += default_namespace.length ? ':' : '';\n // Apply namespaces to layout, recursively\n var applyNamespaces = function (element, namespace) {\n if (namespace) {\n if (typeof namespace == 'string') {\n namespace = { default: namespace };\n }\n } else {\n namespace = { default: '' };\n }\n if (typeof element == 'string') {\n var re = /\\{\\{namespace(\\[[A-Za-z_0-9]+\\]|)\\}\\}/g;\n var match, base, key, resolved_namespace;\n var replace = [];\n while ((match = re.exec(element)) !== null) {\n base = match[0];\n key = match[1].length ? match[1].replace(/(\\[|\\])/g, '') : null;\n resolved_namespace = default_namespace;\n if (namespace != null && typeof namespace == 'object' && typeof namespace[key] != 'undefined') {\n resolved_namespace = namespace[key] + (namespace[key].length ? ':' : '');\n }\n replace.push({\n base: base,\n namespace: resolved_namespace\n });\n }\n for (var r in replace) {\n element = element.replace(replace[r].base, replace[r].namespace);\n }\n } else if (typeof element == 'object' && element != null) {\n if (typeof element.namespace != 'undefined') {\n var merge_namespace = typeof element.namespace == 'string' ? { default: element.namespace } : element.namespace;\n namespace = LocusZoom.Layouts.merge(namespace, merge_namespace);\n }\n var namespaced_element, namespaced_property;\n for (var property in element) {\n if (property === 'namespace') {\n continue;\n }\n namespaced_element = applyNamespaces(element[property], namespace);\n namespaced_property = applyNamespaces(property, namespace);\n if (property !== namespaced_property) {\n delete element[property];\n }\n element[namespaced_property] = namespaced_element;\n }\n }\n return element;\n };\n layout = applyNamespaces(layout, layout.namespace);\n // Return the layout as valid JSON only\n return JSON.parse(JSON.stringify(layout));\n } else {\n throw new Error('layout type [' + type + '] name [' + name + '] not found');\n }\n };\n /** @private */\n obj.set = function (type, name, layout) {\n if (typeof type != 'string' || typeof name != 'string' || typeof layout != 'object') {\n throw new Error('unable to set new layout; bad arguments passed to set()');\n }\n if (!layouts[type]) {\n layouts[type] = {};\n }\n if (layout) {\n return layouts[type][name] = JSON.parse(JSON.stringify(layout));\n } else {\n delete layouts[type][name];\n return null;\n }\n };\n /**\n * Register a new layout definition by name.\n *\n * @param {string} type The type of layout to add. Usually, this will be one of the predefined LocusZoom types,\n * but if you pass a different name, this method will automatically create the new `type` bucket\n * @param {string} name The identifier of the newly added layout\n * @param {object} [layout] A JSON-serializable object containing configuration properties for this layout\n * @returns The JSON representation of the newly created layout\n */\n obj.add = function (type, name, layout) {\n return obj.set(type, name, layout);\n };\n /**\n * List all registered layouts\n * @param [type] Optionally narrow the list to only layouts of a specific type; else return all known layouts\n * @returns {*}\n */\n obj.list = function (type) {\n if (!layouts[type]) {\n var list = {};\n Object.keys(layouts).forEach(function (type) {\n list[type] = Object.keys(layouts[type]);\n });\n return list;\n } else {\n return Object.keys(layouts[type]);\n }\n };\n /**\n * A helper method used for merging two objects. If a key is present in both, takes the value from the first object\n * Values from `default_layout` will be cleanly copied over, ensuring no references or shared state.\n *\n * Frequently used for preparing custom layouts. Both objects should be JSON-serializable.\n *\n * @param {object} custom_layout An object containing configuration parameters that override or add to defaults\n * @param {object} default_layout An object containing default settings.\n * @returns {object} The custom layout is modified in place and also returned from this method.\n */\n obj.merge = function (custom_layout, default_layout) {\n if (typeof custom_layout !== 'object' || typeof default_layout !== 'object') {\n throw new Error('LocusZoom.Layouts.merge only accepts two layout objects; ' + typeof custom_layout + ', ' + typeof default_layout + ' given');\n }\n for (var property in default_layout) {\n if (!default_layout.hasOwnProperty(property)) {\n continue;\n }\n // Get types for comparison. Treat nulls in the custom layout as undefined for simplicity.\n // (javascript treats nulls as \"object\" when we just want to overwrite them as if they're undefined)\n // Also separate arrays from objects as a discrete type.\n var custom_type = custom_layout[property] === null ? 'undefined' : typeof custom_layout[property];\n var default_type = typeof default_layout[property];\n if (custom_type === 'object' && Array.isArray(custom_layout[property])) {\n custom_type = 'array';\n }\n if (default_type === 'object' && Array.isArray(default_layout[property])) {\n default_type = 'array';\n }\n // Unsupported property types: throw an exception\n if (custom_type === 'function' || default_type === 'function') {\n throw new Error('LocusZoom.Layouts.merge encountered an unsupported property type');\n }\n // Undefined custom value: pull the default value\n if (custom_type === 'undefined') {\n custom_layout[property] = JSON.parse(JSON.stringify(default_layout[property]));\n continue;\n }\n // Both values are objects: merge recursively\n if (custom_type === 'object' && default_type === 'object') {\n custom_layout[property] = LocusZoom.Layouts.merge(custom_layout[property], default_layout[property]);\n continue;\n }\n }\n return custom_layout;\n };\n return obj;\n }();\n /**\n * Tooltip Layouts\n * @namespace LocusZoom.Layouts.tooltips\n */\n LocusZoom.Layouts.add('tooltip', 'standard_association', {\n namespace: { 'assoc': 'assoc' },\n closable: true,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: '{{{{namespace[assoc]}}variant|htmlescape}}
' + 'P Value: {{{{namespace[assoc]}}log_pvalue|logtoscinotation|htmlescape}}
' + 'Ref. Allele: {{{{namespace[assoc]}}ref_allele|htmlescape}}
' + 'Make LD Reference
'\n });\n LocusZoom.Layouts.add('tooltip', 'covariates_model_association', function () {\n var covariates_model_association = LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true });\n covariates_model_association.html += 'Condition on Variant
';\n return covariates_model_association;\n }());\n LocusZoom.Layouts.add('tooltip', 'standard_genes', {\n closable: true,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: '

{{gene_name|htmlescape}}

' + 'Gene ID: {{gene_id|htmlescape}}
' + 'Transcript ID: {{transcript_id|htmlescape}}
' + '{{#if pLI}}' + '' + '' + '' + '' + '
ConstraintExpected variantsObserved variantsConst. Metric
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
o/e = {{oe_syn}} ({{oe_syn_lower}} - {{oe_syn_upper}})
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
o/e = {{oe_mis}} ({{oe_mis_lower}} - {{oe_mis_upper}})
pLoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
o/e = {{oe_lof}} ({{oe_lof_lower}} - {{oe_lof_upper}})

{{/if}}' + 'More data on gnomAD'\n });\n LocusZoom.Layouts.add('tooltip', 'standard_intervals', {\n namespace: { 'intervals': 'intervals' },\n closable: false,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: '{{{{namespace[intervals]}}state_name|htmlescape}}
{{{{namespace[intervals]}}start|htmlescape}}-{{{{namespace[intervals]}}end|htmlescape}}'\n });\n LocusZoom.Layouts.add('tooltip', 'catalog_variant', {\n namespace: {\n 'assoc': 'assoc',\n 'catalog': 'catalog'\n },\n closable: true,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: '{{{{namespace[catalog]}}variant|htmlescape}}
' + 'Catalog entries: {{n_catalog_matches|htmlescape}}
' + 'Top Trait: {{{{namespace[catalog]}}trait|htmlescape}}
' + 'Top P Value: {{{{namespace[catalog]}}log_pvalue|logtoscinotation}}
' // User note: if a different catalog is used, the tooltip will need to be replaced with a different link URL\n+ 'More: GWAS catalog / dbSNP'\n });\n /**\n * Data Layer Layouts: represent specific information from a data source\n * @namespace Layouts.data_layer\n */\n LocusZoom.Layouts.add('data_layer', 'significance', {\n id: 'significance',\n type: 'orthogonal_line',\n orientation: 'horizontal',\n offset: LZ_SIG_THRESHOLD_LOGP\n });\n LocusZoom.Layouts.add('data_layer', 'recomb_rate', {\n namespace: { 'recomb': 'recomb' },\n id: 'recombrate',\n type: 'line',\n fields: [\n '{{namespace[recomb]}}position',\n '{{namespace[recomb]}}recomb_rate'\n ],\n z_index: 1,\n style: {\n 'stroke': '#0000FF',\n 'stroke-width': '1.5px'\n },\n x_axis: { field: '{{namespace[recomb]}}position' },\n y_axis: {\n axis: 2,\n field: '{{namespace[recomb]}}recomb_rate',\n floor: 0,\n ceiling: 100\n }\n });\n LocusZoom.Layouts.add('data_layer', 'association_pvalues', {\n namespace: {\n 'assoc': 'assoc',\n 'ld': 'ld'\n },\n id: 'associationpvalues',\n type: 'scatter',\n point_shape: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 'diamond',\n else: 'circle'\n }\n },\n point_size: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 80,\n else: 40\n }\n },\n color: [\n {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: '#9632b8'\n }\n },\n {\n scale_function: 'numerical_bin',\n field: '{{namespace[ld]}}state',\n parameters: {\n breaks: [\n 0,\n 0.2,\n 0.4,\n 0.6,\n 0.8\n ],\n values: [\n '#357ebd',\n '#46b8da',\n '#5cb85c',\n '#eea236',\n '#d43f3a'\n ]\n }\n },\n '#B8B8B8'\n ],\n legend: [\n {\n shape: 'diamond',\n color: '#9632b8',\n size: 40,\n label: 'LD Ref Var',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#d43f3a',\n size: 40,\n label: '1.0 > r\\xB2 \\u2265 0.8',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#eea236',\n size: 40,\n label: '0.8 > r\\xB2 \\u2265 0.6',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#5cb85c',\n size: 40,\n label: '0.6 > r\\xB2 \\u2265 0.4',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#46b8da',\n size: 40,\n label: '0.4 > r\\xB2 \\u2265 0.2',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#357ebd',\n size: 40,\n label: '0.2 > r\\xB2 \\u2265 0.0',\n class: 'lz-data_layer-scatter'\n },\n {\n shape: 'circle',\n color: '#B8B8B8',\n size: 40,\n label: 'no r\\xB2 data',\n class: 'lz-data_layer-scatter'\n }\n ],\n label: null,\n fields: [\n '{{namespace[assoc]}}variant',\n '{{namespace[assoc]}}position',\n '{{namespace[assoc]}}log_pvalue',\n '{{namespace[assoc]}}log_pvalue|logtoscinotation',\n '{{namespace[assoc]}}ref_allele',\n '{{namespace[ld]}}state',\n '{{namespace[ld]}}isrefvar'\n ],\n id_field: '{{namespace[assoc]}}variant',\n z_index: 2,\n x_axis: { field: '{{namespace[assoc]}}position' },\n y_axis: {\n axis: 1,\n field: '{{namespace[assoc]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.1,\n min_extent: [\n 0,\n 10\n ]\n },\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true })\n });\n LocusZoom.Layouts.add('data_layer', 'association_pvalues_catalog', function () {\n // Slightly modify an existing layout\n var l = LocusZoom.Layouts.get('data_layer', 'association_pvalues', {\n unnamespaced: true,\n id: 'associationpvaluescatalog',\n fill_opacity: 0.7\n });\n l.tooltip.html += '{{#if {{namespace[catalog]}}rsid}}
See hits in GWAS catalog{{/if}}';\n l.namespace.catalog = 'catalog';\n l.fields.push('{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait', '{{namespace[catalog]}}log_pvalue');\n return l;\n }());\n LocusZoom.Layouts.add('data_layer', 'phewas_pvalues', {\n namespace: { 'phewas': 'phewas' },\n id: 'phewaspvalues',\n type: 'category_scatter',\n point_shape: 'circle',\n point_size: 70,\n tooltip_positioning: 'vertical',\n id_field: '{{namespace[phewas]}}id',\n fields: [\n '{{namespace[phewas]}}id',\n '{{namespace[phewas]}}log_pvalue',\n '{{namespace[phewas]}}trait_group',\n '{{namespace[phewas]}}trait_label'\n ],\n x_axis: {\n field: '{{namespace[phewas]}}x',\n // Synthetic/derived field added by `category_scatter` layer\n category_field: '{{namespace[phewas]}}trait_group',\n lower_buffer: 0.025,\n upper_buffer: 0.025\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[phewas]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.15\n },\n color: [{\n field: '{{namespace[phewas]}}trait_group',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [],\n values: [],\n null_value: '#B8B8B8'\n }\n }],\n fill_opacity: 0.7,\n tooltip: {\n closable: true,\n show: {\n or: [\n 'highlighted',\n 'selected'\n ]\n },\n hide: {\n and: [\n 'unhighlighted',\n 'unselected'\n ]\n },\n html: [\n 'Trait: {{{{namespace[phewas]}}trait_label|htmlescape}}
',\n 'Trait Category: {{{{namespace[phewas]}}trait_group|htmlescape}}
',\n 'P-value: {{{{namespace[phewas]}}log_pvalue|logtoscinotation|htmlescape}}
'\n ].join('')\n },\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n label: {\n text: '{{{{namespace[phewas]}}trait_label|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [{\n field: '{{namespace[phewas]}}log_pvalue',\n operator: '>=',\n value: 20\n }],\n style: {\n 'font-size': '14px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n });\n LocusZoom.Layouts.add('data_layer', 'genes', {\n namespace: {\n 'gene': 'gene',\n 'constraint': 'constraint'\n },\n id: 'genes',\n type: 'genes',\n fields: [\n '{{namespace[gene]}}all',\n '{{namespace[constraint]}}all'\n ],\n id_field: 'gene_id',\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_genes', { unnamespaced: true })\n });\n LocusZoom.Layouts.add('data_layer', 'genome_legend', {\n namespace: { 'genome': 'genome' },\n id: 'genome_legend',\n type: 'genome_legend',\n fields: [\n '{{namespace[genome]}}chr',\n '{{namespace[genome]}}base_pairs'\n ],\n x_axis: {\n floor: 0,\n ceiling: 2881033286\n }\n });\n LocusZoom.Layouts.add('data_layer', 'intervals', {\n namespace: { 'intervals': 'intervals' },\n id: 'intervals',\n type: 'intervals',\n fields: [\n '{{namespace[intervals]}}start',\n '{{namespace[intervals]}}end',\n '{{namespace[intervals]}}state_id',\n '{{namespace[intervals]}}state_name'\n ],\n id_field: '{{namespace[intervals]}}start',\n start_field: '{{namespace[intervals]}}start',\n end_field: '{{namespace[intervals]}}end',\n track_split_field: '{{namespace[intervals]}}state_id',\n split_tracks: true,\n always_hide_legend: false,\n color: {\n field: '{{namespace[intervals]}}state_id',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [\n 1,\n 2,\n 3,\n 4,\n 5,\n 6,\n 7,\n 8,\n 9,\n 10,\n 11,\n 12,\n 13\n ],\n values: [\n 'rgb(212,63,58)',\n 'rgb(250,120,105)',\n 'rgb(252,168,139)',\n 'rgb(240,189,66)',\n 'rgb(250,224,105)',\n 'rgb(240,238,84)',\n 'rgb(244,252,23)',\n 'rgb(23,232,252)',\n 'rgb(32,191,17)',\n 'rgb(23,166,77)',\n 'rgb(32,191,17)',\n 'rgb(162,133,166)',\n 'rgb(212,212,212)'\n ],\n null_value: '#B8B8B8'\n }\n },\n legend: [\n {\n shape: 'rect',\n color: 'rgb(212,63,58)',\n width: 9,\n label: 'Active Promoter',\n '{{namespace[intervals]}}state_id': 1\n },\n {\n shape: 'rect',\n color: 'rgb(250,120,105)',\n width: 9,\n label: 'Weak Promoter',\n '{{namespace[intervals]}}state_id': 2\n },\n {\n shape: 'rect',\n color: 'rgb(252,168,139)',\n width: 9,\n label: 'Poised Promoter',\n '{{namespace[intervals]}}state_id': 3\n },\n {\n shape: 'rect',\n color: 'rgb(240,189,66)',\n width: 9,\n label: 'Strong enhancer',\n '{{namespace[intervals]}}state_id': 4\n },\n {\n shape: 'rect',\n color: 'rgb(250,224,105)',\n width: 9,\n label: 'Strong enhancer',\n '{{namespace[intervals]}}state_id': 5\n },\n {\n shape: 'rect',\n color: 'rgb(240,238,84)',\n width: 9,\n label: 'Weak enhancer',\n '{{namespace[intervals]}}state_id': 6\n },\n {\n shape: 'rect',\n color: 'rgb(244,252,23)',\n width: 9,\n label: 'Weak enhancer',\n '{{namespace[intervals]}}state_id': 7\n },\n {\n shape: 'rect',\n color: 'rgb(23,232,252)',\n width: 9,\n label: 'Insulator',\n '{{namespace[intervals]}}state_id': 8\n },\n {\n shape: 'rect',\n color: 'rgb(32,191,17)',\n width: 9,\n label: 'Transcriptional transition',\n '{{namespace[intervals]}}state_id': 9\n },\n {\n shape: 'rect',\n color: 'rgb(23,166,77)',\n width: 9,\n label: 'Transcriptional elongation',\n '{{namespace[intervals]}}state_id': 10\n },\n {\n shape: 'rect',\n color: 'rgb(136,240,129)',\n width: 9,\n label: 'Weak transcribed',\n '{{namespace[intervals]}}state_id': 11\n },\n {\n shape: 'rect',\n color: 'rgb(162,133,166)',\n width: 9,\n label: 'Polycomb-repressed',\n '{{namespace[intervals]}}state_id': 12\n },\n {\n shape: 'rect',\n color: 'rgb(212,212,212)',\n width: 9,\n label: 'Heterochromatin / low signal',\n '{{namespace[intervals]}}state_id': 13\n }\n ],\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_intervals', { unnamespaced: true })\n });\n LocusZoom.Layouts.add('data_layer', 'annotation_catalog', {\n // Identify GWAS hits that are present in the GWAS catalog\n namespace: {\n 'assoc': 'assoc',\n 'catalog': 'catalog'\n },\n id: 'annotation_catalog',\n type: 'annotation_track',\n id_field: '{{namespace[catalog]}}variant',\n x_axis: { field: '{{namespace[assoc]}}position' },\n color: '#0000CC',\n fields: [\n '{{namespace[assoc]}}variant',\n '{{namespace[assoc]}}chromosome',\n '{{namespace[assoc]}}position',\n '{{namespace[catalog]}}variant',\n '{{namespace[catalog]}}rsid',\n '{{namespace[catalog]}}trait',\n '{{namespace[catalog]}}log_pvalue',\n '{{namespace[catalog]}}pos'\n ],\n filters: [\n // Specify which points to show on the track. Any selection must satisfy ALL filters\n [\n '{{namespace[catalog]}}rsid',\n '!=',\n null\n ],\n [\n '{{namespace[catalog]}}log_pvalue',\n '>',\n LZ_SIG_THRESHOLD_LOGP\n ]\n ],\n behaviors: {\n onmouseover: [{\n action: 'set',\n status: 'highlighted'\n }],\n onmouseout: [{\n action: 'unset',\n status: 'highlighted'\n }],\n onclick: [{\n action: 'toggle',\n status: 'selected',\n exclusive: true\n }],\n onshiftclick: [{\n action: 'toggle',\n status: 'selected'\n }]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'catalog_variant', { unnamespaced: true }),\n tooltip_positioning: 'top'\n });\n /**\n * Individual dashboard buttons\n * @namespace Layouts.dashboard_components\n */\n LocusZoom.Layouts.add('dashboard_components', 'ldlz2_pop_selector', {\n // **Note**: this widget is aimed at the LDLZ2 datasource, and the UM 1000G LDServer. Older LZ usages\n // (on the original LD data source) will not work with these population names.\n type: 'set_state',\n position: 'right',\n color: 'blue',\n button_html: 'LD Population: ',\n show_selected: true,\n button_title: 'Select LD Population: ',\n state_field: 'ld_pop',\n // This list below is hardcoded to work with the UMich LDServer, default 1000G populations\n // It can be customized to work with other LD servers that specify population differently\n // https://portaldev.sph.umich.edu/ld/genome_builds/GRCh37/references/1000G/populations\n options: [\n {\n display_name: 'ALL (default)',\n value: 'ALL'\n },\n {\n display_name: 'AFR',\n value: 'AFR'\n },\n {\n display_name: 'AMR',\n value: 'AMR'\n },\n {\n display_name: 'EAS',\n value: 'EAS'\n },\n {\n display_name: 'EUR',\n value: 'EUR'\n },\n {\n display_name: 'SAS',\n value: 'SAS'\n }\n ]\n });\n /**\n * Dashboard Layouts: Collections of toolbar buttons etc\n * @namespace Layouts.dashboard\n */\n LocusZoom.Layouts.add('dashboard', 'standard_panel', {\n components: [\n {\n type: 'remove_panel',\n position: 'right',\n color: 'red',\n group_position: 'end'\n },\n {\n type: 'move_panel_up',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'move_panel_down',\n position: 'right',\n group_position: 'start',\n style: { 'margin-left': '0.75em' }\n }\n ]\n });\n LocusZoom.Layouts.add('dashboard', 'standard_plot', {\n components: [\n {\n type: 'title',\n title: 'LocusZoom',\n subtitle: 'v' + LocusZoom.version + '',\n position: 'left'\n },\n {\n type: 'download',\n position: 'right'\n }\n ]\n });\n LocusZoom.Layouts.add('dashboard', 'covariates_model_plot', function () {\n var covariates_model_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n covariates_model_plot_dashboard.components.push({\n type: 'covariates_model',\n button_html: 'Model',\n button_title: 'Show and edit covariates currently in model',\n position: 'left'\n });\n return covariates_model_plot_dashboard;\n }());\n LocusZoom.Layouts.add('dashboard', 'region_nav_plot', function () {\n var region_nav_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n region_nav_plot_dashboard.components.push({\n type: 'shift_region',\n step: 500000,\n button_html: '>>',\n position: 'right',\n group_position: 'end'\n }, {\n type: 'shift_region',\n step: 50000,\n button_html: '>',\n position: 'right',\n group_position: 'middle'\n }, {\n type: 'zoom_region',\n step: 0.2,\n position: 'right',\n group_position: 'middle'\n }, {\n type: 'zoom_region',\n step: -0.2,\n position: 'right',\n group_position: 'middle'\n }, {\n type: 'shift_region',\n step: -50000,\n button_html: '<',\n position: 'right',\n group_position: 'middle'\n }, {\n type: 'shift_region',\n step: -500000,\n button_html: '<<',\n position: 'right',\n group_position: 'start'\n });\n return region_nav_plot_dashboard;\n }());\n /**\n * Panel Layouts\n * @namespace Layouts.panel\n */\n LocusZoom.Layouts.add('panel', 'association', {\n id: 'association',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 200,\n proportional_width: 1,\n margin: {\n top: 35,\n right: 50,\n bottom: 40,\n left: 50\n },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_legend',\n position: 'right'\n });\n return l;\n }(),\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n },\n y2: {\n label: 'Recombination Rate (cM/Mb)',\n label_offset: 40\n }\n },\n legend: {\n orientation: 'vertical',\n origin: {\n x: 55,\n y: 40\n },\n hidden: true\n },\n interaction: {\n drag_background_to_pan: true,\n drag_x_ticks_to_scale: true,\n drag_y1_ticks_to_scale: true,\n drag_y2_ticks_to_scale: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues', { unnamespaced: true })\n ]\n });\n LocusZoom.Layouts.add('panel', 'association_catalog', function () {\n var l = LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n id: 'associationcatalog',\n namespace: {\n 'assoc': 'assoc',\n 'ld': 'ld',\n 'catalog': 'catalog'\n } // Required to resolve display options\n });\n l.dashboard.components.push({\n type: 'display_options',\n position: 'right',\n color: 'blue',\n // Below: special config specific to this widget\n button_html: 'Display options...',\n button_title: 'Control how plot items are displayed',\n layer_name: 'associationpvaluescatalog',\n default_config_display_name: 'No catalog labels (default)',\n // display name for the default plot color option (allow user to revert to plot defaults)\n options: [{\n // First dropdown menu item\n display_name: 'Label catalog traits',\n // Human readable representation of field name\n display: {\n // Specify layout directives that control display of the plot for this option\n label: {\n text: '{{{{namespace[catalog]}}trait|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n // Only label points if they are significant for some trait in the catalog, AND in high LD\n // with the top hit of interest\n {\n field: '{{namespace[catalog]}}trait',\n operator: '!=',\n value: null\n },\n {\n field: '{{namespace[catalog]}}log_pvalue',\n operator: '>',\n value: LZ_SIG_THRESHOLD_LOGP\n },\n {\n field: '{{namespace[ld]}}state',\n operator: '>',\n value: 0.4\n }\n ],\n style: {\n 'font-size': '10px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n }\n }]\n });\n l.data_layers = [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues_catalog', { unnamespaced: true })\n ];\n return l;\n }());\n LocusZoom.Layouts.add('panel', 'genes', {\n id: 'genes',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 112.5,\n proportional_width: 1,\n margin: {\n top: 20,\n right: 50,\n bottom: 20,\n left: 50\n },\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n dashboard: function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'resize_to_data',\n position: 'right',\n button_html: 'Show all genes'\n });\n return l;\n }(),\n data_layers: [LocusZoom.Layouts.get('data_layer', 'genes', { unnamespaced: true })]\n });\n LocusZoom.Layouts.add('panel', 'phewas', {\n id: 'phewas',\n width: 800,\n height: 300,\n min_width: 800,\n min_height: 300,\n proportional_width: 1,\n margin: {\n top: 20,\n right: 50,\n bottom: 120,\n left: 50\n },\n inner_border: 'rgb(210, 210, 210)',\n axes: {\n x: {\n ticks: {\n // Object based config (shared defaults; allow layers to specify ticks)\n style: {\n 'font-weight': 'bold',\n 'font-size': '11px',\n 'text-anchor': 'start'\n },\n transform: 'rotate(50)',\n position: 'left' // Special param recognized by `category_scatter` layers\n }\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'phewas_pvalues', { unnamespaced: true })\n ]\n });\n LocusZoom.Layouts.add('panel', 'genome_legend', {\n id: 'genome_legend',\n width: 800,\n height: 50,\n origin: {\n x: 0,\n y: 300\n },\n min_width: 800,\n min_height: 50,\n proportional_width: 1,\n margin: {\n top: 0,\n right: 50,\n bottom: 35,\n left: 50\n },\n axes: {\n x: {\n label: 'Genomic Position (number denotes chromosome)',\n label_offset: 35,\n ticks: [\n {\n x: 124625310,\n text: '1',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 370850307,\n text: '2',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 591461209,\n text: '3',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 786049562,\n text: '4',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 972084330,\n text: '5',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1148099493,\n text: '6',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1313226358,\n text: '7',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1465977701,\n text: '8',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1609766427,\n text: '9',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1748140516,\n text: '10',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1883411148,\n text: '11',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2017840353,\n text: '12',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2142351240,\n text: '13',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2253610949,\n text: '14',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2358551415,\n text: '15',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2454994487,\n text: '16',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2540769469,\n text: '17',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2620405698,\n text: '18',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2689008813,\n text: '19',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2750086065,\n text: '20',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2805663772,\n text: '21',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2855381003,\n text: '22',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n }\n ]\n }\n },\n data_layers: [LocusZoom.Layouts.get('data_layer', 'genome_legend', { unnamespaced: true })]\n });\n LocusZoom.Layouts.add('panel', 'intervals', {\n id: 'intervals',\n width: 1000,\n height: 50,\n min_width: 500,\n min_height: 50,\n margin: {\n top: 25,\n right: 150,\n bottom: 5,\n left: 50\n },\n dashboard: function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_split_tracks',\n data_layer_id: 'intervals',\n position: 'right'\n });\n return l;\n }(),\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n legend: {\n hidden: true,\n orientation: 'horizontal',\n origin: {\n x: 50,\n y: 0\n },\n pad_from_bottom: 5\n },\n data_layers: [LocusZoom.Layouts.get('data_layer', 'intervals', { unnamespaced: true })]\n });\n LocusZoom.Layouts.add('panel', 'annotation_catalog', {\n id: 'annotationcatalog',\n width: 800,\n height: 50,\n min_height: 50,\n proportional_width: 1,\n margin: {\n top: 25,\n right: 50,\n bottom: 0,\n left: 50\n },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true }),\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [LocusZoom.Layouts.get('data_layer', 'annotation_catalog', { unnamespaced: true })]\n });\n /**\n * Plot Layouts\n * @namespace Layouts.plot\n */\n LocusZoom.Layouts.add('plot', 'standard_association', {\n state: {},\n width: 800,\n height: 450,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n proportional_height: 0.5\n }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true,\n proportional_height: 0.5\n })\n ]\n });\n LocusZoom.Layouts.add('plot', 'association_catalog', {\n state: {},\n width: 800,\n height: 500,\n responsive_resize: 'width_only',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'annotation_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'association_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true })\n ]\n });\n // Shortcut to \"StandardLayout\" for backward compatibility\n LocusZoom.StandardLayout = LocusZoom.Layouts.get('plot', 'standard_association');\n LocusZoom.Layouts.add('plot', 'standard_phewas', {\n width: 800,\n height: 600,\n min_width: 800,\n min_height: 600,\n responsive_resize: 'both',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'phewas', {\n unnamespaced: true,\n proportional_height: 0.45\n }),\n LocusZoom.Layouts.get('panel', 'genome_legend', {\n unnamespaced: true,\n proportional_height: 0.1\n }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true,\n proportional_height: 0.45,\n margin: { bottom: 40 },\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n }\n }\n })\n ],\n mouse_guide: false\n });\n LocusZoom.Layouts.add('plot', 'interval_association', {\n state: {},\n width: 800,\n height: 550,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n width: 800,\n proportional_height: 225 / 570\n }),\n LocusZoom.Layouts.get('panel', 'intervals', {\n unnamespaced: true,\n proportional_height: 120 / 570\n }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true,\n width: 800,\n proportional_height: 225 / 570\n })\n ]\n });\n /* global LocusZoom */\n 'use strict';\n /**\n * A data layer is an abstract class representing a data set and its graphical representation within a panel\n * @public\n * @class\n * @param {Object} layout A JSON-serializable object describing the layout for this layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n*/\n LocusZoom.DataLayer = function (layout, parent) {\n /** @member {Boolean} */\n this.initialized = false;\n /** @member {Number} */\n this.layout_idx = null;\n /** @member {String} */\n this.id = null;\n /** @member {LocusZoom.Panel} */\n this.parent = parent || null;\n /**\n * @member {{group: d3.selection, container: d3.selection, clipRect: d3.selection}}\n */\n this.svg = {};\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n if (typeof parent != 'undefined' && parent instanceof LocusZoom.Panel) {\n this.parent_plot = parent.parent;\n }\n /** @member {Object} */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.DataLayer.DefaultLayout);\n if (this.layout.id) {\n this.id = this.layout.id;\n }\n // Ensure any axes defined in the layout have an explicit axis number (default: 1)\n if (this.layout.x_axis !== {} && typeof this.layout.x_axis.axis !== 'number') {\n this.layout.x_axis.axis = 1;\n }\n if (this.layout.y_axis !== {} && typeof this.layout.y_axis.axis !== 'number') {\n this.layout.y_axis.axis = 1;\n }\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original data layer state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n /** @member {Object} */\n this.state = {};\n /** @member {String} */\n this.state_id = null;\n this.setDefaultState();\n // Initialize parameters for storing data and tool tips\n /** @member {Array} */\n this.data = [];\n if (this.layout.tooltip) {\n /** @member {Object} */\n this.tooltips = {};\n }\n // Initialize flags for tracking global statuses\n this.global_statuses = {\n 'highlighted': false,\n 'selected': false,\n 'faded': false,\n 'hidden': false\n };\n return this;\n };\n /**\n * Instruct this datalayer to begin tracking additional fields from data sources (does not guarantee that such a field actually exists)\n *\n * Custom plots can use this to dynamically extend datalayer functionality after the plot is drawn\n *\n * (since removing core fields may break layer functionality, there is presently no hook for the inverse behavior)\n * @param fieldName\n * @param namespace\n * @param {String|String[]} transformations The name (or array of names) of transformations to apply to this field\n * @returns {String} The raw string added to the fields array\n */\n LocusZoom.DataLayer.prototype.addField = function (fieldName, namespace, transformations) {\n if (!fieldName || !namespace) {\n throw new Error('Must specify field name and namespace to use when adding field');\n }\n var fieldString = namespace + ':' + fieldName;\n if (transformations) {\n fieldString += '|';\n if (typeof transformations === 'string') {\n fieldString += transformations;\n } else if (Array.isArray(transformations)) {\n fieldString += transformations.join('|');\n } else {\n throw new Error('Must provide transformations as either a string or array of strings');\n }\n }\n var fields = this.layout.fields;\n if (fields.indexOf(fieldString) === -1) {\n fields.push(fieldString);\n }\n return fieldString;\n };\n /**\n * Define default state that should get tracked during the lifetime of this layer.\n *\n * In some special custom usages, it may be useful to completely reset a panel (eg \"click for\n * genome region\" links), plotting new data that invalidates any previously tracked state. This hook makes it\n * possible to reset without destroying the panel entirely. It is used by `Plot.clearPanelData`.\n */\n LocusZoom.DataLayer.prototype.setDefaultState = function () {\n // Define state parameters specific to this data layer. Within plot state, this will live under a key\n // `panel_name.layer_name`.\n if (this.parent) {\n this.state = this.parent.state;\n this.state_id = this.parent.id + '.' + this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n var layer_state = this.state[this.state_id];\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function (status) {\n layer_state[status] = layer_state[status] || [];\n });\n // Also initialize \"internal-only\" state fields\n layer_state['has_tooltip'] = layer_state['has_tooltip'] || [];\n }\n };\n /**\n * A basic description of keys expected in a layout. Not intended to be directly used or modified by an end user.\n * @protected\n * @type {{type: string, fields: Array, x_axis: {}, y_axis: {}}}\n */\n LocusZoom.DataLayer.DefaultLayout = {\n type: '',\n fields: [],\n x_axis: {},\n y_axis: {}\n };\n /**\n * Available statuses that individual elements can have. Each status is described by\n * a verb/antiverb and an adjective. Verbs and antiverbs are used to generate data layer\n * methods for updating the status on one or more elements. Adjectives are used in class\n * names and applied or removed from elements to have a visual representation of the status,\n * as well as used as keys in the state for tracking which elements are in which status(es)\n * @static\n * @type {{verbs: String[], adjectives: String[], menu_antiverbs: String[]}}\n */\n LocusZoom.DataLayer.Statuses = {\n verbs: [\n 'highlight',\n 'select',\n 'fade',\n 'hide'\n ],\n adjectives: [\n 'highlighted',\n 'selected',\n 'faded',\n 'hidden'\n ],\n menu_antiverbs: [\n 'unhighlight',\n 'deselect',\n 'unfade',\n 'show'\n ]\n };\n /**\n * Get the fully qualified identifier for the data layer, prefixed by any parent or container elements\n *\n * @returns {string} A dot-delimited string of the format ..\n */\n LocusZoom.DataLayer.prototype.getBaseId = function () {\n return this.parent_plot.id + '.' + this.parent.id + '.' + this.id;\n };\n /**\n * Determine the pixel height of data-bound objects represented inside this data layer. (excluding elements such as axes)\n *\n * May be used by operations that resize the data layer to fit available data\n *\n * @public\n * @returns {number}\n */\n LocusZoom.DataLayer.prototype.getAbsoluteDataHeight = function () {\n var dataBCR = this.svg.group.node().getBoundingClientRect();\n return dataBCR.height;\n };\n /**\n * Whether transitions can be applied to this data layer\n * @returns {boolean}\n */\n LocusZoom.DataLayer.prototype.canTransition = function () {\n if (!this.layout.transition) {\n return false;\n }\n return !(this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.panel_id);\n };\n /**\n * Fetch the fully qualified ID to be associated with a specific visual element, based on the data to which that\n * element is bound. In general this element ID will be unique, allowing it to be addressed directly via selectors.\n * @param {String|Object} element\n * @returns {String}\n */\n LocusZoom.DataLayer.prototype.getElementId = function (element) {\n var element_id = 'element';\n if (typeof element == 'string') {\n element_id = element;\n } else if (typeof element == 'object') {\n var id_field = this.layout.id_field || 'id';\n if (typeof element[id_field] == 'undefined') {\n throw new Error('Unable to generate element ID');\n }\n element_id = element[id_field].toString().replace(/\\W/g, '');\n }\n return (this.getBaseId() + '-' + element_id).replace(/([:.[\\],])/g, '_');\n };\n /**\n * Fetch an ID that may bind a data element to a separate visual node for displaying status\n * Examples of this might be seperate visual nodes to show select/highlight statuses, or\n * even a common/shared node to show status across many elements in a set.\n * Abstract method. It should be overridden by data layers that implement seperate status\n * nodes specifically to the use case of the data layer type.\n * @param {String|Object} element\n * @returns {String|null}\n */\n LocusZoom.DataLayer.prototype.getElementStatusNodeId = function (element) {\n return null;\n };\n /**\n * Returns a reference to the underlying data associated with a single visual element in the data layer, as\n * referenced by the unique identifier for the element\n\n * @param {String} id The unique identifier for the element, as defined by `getElementId`\n * @returns {Object|null} The data bound to that element\n */\n LocusZoom.DataLayer.prototype.getElementById = function (id) {\n var selector = d3.select('#' + id.replace(/([:.[\\],])/g, '\\\\$1'));\n // escape special characters\n if (!selector.empty() && selector.data() && selector.data().length) {\n return selector.data()[0];\n } else {\n return null;\n }\n };\n /**\n * Basic method to apply arbitrary methods and properties to data elements.\n * This is called on all data immediately after being fetched.\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.applyDataMethods = function () {\n var field_to_match = this.layout.match && this.layout.match.receive;\n var broadcast_value = this.parent_plot.state.lz_match_value;\n this.data.forEach(function (d, i) {\n // Basic toHTML() method - return the stringified value in the id_field, if defined.\n // When this layer receives data, mark whether points match (via a synthetic boolean field)\n // Any field-based layout directives (color, size, shape) can then be used to control display\n if (field_to_match && broadcast_value !== null && broadcast_value !== undefined) {\n d.lz_highlight_match = d[field_to_match] === broadcast_value;\n }\n this.data[i].toHTML = function () {\n var id_field = this.layout.id_field || 'id';\n var html = '';\n if (this.data[i][id_field]) {\n html = this.data[i][id_field].toString();\n }\n return html;\n }.bind(this);\n // getDataLayer() method - return a reference to the data layer\n this.data[i].getDataLayer = function () {\n return this;\n }.bind(this);\n // deselect() method - shortcut method to deselect the element\n this.data[i].deselect = function () {\n var data_layer = this.getDataLayer();\n data_layer.unselectElement(this);\n };\n }.bind(this));\n this.applyCustomDataMethods();\n return this;\n };\n /**\n * Hook that allows custom datalayers to apply additional methods and properties to data elements as needed\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.applyCustomDataMethods = function () {\n return this;\n };\n /**\n * Initialize a data layer\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.initialize = function () {\n // Append a container group element to house the main data layer group element and the clip path\n this.svg.container = this.parent.svg.group.append('g').attr('class', 'lz-data_layer-container').attr('id', this.getBaseId() + '.data_layer_container');\n // Append clip path to the container element\n this.svg.clipRect = this.svg.container.append('clipPath').attr('id', this.getBaseId() + '.clip').append('rect');\n // Append svg group for rendering all data layer elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g').attr('id', this.getBaseId() + '.data_layer').attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n return this;\n };\n /**\n * Move a data layer up relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.moveUp = function () {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n };\n /**\n * Move a data layer down relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.moveDown = function () {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n };\n /**\n * Apply scaling functions to an element or parameter as needed, based on its layout and the element's data\n * If the layout parameter is already a primitive type, simply return the value as given\n * @param {Array|Number|String|Object} layout\n * @param {*} data The value to be used with the filter\n * @returns {*} The transformed value\n */\n LocusZoom.DataLayer.prototype.resolveScalableParameter = function (layout, data) {\n var ret = null;\n if (Array.isArray(layout)) {\n var idx = 0;\n while (ret === null && idx < layout.length) {\n ret = this.resolveScalableParameter(layout[idx], data);\n idx++;\n }\n } else {\n switch (typeof layout) {\n case 'number':\n case 'string':\n ret = layout;\n break;\n case 'object':\n if (layout.scale_function) {\n if (layout.field) {\n var f = new LocusZoom.Data.Field(layout.field);\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, f.resolve(data));\n } else {\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, data);\n }\n }\n break;\n }\n }\n return ret;\n };\n /**\n * Implementation hook for fetching the min and max values of available data. Used to determine axis range, if no other\n * explicit axis settings override. Useful for data layers where the data extent depends on more than one field.\n * (eg confidence intervals in a forest plot)\n * @param data\n * @param axis_config The configuration object for the specified axis.\n * @returns {Array} [min, max] without any padding applied\n * @private\n */\n LocusZoom.DataLayer.prototype._getDataExtent = function (data, axis_config) {\n data = data || this.data;\n // By default this depends only on a single field.\n return d3.extent(data, function (d) {\n var f = new LocusZoom.Data.Field(axis_config.field);\n return +f.resolve(d);\n });\n };\n /**\n * Generate dimension extent function based on layout parameters\n * @param {('x'|'y')} dimension\n */\n LocusZoom.DataLayer.prototype.getAxisExtent = function (dimension) {\n if ([\n 'x',\n 'y'\n ].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier passed to LocusZoom.DataLayer.getAxisExtent()');\n }\n var axis_name = dimension + '_axis';\n var axis_layout = this.layout[axis_name];\n // If a floor AND a ceiling are explicitly defined then just return that extent and be done\n if (!isNaN(axis_layout.floor) && !isNaN(axis_layout.ceiling)) {\n return [\n +axis_layout.floor,\n +axis_layout.ceiling\n ];\n }\n // If a field is defined for the axis and the data layer has data then generate the extent from the data set\n var data_extent = [];\n if (axis_layout.field && this.data) {\n if (!this.data.length) {\n // If data has been fetched (but no points in region), enforce the min_extent (with no buffers,\n // because we don't need padding around an empty screen)\n data_extent = axis_layout.min_extent || [];\n return data_extent;\n } else {\n data_extent = this._getDataExtent(this.data, axis_layout);\n // Apply upper/lower buffers, if applicable\n var original_extent_span = data_extent[1] - data_extent[0];\n if (!isNaN(axis_layout.lower_buffer)) {\n data_extent[0] -= original_extent_span * axis_layout.lower_buffer;\n }\n if (!isNaN(axis_layout.upper_buffer)) {\n data_extent[1] += original_extent_span * axis_layout.upper_buffer;\n }\n if (typeof axis_layout.min_extent == 'object') {\n // The data should span at least the range specified by min_extent, an array with [low, high]\n var range_min = axis_layout.min_extent[0];\n var range_max = axis_layout.min_extent[1];\n if (!isNaN(range_min) && !isNaN(range_max)) {\n data_extent[0] = Math.min(data_extent[0], range_min);\n }\n if (!isNaN(range_max)) {\n data_extent[1] = Math.max(data_extent[1], range_max);\n }\n }\n // If specified, floor and ceiling will override the actual data range\n return [\n isNaN(axis_layout.floor) ? data_extent[0] : axis_layout.floor,\n isNaN(axis_layout.ceiling) ? data_extent[1] : axis_layout.ceiling\n ];\n }\n }\n // If this is for the x axis and no extent could be generated yet but state has a defined start and end\n // then default to using the state-defined region as the extent\n if (dimension === 'x' && !isNaN(this.state.start) && !isNaN(this.state.end)) {\n return [\n this.state.start,\n this.state.end\n ];\n }\n // No conditions met for generating a valid extent, return an empty array\n return [];\n };\n /**\n * Allow this data layer to tell the panel what axis ticks it thinks it will require. The panel may choose whether\n * to use some, all, or none of these when rendering, either alone or in conjunction with other data layers.\n *\n * This method is a stub and should be overridden in data layers that need to specify custom behavior.\n *\n * @param {('x'|'y1'|'y2')} dimension\n * @param {Object} [config] Additional parameters for the panel to specify how it wants ticks to be drawn. The names\n * and meanings of these parameters may vary between different data layers.\n * @returns {Object[]}\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\n LocusZoom.DataLayer.prototype.getTicks = function (dimension, config) {\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier at layer level' + dimension);\n }\n return [];\n };\n /**\n * Generate a tool tip for a given element\n * @param {String|Object} data Data for the element associated with the tooltip\n */\n LocusZoom.DataLayer.prototype.createTooltip = function (data) {\n if (typeof this.layout.tooltip != 'object') {\n throw new Error('DataLayer [' + this.id + '] layout does not define a tooltip');\n }\n var id = this.getElementId(data);\n if (this.tooltips[id]) {\n this.positionTooltip(id);\n return;\n }\n this.tooltips[id] = {\n data: data,\n arrow: null,\n selector: d3.select(this.parent_plot.svg.node().parentNode).append('div').attr('class', 'lz-data_layer-tooltip').attr('id', id + '-tooltip')\n };\n this.state[this.state_id]['has_tooltip'].push(id);\n this.updateTooltip(data);\n return this;\n };\n /**\n * Update a tool tip (generate its inner HTML)\n * @param {String|Object} d The element associated with the tooltip\n * @param {String} [id] An identifier to the tooltip\n */\n LocusZoom.DataLayer.prototype.updateTooltip = function (d, id) {\n if (typeof id == 'undefined') {\n id = this.getElementId(d);\n }\n // Empty the tooltip of all HTML (including its arrow!)\n this.tooltips[id].selector.html('');\n this.tooltips[id].arrow = null;\n // Set the new HTML\n if (this.layout.tooltip.html) {\n this.tooltips[id].selector.html(LocusZoom.parseFields(d, this.layout.tooltip.html));\n }\n // If the layout allows tool tips on this data layer to be closable then add the close button\n // and add padding to the tooltip to accommodate it\n if (this.layout.tooltip.closable) {\n this.tooltips[id].selector.insert('button', ':first-child').attr('class', 'lz-tooltip-close-button').attr('title', 'Close').text('\\xD7').on('click', function () {\n this.destroyTooltip(id);\n }.bind(this));\n }\n // Apply data directly to the tool tip for easier retrieval by custom UI elements inside the tool tip\n this.tooltips[id].selector.data([d]);\n // Reposition and draw a new arrow\n this.positionTooltip(id);\n return this;\n };\n /**\n * Destroy tool tip - remove the tool tip element from the DOM and delete the tool tip's record on the data layer\n * @param {String|Object} element_or_id The element (or id) associated with the tooltip\n * @param {boolean} [temporary=false] Whether this is temporary (not to be tracked in state). Differentiates\n * \"recreate tooltips on re-render\" (which is temporary) from \"user has closed this tooltip\" (permanent)\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.destroyTooltip = function (element_or_id, temporary) {\n var id;\n if (typeof element_or_id == 'string') {\n id = element_or_id;\n } else {\n id = this.getElementId(element_or_id);\n }\n if (this.tooltips[id]) {\n if (typeof this.tooltips[id].selector == 'object') {\n this.tooltips[id].selector.remove();\n }\n delete this.tooltips[id];\n }\n // When a tooltip is removed, also remove the reference from the state\n if (!temporary) {\n var state = this.state[this.state_id]['has_tooltip'];\n var label_mark_position = state.indexOf(id);\n state.splice(label_mark_position, 1);\n }\n return this;\n };\n /**\n * Loop through and destroy all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.destroyAllTooltips = function () {\n for (var id in this.tooltips) {\n this.destroyTooltip(id, true);\n }\n return this;\n };\n //\n /**\n * Position tool tip - naïve function to place a tool tip to the lower right of the current mouse element\n * Most data layers reimplement this method to position tool tips specifically for the data they display\n * @param {String} id The identifier of the tooltip to position\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n // Position the div itself\n this.tooltips[id].selector.style('left', d3.event.pageX + 'px').style('top', d3.event.pageY + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!this.tooltips[id].arrow) {\n this.tooltips[id].arrow = this.tooltips[id].selector.append('div').style('position', 'absolute').attr('class', 'lz-data_layer-tooltip-arrow_top_left');\n }\n this.tooltips[id].arrow.style('left', '-1px').style('top', '-1px');\n return this;\n };\n /**\n * Loop through and position all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.positionAllTooltips = function () {\n for (var id in this.tooltips) {\n this.positionTooltip(id);\n }\n return this;\n };\n /**\n * Show or hide a tool tip by ID depending on directives in the layout and state values relative to the ID\n * @param {String|Object} element The element associated with the tooltip\n * @param {boolean} first_time Because panels can re-render, the rules for showing a tooltip\n * depend on whether this is the first time a status change affecting display has been applied.\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.showOrHideTooltip = function (element, first_time) {\n if (typeof this.layout.tooltip != 'object') {\n return;\n }\n var id = this.getElementId(element);\n /**\n * Apply rules and decide whether to show or hide the tooltip\n * @param {Object} statuses All statuses that apply to an element\n * @param {String[]|object} directive A layout directive object\n * @param operator\n * @returns {null|bool}\n */\n var resolveStatus = function (statuses, directive, operator) {\n var status = null;\n if (typeof statuses != 'object' || statuses === null) {\n return null;\n }\n if (Array.isArray(directive)) {\n // This happens when the function is called on the inner part of the directive\n operator = operator || 'and';\n if (directive.length === 1) {\n status = statuses[directive[0]];\n } else {\n status = directive.reduce(function (previousValue, currentValue) {\n if (operator === 'and') {\n return statuses[previousValue] && statuses[currentValue];\n } else if (operator === 'or') {\n return statuses[previousValue] || statuses[currentValue];\n }\n return null;\n });\n }\n } else if (typeof directive == 'object') {\n var sub_status;\n for (var sub_operator in directive) {\n sub_status = resolveStatus(statuses, directive[sub_operator], sub_operator);\n if (status === null) {\n status = sub_status;\n } else if (operator === 'and') {\n status = status && sub_status;\n } else if (operator === 'or') {\n status = status || sub_status;\n }\n }\n } else {\n return false;\n }\n return status;\n };\n var show_directive = {};\n if (typeof this.layout.tooltip.show == 'string') {\n show_directive = { and: [this.layout.tooltip.show] };\n } else if (typeof this.layout.tooltip.show == 'object') {\n show_directive = this.layout.tooltip.show;\n }\n var hide_directive = {};\n if (typeof this.layout.tooltip.hide == 'string') {\n hide_directive = { and: [this.layout.tooltip.hide] };\n } else if (typeof this.layout.tooltip.hide == 'object') {\n hide_directive = this.layout.tooltip.hide;\n }\n // Find all the statuses that apply to just this single element\n var layer_state = this.state[this.state_id];\n var statuses = {};\n // {status_name: bool}\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function (status) {\n var antistatus = 'un' + status;\n statuses[status] = layer_state[status].indexOf(id) !== -1;\n statuses[antistatus] = !statuses[status];\n });\n // Decide whether to show/hide the tooltip based solely on the underlying element\n var show_resolved = resolveStatus(statuses, show_directive);\n var hide_resolved = resolveStatus(statuses, hide_directive);\n // Most of the tooltip display logic depends on behavior layouts: was point (un)selected, (un)highlighted, etc.\n // But sometimes, a point is selected, and the user then closes the tooltip. If the panel is re-rendered for\n // some outside reason (like state change), we must track this in the create/destroy events as tooltip state.\n var has_tooltip = layer_state['has_tooltip'].indexOf(id) !== -1;\n var tooltip_was_closed = first_time ? false : !has_tooltip;\n if (show_resolved && !tooltip_was_closed && !hide_resolved) {\n this.createTooltip(element);\n } else {\n this.destroyTooltip(element);\n }\n return this;\n };\n /**\n * Find the elements (or indices) that match any of a set of provided filters\n * @protected\n * @param {Array[]} filters A list of filter entries: [field, value] (for equivalence testing) or\n * [field, operator, value] for other operators\n * @param {('indexes'|'elements')} [return_type='indexes'] Specify whether to return either the indices of the matching\n * elements, or references to the elements themselves\n * @returns {Array}\n */\n LocusZoom.DataLayer.prototype.filter = function (filters, return_type) {\n if (typeof return_type == 'undefined' || [\n 'indexes',\n 'elements'\n ].indexOf(return_type) === -1) {\n return_type = 'indexes';\n }\n if (!Array.isArray(filters)) {\n return [];\n }\n var test = function (element, filter) {\n var operators = {\n '=': function (a, b) {\n return a === b;\n },\n // eslint-disable-next-line eqeqeq\n '!=': function (a, b) {\n return a != b;\n },\n // For absence of a value, deliberately allow weak comparisons (eg undefined/null)\n '<': function (a, b) {\n return a < b;\n },\n '<=': function (a, b) {\n return a <= b;\n },\n '>': function (a, b) {\n return a > b;\n },\n '>=': function (a, b) {\n return a >= b;\n },\n '%': function (a, b) {\n return a % b;\n }\n };\n if (!Array.isArray(filter)) {\n return false;\n }\n if (filter.length === 2) {\n return element[filter[0]] === filter[1];\n } else if (filter.length === 3 && operators[filter[1]]) {\n return operators[filter[1]](element[filter[0]], filter[2]);\n } else {\n return false;\n }\n };\n var matches = [];\n this.data.forEach(function (element, idx) {\n var match = true;\n filters.forEach(function (filter) {\n if (!test(element, filter)) {\n match = false;\n }\n });\n if (match) {\n matches.push(return_type === 'indexes' ? idx : element);\n }\n });\n return matches;\n };\n /**\n * @param filters\n * @returns {Array}\n */\n LocusZoom.DataLayer.prototype.filterIndexes = function (filters) {\n return this.filter(filters, 'indexes');\n };\n /**\n * @param filters\n * @returns {Array}\n */\n LocusZoom.DataLayer.prototype.filterElements = function (filters) {\n return this.filter(filters, 'elements');\n };\n LocusZoom.DataLayer.Statuses.verbs.forEach(function (verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset a single element's status\n // TODO: Improve documentation for dynamically generated methods/properties\n LocusZoom.DataLayer.prototype[verb + 'Element'] = function (element, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n this.setElementStatus(adjective, element, true, exclusive);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'Element'] = function (element, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n this.setElementStatus(adjective, element, false, exclusive);\n return this;\n };\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.DataLayer.prototype[verb + 'ElementsByFilters'] = function (filters, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.DataLayer.prototype[antiverb + 'ElementsByFilters'] = function (filters, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.DataLayer.prototype[verb + 'AllElements'] = function () {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'AllElements'] = function () {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n });\n /**\n * Toggle a status (e.g. highlighted, selected, identified) on an element\n * @param {String} status The name of a recognized status to be added/removed on an appropriate element\n * @param {String|Object} element The data bound to the element of interest\n * @param {Boolean} active True to add the status (and associated CSS styles); false to remove it\n * @param {Boolean} exclusive Whether to only allow a state for a single element at a time\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.setElementStatus = function (status, element, active, exclusive) {\n if (status === 'has_tooltip') {\n // This is a special adjective that exists solely to track tooltip state. It has no CSS and never gets set\n // directly. It is invisible to the official enums.\n return this;\n }\n // Sanity checks\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatus()');\n }\n if (typeof element == 'undefined') {\n throw new Error('Invalid element passed to DataLayer.setElementStatus()');\n }\n if (typeof active == 'undefined') {\n active = true;\n }\n // Get an ID for the element or return having changed nothing\n try {\n var element_id = this.getElementId(element);\n } catch (get_element_id_error) {\n return this;\n }\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !active);\n }\n // Set/unset the proper status class on the appropriate DOM element(s)\n d3.select('#' + element_id).classed('lz-data_layer-' + this.layout.type + '-' + status, active);\n var element_status_node_id = this.getElementStatusNodeId(element);\n if (element_status_node_id !== null) {\n d3.select('#' + element_status_node_id).classed('lz-data_layer-' + this.layout.type + '-statusnode-' + status, active);\n }\n // Track element ID in the proper status state array\n var element_status_idx = this.state[this.state_id][status].indexOf(element_id);\n var added_status = element_status_idx === -1;\n // On a re-render, existing statuses will be reapplied.\n if (active && added_status) {\n this.state[this.state_id][status].push(element_id);\n }\n if (!active && !added_status) {\n this.state[this.state_id][status].splice(element_status_idx, 1);\n }\n // Trigger tool tip show/hide logic\n this.showOrHideTooltip(element, added_status);\n // Trigger layout changed event hook\n if (added_status) {\n this.parent.emit('layout_changed', true);\n }\n var is_selected = status === 'selected';\n if (is_selected && (added_status || !active)) {\n // Notify parents that an element has changed selection status (either active, or inactive)\n this.parent.emit('element_selection', {\n element: element,\n active: active\n }, true);\n }\n var value_to_broadcast = this.layout.match && this.layout.match.send;\n if (is_selected && value_to_broadcast && (added_status || !active)) {\n this.parent.emit('match_requested', {\n value: element[value_to_broadcast],\n active: active\n }, true);\n }\n return this;\n };\n /**\n * Toggle a status on elements in the data layer based on a set of filters\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.setElementStatusByFilters = function (status, toggle, filters, exclusive) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatusByFilters()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') {\n return this;\n }\n if (typeof toggle == 'undefined') {\n toggle = true;\n } else {\n toggle = !!toggle;\n }\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n if (!Array.isArray(filters)) {\n filters = [];\n }\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !toggle);\n }\n // Apply statuses\n this.filterElements(filters).forEach(function (element) {\n this.setElementStatus(status, element, toggle);\n }.bind(this));\n return this;\n };\n /**\n * Toggle a status on all elements in the data layer\n * @param {String} status\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.setAllElementStatus = function (status, toggle) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') {\n return this;\n }\n if (typeof toggle == 'undefined') {\n toggle = true;\n }\n // Apply statuses\n if (toggle) {\n this.data.forEach(function (element) {\n this.setElementStatus(status, element, true);\n }.bind(this));\n } else {\n var status_ids = this.state[this.state_id][status].slice();\n status_ids.forEach(function (id) {\n var element = this.getElementById(id);\n if (typeof element == 'object' && element !== null) {\n this.setElementStatus(status, element, false);\n }\n }.bind(this));\n this.state[this.state_id][status] = [];\n }\n // Update global status flag\n this.global_statuses[status] = toggle;\n return this;\n };\n /**\n * Apply all layout-defined behaviors (DOM event handlers) to a selection of elements\n * @param {d3.selection} selection\n */\n LocusZoom.DataLayer.prototype.applyBehaviors = function (selection) {\n if (typeof this.layout.behaviors != 'object') {\n return;\n }\n Object.keys(this.layout.behaviors).forEach(function (directive) {\n var event_match = /(click|mouseover|mouseout)/.exec(directive);\n if (!event_match) {\n return;\n }\n selection.on(event_match[0] + '.' + directive, this.executeBehaviors(directive, this.layout.behaviors[directive]));\n }.bind(this));\n };\n /**\n * Generate a function that executes an arbitrary list of behaviors on an element during an event\n * @param {String} directive The name of the event, as described in layout.behaviors for this datalayer\n * @param {Object} behaviors An object describing the behavior to attach to this single element\n * @param {string} behaviors.action The name of the action that would trigger this behavior (eg click, mouseover, etc)\n * @param {string} behaviors.status What status to apply to the element when this behavior is triggered (highlighted,\n * selected, etc)\n * @param {string} [behaviors.exclusive] Whether triggering the event for this element should unset the relevant status\n * for all other elements. Useful for, eg, click events that exclusively highlight one thing.\n * @returns {function(this:LocusZoom.DataLayer)} Return a function that handles the event in context with the behavior\n * and the element- can be attached as an event listener\n */\n LocusZoom.DataLayer.prototype.executeBehaviors = function (directive, behaviors) {\n // Determine the required state of control and shift keys during the event\n var requiredKeyStates = {\n 'ctrl': directive.indexOf('ctrl') !== -1,\n 'shift': directive.indexOf('shift') !== -1\n };\n return function (element) {\n // Do nothing if the required control and shift key presses (or lack thereof) doesn't match the event\n if (requiredKeyStates.ctrl !== !!d3.event.ctrlKey || requiredKeyStates.shift !== !!d3.event.shiftKey) {\n return;\n }\n // Loop through behaviors making each one go in succession\n behaviors.forEach(function (behavior) {\n // Route first by the action, if defined\n if (typeof behavior != 'object' || behavior === null) {\n return;\n }\n switch (behavior.action) {\n // Set a status (set to true regardless of current status, optionally with exclusivity)\n case 'set':\n this.setElementStatus(behavior.status, element, true, behavior.exclusive);\n break;\n // Unset a status (set to false regardless of current status, optionally with exclusivity)\n case 'unset':\n this.setElementStatus(behavior.status, element, false, behavior.exclusive);\n break;\n // Toggle a status\n case 'toggle':\n var current_status_boolean = this.state[this.state_id][behavior.status].indexOf(this.getElementId(element)) !== -1;\n var exclusive = behavior.exclusive && !current_status_boolean;\n this.setElementStatus(behavior.status, element, !current_status_boolean, exclusive);\n break;\n // Link to a dynamic URL\n case 'link':\n if (typeof behavior.href == 'string') {\n var url = LocusZoom.parseFields(element, behavior.href);\n if (typeof behavior.target == 'string') {\n window.open(url, behavior.target);\n } else {\n window.location.href = url;\n }\n }\n break;\n // Action not defined, just return\n default:\n break;\n }\n return;\n }.bind(this));\n }.bind(this);\n };\n /**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\n LocusZoom.DataLayer.prototype.getPageOrigin = function () {\n var panel_origin = this.parent.getPageOrigin();\n return {\n x: panel_origin.x + this.parent.layout.margin.left,\n y: panel_origin.y + this.parent.layout.margin.top\n };\n };\n /**\n * Get a data layer's current underlying data in a standard format (e.g. JSON or CSV)\n * @param {('csv'|'tsv'|'json')} format How to export the data\n * @returns {*}\n */\n LocusZoom.DataLayer.prototype.exportData = function (format) {\n var default_format = 'json';\n format = format || default_format;\n format = typeof format == 'string' ? format.toLowerCase() : default_format;\n if ([\n 'json',\n 'csv',\n 'tsv'\n ].indexOf(format) === -1) {\n format = default_format;\n }\n var ret;\n switch (format) {\n case 'json':\n try {\n ret = JSON.stringify(this.data);\n } catch (e) {\n ret = null;\n console.warn('Unable to export JSON data from data layer: ' + this.getBaseId());\n console.error(e);\n }\n break;\n case 'tsv':\n case 'csv':\n try {\n var jsonified = JSON.parse(JSON.stringify(this.data));\n if (typeof jsonified != 'object') {\n ret = jsonified.toString();\n } else if (!Array.isArray(jsonified)) {\n ret = 'Object';\n } else {\n var delimiter = format === 'tsv' ? '\\t' : ',';\n var header = this.layout.fields.map(function (header) {\n return JSON.stringify(header);\n }).join(delimiter) + '\\n';\n ret = header + jsonified.map(function (record) {\n return this.layout.fields.map(function (field) {\n if (typeof record[field] == 'undefined') {\n return JSON.stringify(null);\n } else if (typeof record[field] == 'object' && record[field] !== null) {\n return Array.isArray(record[field]) ? '\"[Array(' + record[field].length + ')]\"' : '\"[Object]\"';\n } else {\n return JSON.stringify(record[field]);\n }\n }).join(delimiter);\n }.bind(this)).join('\\n');\n }\n } catch (e) {\n ret = null;\n console.error('Unable to export CSV data from data layer: ' + this.getBaseId() + ';', e);\n }\n break;\n }\n return ret;\n };\n /**\n * Position the datalayer and all tooltips\n * @returns {LocusZoom.DataLayer}\n */\n LocusZoom.DataLayer.prototype.draw = function () {\n this.svg.container.attr('transform', 'translate(' + this.parent.layout.cliparea.origin.x + ',' + this.parent.layout.cliparea.origin.y + ')');\n this.svg.clipRect.attr('width', this.parent.layout.cliparea.width).attr('height', this.parent.layout.cliparea.height);\n this.positionAllTooltips();\n return this;\n };\n /**\n * Re-Map a data layer to reflect changes in the state of a plot (such as viewing region/ chromosome range)\n * @return {Promise}\n */\n LocusZoom.DataLayer.prototype.reMap = function () {\n this.destroyAllTooltips();\n // hack - only non-visible tooltips should be destroyed\n // and then recreated if returning to visibility\n // Fetch new data. Datalayers are only given access to the final consolidated data from the chain (not headers or raw payloads)\n var promise = this.parent_plot.lzd.getData(this.state, this.layout.fields);\n promise.then(function (new_data) {\n this.data = new_data.body;\n this.applyDataMethods();\n this.initialized = true;\n }.bind(this));\n return promise;\n };\n /**\n * The central registry of known data layer definitions (which may be stored in separate files due to length)\n * @namespace\n */\n LocusZoom.DataLayers = function () {\n var obj = {};\n var datalayers = {};\n /**\n * @name LocusZoom.DataLayers.get\n * @param {String} name The name of the datalayer\n * @param {Object} layout The configuration object for this data layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n * @returns {LocusZoom.DataLayer}\n */\n obj.get = function (name, layout, parent) {\n if (!name) {\n return null;\n } else if (datalayers[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for data layer [' + name + ']');\n } else {\n return new datalayers[name](layout, parent);\n }\n } else {\n throw new Error('data layer [' + name + '] not found');\n }\n };\n /**\n * @name LocusZoom.DataLayers.set\n * @protected\n * @param {String} name\n * @param {Function} datalayer Constructor for the datalayer\n */\n obj.set = function (name, datalayer) {\n if (datalayer) {\n if (typeof datalayer != 'function') {\n throw new Error('unable to set data layer [' + name + '], argument provided is not a function');\n } else {\n datalayers[name] = datalayer;\n datalayers[name].prototype = new LocusZoom.DataLayer();\n }\n } else {\n delete datalayers[name];\n }\n };\n /**\n * Add a new type of datalayer to the registry of known layer types\n * @name LocusZoom.DataLayers.add\n * @param {String} name The name of the data layer to register\n * @param {Function} datalayer\n */\n obj.add = function (name, datalayer) {\n if (datalayers[name]) {\n throw new Error('data layer already exists with name: ' + name);\n } else {\n obj.set(name, datalayer);\n }\n };\n /**\n * Register a new datalayer that inherits and extends basic behaviors from a known datalayer\n * @param {String} parent_name The name of the parent data layer whose behavior is to be extended\n * @param {String} name The name of the new datalayer to register\n * @param {Object} [overrides] Object of properties and methods to combine with the prototype of the parent datalayer\n * @returns {Function} The constructor for the new child class\n */\n obj.extend = function (parent_name, name, overrides) {\n // TODO: Consider exposing additional constructor argument, if there is a use case for very granular extension\n overrides = overrides || {};\n var parent = datalayers[parent_name];\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered datalayer type');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n // Bypass .set() because we want a layer of inheritance below `DataLayer`\n datalayers[name] = child;\n return child;\n };\n /**\n * List the names of all known datalayers\n * @name LocusZoom.DataLayers.list\n * @returns {String[]}\n */\n obj.list = function () {\n return Object.keys(datalayers);\n };\n return obj;\n }();\n 'use strict';\n /**\n * Create a single continuous 2D track that provides information about each datapoint\n *\n * For example, this can be used to color by membership in a group, alongside information in other panels\n *\n * @class LocusZoom.DataLayers.annotation_track\n * @augments LocusZoom.DataLayer\n * @param {Object} layout\n * @param {Object|String} [layout.color]\n * @param {Array[]} An array of filter entries specifying which points to draw annotations for.\n * See `LocusZoom.DataLayer.filter` for details\n */\n LocusZoom.DataLayers.add('annotation_track', function (layout) {\n // In the future we may add additional options for controlling marker size/ shape, based on user feedback\n this.DefaultLayout = {\n color: '#000000',\n filters: [],\n tooltip_positioning: 'middle',\n // Allowed values: top, middle, bottom\n hit_area_width: 8\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n if (!Array.isArray(layout.filters)) {\n throw new Error('Annotation track must specify array of filters for selecting points to annotate');\n }\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n this.render = function () {\n var self = this;\n // Only render points that currently satisfy all provided filter conditions.\n var trackData = this.filter(this.layout.filters, 'elements');\n // Put the containing visible lines before the one containing hit areas, so that the hit areas will be on top.\n var visible_lines_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-visible_lines');\n if (visible_lines_group.size() === 0) {\n visible_lines_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-visible_lines');\n }\n var selection = visible_lines_group.selectAll('rect.lz-data_layer-' + self.layout.type).data(trackData, function (d) {\n return d[self.layout.id_field];\n });\n // Draw rectangles (visual and tooltip positioning)\n selection.enter().append('rect').attr('class', 'lz-data_layer-' + this.layout.type).attr('id', function (d) {\n return self.getElementId(d);\n });\n var width = 1;\n selection.attr('x', function (d) {\n return self.parent['x_scale'](d[self.layout.x_axis.field]) - width / 2;\n }).attr('width', width).attr('height', self.parent.layout.height).attr('fill', function (d) {\n return self.resolveScalableParameter(self.layout.color, d);\n });\n // Remove unused elements\n selection.exit().remove();\n var hit_areas_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-hit_areas');\n if (hit_areas_group.size() === 0) {\n hit_areas_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-hit_areas');\n }\n var hit_areas_selection = hit_areas_group.selectAll('rect.lz-data_layer-' + self.layout.type).data(trackData, function (d) {\n return d[self.layout.id_field];\n });\n // Add new elements as needed\n hit_areas_selection.enter().append('rect').attr('class', 'lz-data_layer-' + this.layout.type).attr('id', function (d) {\n return self.getElementId(d);\n });\n // Update the set of elements to reflect new data\n var _getX = function (d, i) {\n // Helper for position calcs below\n var x_center = self.parent['x_scale'](d[self.layout.x_axis.field]);\n var x_left = x_center - self.layout.hit_area_width / 2;\n if (i >= 1) {\n // This assumes that the data are in sorted order.\n var left_node = trackData[i - 1];\n var left_node_x_center = self.parent['x_scale'](left_node[self.layout.x_axis.field]);\n x_left = Math.max(x_left, (x_center + left_node_x_center) / 2);\n }\n return [\n x_left,\n x_center\n ];\n };\n hit_areas_selection.attr('height', self.parent.layout.height).attr('opacity', 0).attr('x', function (d, i) {\n var crds = _getX(d, i);\n return crds[0];\n }).attr('width', function (d, i) {\n var crds = _getX(d, i);\n return crds[1] - crds[0] + self.layout.hit_area_width / 2;\n });\n // Remove unused elements\n hit_areas_selection.exit().remove();\n // Set up tooltips and mouse interaction\n this.applyBehaviors(hit_areas_selection);\n };\n // Reimplement the positionTooltip() method to be annotation-specific\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var offset = stroke_width / 2;\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_center = data_layer_height / 2;\n // Tooltip should be horizontally centered above the point to be annotated. (or below if space is limited)\n var offset_right = Math.max(tooltip_box.width / 2 - x_center, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - tooltip_box.width / 2 - offset_left + offset_right;\n arrow_left = tooltip_box.width / 2 - arrow_width + offset_left - offset_right - offset;\n var top_offset = 0;\n switch (this.layout.tooltip_positioning) {\n case 'top':\n arrow_type = 'down';\n break;\n case 'bottom':\n top_offset = data_layer_height;\n arrow_type = 'up';\n break;\n case 'middle':\n default:\n var position = d3.mouse(this.svg.container.node());\n // Position the tooltip so that it does not overlap the mouse pointer\n top_offset = y_center;\n if (position[1] > data_layer_height / 2) {\n arrow_type = 'down';\n } else {\n arrow_type = 'up';\n }\n }\n if (arrow_type === 'up') {\n top = page_origin.y + top_offset + stroke_width + arrow_width;\n arrow_top = 0 - stroke_width - arrow_width;\n } else if (arrow_type === 'down') {\n top = page_origin.y + top_offset - (tooltip_box.height + stroke_width + arrow_width);\n arrow_top = tooltip_box.height - stroke_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n return this;\n });\n 'use strict';\n /**\n * Forest Data Layer\n * Implements a standard forest plot. In order to space out points, any layout using this must specify axis ticks\n * and extent in advance.\n *\n * If you are using dynamically fetched data, consider using `category_forest` instead.\n *\n * @class LocusZoom.DataLayers.forest\n */\n LocusZoom.DataLayers.add('forest', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'square',\n color: '#888888',\n fill_opacity: 1,\n y_axis: { axis: 2 },\n id_field: 'id',\n confidence_intervals: {\n start_field: 'ci_start',\n end_field: 'ci_end'\n },\n show_no_significance_line: true\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n // Reimplement the positionTooltip() method to be forest-specific\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var border_radius = 6;\n // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n var offset = Math.sqrt(point_size / Math.PI);\n var left, arrow_type, arrow_left;\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var top, arrow_top;\n if (y_center - tooltip_box.height / 2 <= 0) {\n // Too close to the top, push it down\n top = page_origin.y + y_center - 1.5 * arrow_width - border_radius;\n arrow_top = border_radius;\n } else if (y_center + tooltip_box.height / 2 >= data_layer_height) {\n // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - 2 * arrow_width - border_radius;\n } else {\n // vertically centered\n top = page_origin.y + y_center - tooltip_box.height / 2;\n arrow_top = tooltip_box.height / 2 - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n // Implement the main render function\n this.render = function () {\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n // Generate confidence interval paths if fields are defined\n if (this.layout.confidence_intervals && this.layout.fields.indexOf(this.layout.confidence_intervals.start_field) !== -1 && this.layout.fields.indexOf(this.layout.confidence_intervals.end_field) !== -1) {\n // Generate a selection for all forest plot confidence intervals\n var ci_selection = this.svg.group.selectAll('rect.lz-data_layer-forest.lz-data_layer-forest-ci').data(this.data, function (d) {\n return d[this.layout.id_field];\n }.bind(this));\n // Create confidence interval rect elements\n ci_selection.enter().append('rect').attr('class', 'lz-data_layer-forest lz-data_layer-forest-ci').attr('id', function (d) {\n return this.getElementId(d) + '_ci';\n }.bind(this)).attr('transform', 'translate(0,' + (isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height) + ')');\n // Apply position and size parameters using transition if necessary\n var ci_transform = function (d) {\n var x = this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) {\n x = -1000;\n }\n if (isNaN(y)) {\n y = -1000;\n }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var ci_width = function (d) {\n return this.parent[x_scale](d[this.layout.confidence_intervals.end_field]) - this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n }.bind(this);\n var ci_height = 1;\n if (this.canTransition()) {\n ci_selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('transform', ci_transform).attr('width', ci_width).attr('height', ci_height);\n } else {\n ci_selection.attr('transform', ci_transform).attr('width', ci_width).attr('height', ci_height);\n }\n // Remove old elements as needed\n ci_selection.exit().remove();\n }\n // Generate a selection for all forest plot points\n var points_selection = this.svg.group.selectAll('path.lz-data_layer-forest.lz-data_layer-forest-point').data(this.data, function (d) {\n return d[this.layout.id_field];\n }.bind(this));\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n points_selection.enter().append('path').attr('class', 'lz-data_layer-forest lz-data_layer-forest-point').attr('id', function (d) {\n return this.getElementId(d);\n }.bind(this)).attr('transform', 'translate(0,' + initial_y + ')');\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function (d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) {\n x = -1000;\n }\n if (isNaN(y)) {\n y = -1000;\n }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var fill = function (d) {\n return this.resolveScalableParameter(this.layout.color, d);\n }.bind(this);\n var fill_opacity = function (d) {\n return this.resolveScalableParameter(this.layout.fill_opacity, d);\n }.bind(this);\n var shape = d3.svg.symbol().size(function (d) {\n return this.resolveScalableParameter(this.layout.point_size, d);\n }.bind(this)).type(function (d) {\n return this.resolveScalableParameter(this.layout.point_shape, d);\n }.bind(this));\n // Apply position and color, using a transition if necessary\n if (this.canTransition()) {\n points_selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('transform', transform).attr('fill', fill).attr('fill-opacity', fill_opacity).attr('d', shape);\n } else {\n points_selection.attr('transform', transform).attr('fill', fill).attr('fill-opacity', fill_opacity).attr('d', shape);\n }\n // Remove old elements as needed\n points_selection.exit().remove();\n // Apply default event emitters to selection\n points_selection.on('click.event_emitter', function (element_data) {\n this.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n // Apply behaviors to points\n this.applyBehaviors(points_selection);\n };\n return this;\n });\n /**\n * A y-aligned forest plot in which the y-axis represents item labels, which are dynamically chosen when data is loaded.\n * Each item is assumed to include both data and confidence intervals.\n * This allows generating forest plots without defining the layout in advance.\n *\n * @class LocusZoom.DataLayers.category_forest\n * @augments LocusZoom.DataLayers.forest\n */\n LocusZoom.DataLayers.extend('forest', 'category_forest', {\n _getDataExtent: function (data, axis_config) {\n // In a forest plot, the data range is determined by *three* fields (beta + CI start/end)\n var ci_config = this.layout.confidence_intervals;\n if (ci_config && this.layout.fields.indexOf(ci_config.start_field) !== -1 && this.layout.fields.indexOf(ci_config.end_field) !== -1) {\n var min = function (d) {\n var f = new LocusZoom.Data.Field(ci_config.start_field);\n return +f.resolve(d);\n };\n var max = function (d) {\n var f = new LocusZoom.Data.Field(ci_config.end_field);\n return +f.resolve(d);\n };\n return [\n d3.min(data, min),\n d3.max(data, max)\n ];\n }\n // If there are no confidence intervals set, then range must depend only on a single field\n return LocusZoom.DataLayer.prototype._getDataExtent.call(this, data, axis_config);\n },\n getTicks: function (dimension, config) {\n // Overrides parent method\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier' + dimension);\n }\n // Design assumption: one axis (y1 or y2) has the ticks, and the layout says which to use\n // Also assumes that every tick gets assigned a unique matching label\n var axis_num = this.layout.y_axis.axis;\n if (dimension === 'y' + axis_num) {\n var category_field = this.layout.y_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n return this.data.map(function (item, index) {\n return {\n y: index + 1,\n text: item[category_field]\n };\n });\n } else {\n return [];\n }\n },\n applyCustomDataMethods: function () {\n // Add a synthetic yaxis field to ensure data is spread out on plot. Then, set axis floor and ceiling to\n // correct extents.\n var field_to_add = this.layout.y_axis.field;\n if (!field_to_add) {\n throw new Error('Layout for ' + this.layout.id + ' must specify yaxis.field');\n }\n this.data = this.data.map(function (item, index) {\n item[field_to_add] = index + 1;\n return item;\n });\n // Update axis extents based on one label for every point (with a bit of padding above and below)\n this.layout.y_axis.floor = 0;\n this.layout.y_axis.ceiling = this.data.length + 1;\n return this;\n }\n });\n 'use strict';\n /*********************\n * Genes Data Layer\n * Implements a data layer that will render gene tracks\n * @class\n * @augments LocusZoom.DataLayer\n*/\n LocusZoom.DataLayers.add('genes', function (layout) {\n /**\n * Define a default layout for this DataLayer type and merge it with the passed argument\n * @protected\n * @member {Object}\n * */\n this.DefaultLayout = {\n // Optionally specify different fill and stroke properties\n stroke: 'rgb(54, 54, 150)',\n color: '#363696',\n label_font_size: 12,\n label_exon_spacing: 4,\n exon_height: 16,\n bounding_box_padding: 6,\n track_vertical_spacing: 10\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n /**\n * Generate a statusnode ID for a given element\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function (element) {\n return this.getElementId(element) + '-statusnode';\n };\n /**\n * Helper function to sum layout values to derive total height for a single gene track\n * @returns {number}\n */\n this.getTrackHeight = function () {\n return 2 * this.layout.bounding_box_padding + this.layout.label_font_size + this.layout.label_exon_spacing + this.layout.exon_height + this.layout.track_vertical_spacing;\n };\n /**\n * A gene may have arbitrarily many transcripts, but this data layer isn't set up to render them yet.\n * Stash a transcript_idx to point to the first transcript and use that for all transcript refs.\n * @member {number}\n * @type {number}\n */\n this.transcript_idx = 0;\n /**\n * An internal counter for the number of tracks in the data layer. Used as an internal counter for looping\n * over positions / assignments\n * @protected\n * @member {number}\n */\n this.tracks = 1;\n /**\n * Store information about genes in dataset, in a hash indexed by track number: {track_number: [gene_indices]}\n * @member {Object.}\n */\n this.gene_track_index = { 1: [] };\n /**\n * Ensure that genes in overlapping chromosome regions are positioned so that parts of different genes do not\n * overlap in the view. A track is a row used to vertically separate overlapping genes.\n * @returns {LocusZoom.DataLayer}\n */\n this.assignTracks = function () {\n /**\n * Function to get the width in pixels of a label given the text and layout attributes\n * TODO: Move to outer scope?\n * @param {String} gene_name\n * @param {number|string} font_size\n * @returns {number}\n */\n this.getLabelWidth = function (gene_name, font_size) {\n try {\n var temp_text = this.svg.group.append('text').attr('x', 0).attr('y', 0).attr('class', 'lz-data_layer-genes lz-label').style('font-size', font_size).text(gene_name + '\\u2192');\n var label_width = temp_text.node().getBBox().width;\n temp_text.remove();\n return label_width;\n } catch (e) {\n return 0;\n }\n };\n // Reinitialize some metadata\n this.tracks = 1;\n this.gene_track_index = { 1: [] };\n this.data.map(function (d, g) {\n // If necessary, split combined gene id / version fields into discrete fields.\n // NOTE: this may be an issue with CSG's genes data source that may eventually be solved upstream.\n if (this.data[g].gene_id && this.data[g].gene_id.indexOf('.')) {\n var split = this.data[g].gene_id.split('.');\n this.data[g].gene_id = split[0];\n this.data[g].gene_version = split[1];\n }\n // Stash the transcript ID on the parent gene\n this.data[g].transcript_id = this.data[g].transcripts[this.transcript_idx].transcript_id;\n // Determine display range start and end, based on minimum allowable gene display width, bounded by what we can see\n // (range: values in terms of pixels on the screen)\n this.data[g].display_range = {\n start: this.parent.x_scale(Math.max(d.start, this.state.start)),\n end: this.parent.x_scale(Math.min(d.end, this.state.end))\n };\n this.data[g].display_range.label_width = this.getLabelWidth(this.data[g].gene_name, this.layout.label_font_size);\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n // Determine label text anchor (default to middle)\n this.data[g].display_range.text_anchor = 'middle';\n if (this.data[g].display_range.width < this.data[g].display_range.label_width) {\n if (d.start < this.state.start) {\n this.data[g].display_range.end = this.data[g].display_range.start + this.data[g].display_range.label_width + this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'start';\n } else if (d.end > this.state.end) {\n this.data[g].display_range.start = this.data[g].display_range.end - this.data[g].display_range.label_width - this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n var centered_margin = (this.data[g].display_range.label_width - this.data[g].display_range.width) / 2 + this.layout.label_font_size;\n if (this.data[g].display_range.start - centered_margin < this.parent.x_scale(this.state.start)) {\n this.data[g].display_range.start = this.parent.x_scale(this.state.start);\n this.data[g].display_range.end = this.data[g].display_range.start + this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'start';\n } else if (this.data[g].display_range.end + centered_margin > this.parent.x_scale(this.state.end)) {\n this.data[g].display_range.end = this.parent.x_scale(this.state.end);\n this.data[g].display_range.start = this.data[g].display_range.end - this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n this.data[g].display_range.start -= centered_margin;\n this.data[g].display_range.end += centered_margin;\n }\n }\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n }\n // Add bounding box padding to the calculated display range start, end, and width\n this.data[g].display_range.start -= this.layout.bounding_box_padding;\n this.data[g].display_range.end += this.layout.bounding_box_padding;\n this.data[g].display_range.width += 2 * this.layout.bounding_box_padding;\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[g].display_domain = {\n start: this.parent.x_scale.invert(this.data[g].display_range.start),\n end: this.parent.x_scale.invert(this.data[g].display_range.end)\n };\n this.data[g].display_domain.width = this.data[g].display_domain.end - this.data[g].display_domain.start;\n // Using display range/domain data generated above cast each gene to tracks such that none overlap\n this.data[g].track = null;\n var potential_track = 1;\n while (this.data[g].track === null) {\n var collision_on_potential_track = false;\n this.gene_track_index[potential_track].map(function (placed_gene) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_gene.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_gene.display_range.end, this.display_range.end);\n if (max_end - min_start < placed_gene.display_range.width + this.display_range.width) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[g]));\n if (!collision_on_potential_track) {\n this.data[g].track = potential_track;\n this.gene_track_index[potential_track].push(this.data[g]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.gene_track_index[potential_track] = [];\n }\n }\n }\n // Stash parent references on all genes, trascripts, and exons\n this.data[g].parent = this;\n this.data[g].transcripts.map(function (d, t) {\n this.data[g].transcripts[t].parent = this.data[g];\n this.data[g].transcripts[t].exons.map(function (d, e) {\n this.data[g].transcripts[t].exons[e].parent = this.data[g].transcripts[t];\n }.bind(this));\n }.bind(this));\n }.bind(this));\n return this;\n };\n /**\n * Main render function\n */\n this.render = function () {\n var self = this;\n this.assignTracks();\n var width, height, x, y;\n // Render gene groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-genes').data(this.data, function (d) {\n return d.gene_name;\n });\n selection.enter().append('g').attr('class', 'lz-data_layer-genes');\n selection.attr('id', function (d) {\n return this.getElementId(d);\n }.bind(this)).each(function (gene) {\n var data_layer = gene.parent;\n // Render gene bounding boxes (status nodes to show selected/highlighted)\n var bboxes = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-data_layer-genes-statusnode').data([gene], function (d) {\n return data_layer.getElementStatusNodeId(d);\n });\n bboxes.enter().append('rect').attr('class', 'lz-data_layer-genes lz-data_layer-genes-statusnode');\n bboxes.attr('id', function (d) {\n return data_layer.getElementStatusNodeId(d);\n }).attr('rx', function () {\n return data_layer.layout.bounding_box_padding;\n }).attr('ry', function () {\n return data_layer.layout.bounding_box_padding;\n });\n width = function (d) {\n return d.display_range.width;\n };\n height = function () {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function (d) {\n return d.display_range.start;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight();\n };\n if (data_layer.canTransition()) {\n bboxes.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n bboxes.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n bboxes.exit().remove();\n // Render gene boundaries\n var boundary_fill = function (d) {\n return self.resolveScalableParameter(self.layout.color, d);\n };\n var boundary_stroke = function (d) {\n return self.resolveScalableParameter(self.layout.stroke, d);\n };\n var boundaries = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-boundary').data([gene], function (d) {\n return d.gene_name + '_boundary';\n }).style({\n fill: boundary_fill,\n stroke: boundary_stroke\n });\n boundaries.enter().append('rect').attr('class', 'lz-data_layer-genes lz-boundary');\n width = function (d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function () {\n return 1; // TODO: scale dynamically?\n };\n x = function (d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight() + data_layer.layout.bounding_box_padding + data_layer.layout.label_font_size + data_layer.layout.label_exon_spacing + Math.max(data_layer.layout.exon_height, 3) / 2;\n };\n if (data_layer.canTransition()) {\n boundaries.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n boundaries.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n boundaries.exit().remove();\n // Render gene labels\n var labels = d3.select(this).selectAll('text.lz-data_layer-genes.lz-label').data([gene], function (d) {\n return d.gene_name + '_label';\n });\n labels.enter().append('text').attr('class', 'lz-data_layer-genes lz-label');\n labels.attr('text-anchor', function (d) {\n return d.display_range.text_anchor;\n }).text(function (d) {\n return d.strand === '+' ? d.gene_name + '\\u2192' : '\\u2190' + d.gene_name;\n }).style('font-size', gene.parent.layout.label_font_size);\n x = function (d) {\n if (d.display_range.text_anchor === 'middle') {\n return d.display_range.start + d.display_range.width / 2;\n } else if (d.display_range.text_anchor === 'start') {\n return d.display_range.start + data_layer.layout.bounding_box_padding;\n } else if (d.display_range.text_anchor === 'end') {\n return d.display_range.end - data_layer.layout.bounding_box_padding;\n }\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight() + data_layer.layout.bounding_box_padding + data_layer.layout.label_font_size;\n };\n if (data_layer.canTransition()) {\n labels.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('x', x).attr('y', y);\n } else {\n labels.attr('x', x).attr('y', y);\n }\n labels.exit().remove();\n // Render exon rects (first transcript only, for now)\n // Exons: by default color on gene properties for consistency with the gene boundary track- hence color uses d.parent.parent\n var exon_fill = function (d) {\n return self.resolveScalableParameter(self.layout.color, d.parent.parent);\n };\n var exon_stroke = function (d) {\n return self.resolveScalableParameter(self.layout.stroke, d.parent.parent);\n };\n var exons = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-exon').data(gene.transcripts[gene.parent.transcript_idx].exons, function (d) {\n return d.exon_id;\n });\n exons.enter().append('rect').attr('class', 'lz-data_layer-genes lz-exon');\n exons.style({\n fill: exon_fill,\n stroke: exon_stroke\n });\n width = function (d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function () {\n return data_layer.layout.exon_height;\n };\n x = function (d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function () {\n return (gene.track - 1) * data_layer.getTrackHeight() + data_layer.layout.bounding_box_padding + data_layer.layout.label_font_size + data_layer.layout.label_exon_spacing;\n };\n if (data_layer.canTransition()) {\n exons.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n exons.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n exons.exit().remove();\n // Render gene click area\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-clickarea').data([gene], function (d) {\n return d.gene_name + '_clickarea';\n });\n clickareas.enter().append('rect').attr('class', 'lz-data_layer-genes lz-clickarea');\n clickareas.attr('id', function (d) {\n return data_layer.getElementId(d) + '_clickarea';\n }).attr('rx', function () {\n return data_layer.layout.bounding_box_padding;\n }).attr('ry', function () {\n return data_layer.layout.bounding_box_padding;\n });\n width = function (d) {\n return d.display_range.width;\n };\n height = function () {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function (d) {\n return d.display_range.start;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight();\n };\n if (data_layer.canTransition()) {\n clickareas.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n // Remove old clickareas as needed\n clickareas.exit().remove();\n // Apply default event emitters to clickareas\n clickareas.on('click.event_emitter', function (element) {\n element.parent.parent.emit('element_clicked', element, true);\n });\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n });\n // Remove old elements as needed\n selection.exit().remove();\n };\n /**\n * Reimplement the positionTooltip() method to be gene-specific\n * @param {String} id\n */\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var gene_bbox_id = this.getElementStatusNodeId(tooltip.data);\n var gene_bbox = d3.select('#' + gene_bbox_id).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the gene that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var gene_center_x = (tooltip.data.display_range.start + tooltip.data.display_range.end) / 2 - this.layout.bounding_box_padding / 2;\n var offset_right = Math.max(tooltip_box.width / 2 - gene_center_x, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + gene_center_x - data_layer_width, 0);\n var left = page_origin.x + gene_center_x - tooltip_box.width / 2 - offset_left + offset_right;\n var arrow_left = tooltip_box.width / 2 - arrow_width / 2 + offset_left - offset_right;\n // Position vertically below the gene unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (gene_bbox.y + gene_bbox.height)) {\n top = page_origin.y + gene_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + gene_bbox.y + gene_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n return this;\n });\n 'use strict';\n /*********************\n Genome Legend Data Layer\n Implements a data layer that will render a genome legend\n*/\n // Build a custom data layer for a genome legend\n LocusZoom.DataLayers.add('genome_legend', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n chromosome_fill_colors: {\n light: 'rgb(155, 155, 188)',\n dark: 'rgb(95, 95, 128)'\n },\n chromosome_label_colors: {\n light: 'rgb(120, 120, 186)',\n dark: 'rgb(0, 0, 66)'\n }\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n // Implement the main render function\n this.render = function () {\n // Iterate over data to generate genome-wide start/end values for each chromosome\n var position = 0;\n this.data.forEach(function (d, i) {\n this.data[i].genome_start = position;\n this.data[i].genome_end = position + d['genome:base_pairs'];\n position += d['genome:base_pairs'];\n }.bind(this));\n var chromosomes = this.svg.group.selectAll('rect.lz-data_layer-genome_legend').data(this.data, function (d) {\n return d['genome:chr'];\n });\n // Create chromosome elements, apply class\n chromosomes.enter().append('rect').attr('class', 'lz-data_layer-genome_legend');\n // Position and fill chromosome rects\n var data_layer = this;\n var panel = this.parent;\n chromosomes.attr('fill', function (d) {\n return d['genome:chr'] % 2 ? data_layer.layout.chromosome_fill_colors.light : data_layer.layout.chromosome_fill_colors.dark;\n }).attr('x', function (d) {\n return panel.x_scale(d.genome_start);\n }).attr('y', 0).attr('width', function (d) {\n return panel.x_scale(d['genome:base_pairs']);\n }).attr('height', panel.layout.cliparea.height);\n // Remove old elements as needed\n chromosomes.exit().remove();\n // Parse current state variant into a position\n // Assumes that variant string is of the format 10:123352136_C/T or 10:123352136\n var variant_parts = /([^:]+):(\\d+)(?:_.*)?/.exec(this.state.variant);\n if (!variant_parts) {\n throw new Error('Genome legend cannot understand the specified variant position');\n }\n var chr = variant_parts[1];\n var offset = variant_parts[2];\n // TODO: How does this handle representation of X or Y chromosomes?\n position = +this.data[chr - 1].genome_start + +offset;\n // Render the position\n var region = this.svg.group.selectAll('rect.lz-data_layer-genome_legend-marker').data([{\n start: position,\n end: position + 1\n }]);\n region.enter().append('rect').attr('class', 'lz-data_layer-genome_legend-marker');\n region.transition().duration(500).style({\n 'fill': 'rgba(255, 250, 50, 0.8)',\n 'stroke': 'rgba(255, 250, 50, 0.8)',\n 'stroke-width': '3px'\n }).attr('x', function (d) {\n return panel.x_scale(d.start);\n }).attr('y', 0).attr('width', function (d) {\n return panel.x_scale(d.end - d.start);\n }).attr('height', panel.layout.cliparea.height);\n region.exit().remove();\n };\n return this;\n });\n 'use strict';\n /**\n * Intervals Data Layer\n * Implements a data layer that will render interval annotation tracks (intervals must provide start and end values)\n * @class LocusZoom.DataLayers.intervals\n * @augments LocusZoom.DataLayer\n */\n LocusZoom.DataLayers.add('intervals', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n start_field: 'start',\n end_field: 'end',\n track_split_field: 'state_id',\n track_split_order: 'DESC',\n track_split_legend_to_y_axis: 2,\n split_tracks: true,\n track_height: 15,\n track_vertical_spacing: 3,\n bounding_box_padding: 2,\n always_hide_legend: false,\n color: '#B8B8B8',\n fill_opacity: 1\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n /**\n * To define shared highlighting on the track split field define the status node id override\n * to generate an ID common to the track when we're actively splitting data out to separate tracks\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function (element) {\n if (this.layout.split_tracks) {\n return (this.getBaseId() + '-statusnode-' + element[this.layout.track_split_field]).replace(/[:.[\\],]/g, '_');\n }\n return this.getElementId(element) + '-statusnode';\n }.bind(this);\n // Helper function to sum layout values to derive total height for a single interval track\n this.getTrackHeight = function () {\n return this.layout.track_height + this.layout.track_vertical_spacing + 2 * this.layout.bounding_box_padding;\n };\n this.tracks = 1;\n this.previous_tracks = 1;\n // track-number-indexed object with arrays of interval indexes in the dataset\n this.interval_track_index = { 1: [] };\n // After we've loaded interval data interpret it to assign\n // each to a track so that they do not overlap in the view\n this.assignTracks = function () {\n // Reinitialize some metadata\n this.previous_tracks = this.tracks;\n this.tracks = 0;\n this.interval_track_index = { 1: [] };\n this.track_split_field_index = {};\n // If splitting tracks by a field's value then do a first pass determine\n // a value/track mapping that preserves the order of possible values\n if (this.layout.track_split_field && this.layout.split_tracks) {\n this.data.map(function (d) {\n this.track_split_field_index[d[this.layout.track_split_field]] = null;\n }.bind(this));\n var index = Object.keys(this.track_split_field_index);\n if (this.layout.track_split_order === 'DESC') {\n index.reverse();\n }\n index.forEach(function (val) {\n this.track_split_field_index[val] = this.tracks + 1;\n this.interval_track_index[this.tracks + 1] = [];\n this.tracks++;\n }.bind(this));\n }\n this.data.map(function (d, i) {\n // Stash a parent reference on the interval\n this.data[i].parent = this;\n // Determine display range start and end, based on minimum allowable interval display width,\n // bounded by what we can see (range: values in terms of pixels on the screen)\n this.data[i].display_range = {\n start: this.parent.x_scale(Math.max(d[this.layout.start_field], this.state.start)),\n end: this.parent.x_scale(Math.min(d[this.layout.end_field], this.state.end))\n };\n this.data[i].display_range.width = this.data[i].display_range.end - this.data[i].display_range.start;\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[i].display_domain = {\n start: this.parent.x_scale.invert(this.data[i].display_range.start),\n end: this.parent.x_scale.invert(this.data[i].display_range.end)\n };\n this.data[i].display_domain.width = this.data[i].display_domain.end - this.data[i].display_domain.start;\n // If splitting to tracks based on the value of the designated track split field\n // then don't bother with collision detection (intervals will be grouped on tracks\n // solely by the value of track_split_field)\n if (this.layout.track_split_field && this.layout.split_tracks) {\n var val = this.data[i][this.layout.track_split_field];\n this.data[i].track = this.track_split_field_index[val];\n this.interval_track_index[this.data[i].track].push(i);\n } else {\n // If not splitting to tracks based on a field value then do so based on collision\n // detection (as how it's done for genes). Use display range/domain data generated\n // above and cast each interval to tracks such that none overlap\n this.tracks = 1;\n this.data[i].track = null;\n var potential_track = 1;\n while (this.data[i].track === null) {\n var collision_on_potential_track = false;\n this.interval_track_index[potential_track].map(function (placed_interval) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_interval.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_interval.display_range.end, this.display_range.end);\n if (max_end - min_start < placed_interval.display_range.width + this.display_range.width) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[i]));\n if (!collision_on_potential_track) {\n this.data[i].track = potential_track;\n this.interval_track_index[potential_track].push(this.data[i]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.interval_track_index[potential_track] = [];\n }\n }\n }\n }\n }.bind(this));\n return this;\n };\n // Implement the main render function\n this.render = function () {\n this.assignTracks();\n // Remove any shared highlight nodes and re-render them if we're splitting on tracks\n // At most there will only be dozen or so nodes here (one per track) and each time\n // we render data we may have new tracks, so wiping/redrawing all is reasonable.\n this.svg.group.selectAll('.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-shared').remove();\n Object.keys(this.track_split_field_index).forEach(function (key) {\n // Make a psuedo-element so that we can generate an id for the shared node\n var psuedoElement = {};\n psuedoElement[this.layout.track_split_field] = key;\n // Insert the shared node\n var sharedstatusnode_style = { display: this.layout.split_tracks ? null : 'none' };\n this.svg.group.insert('rect', ':first-child').attr('id', this.getElementStatusNodeId(psuedoElement)).attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-shared').attr('rx', this.layout.bounding_box_padding).attr('ry', this.layout.bounding_box_padding).attr('width', this.parent.layout.cliparea.width).attr('height', this.getTrackHeight() - this.layout.track_vertical_spacing).attr('x', 0).attr('y', (this.track_split_field_index[key] - 1) * this.getTrackHeight()).style(sharedstatusnode_style);\n }.bind(this));\n var width, height, x, y, fill, fill_opacity;\n // Render interval groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-intervals').data(this.data, function (d) {\n return d[this.layout.id_field];\n }.bind(this));\n selection.enter().append('g').attr('class', 'lz-data_layer-intervals');\n selection.attr('id', function (d) {\n return this.getElementId(d);\n }.bind(this)).each(function (interval) {\n var data_layer = interval.parent;\n // Render interval status nodes (displayed behind intervals to show highlight\n // without needing to modify interval display element(s))\n var statusnode_style = { display: data_layer.layout.split_tracks ? 'none' : null };\n var statusnodes = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-statusnode-discrete').data([interval], function (d) {\n return data_layer.getElementId(d) + '-statusnode';\n });\n statusnodes.enter().insert('rect', ':first-child').attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-statusnode-discrete');\n statusnodes.attr('id', function (d) {\n return data_layer.getElementId(d) + '-statusnode';\n }).attr('rx', function () {\n return data_layer.layout.bounding_box_padding;\n }).attr('ry', function () {\n return data_layer.layout.bounding_box_padding;\n }).style(statusnode_style);\n width = function (d) {\n return d.display_range.width + 2 * data_layer.layout.bounding_box_padding;\n };\n height = function () {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function (d) {\n return d.display_range.start - data_layer.layout.bounding_box_padding;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight();\n };\n if (data_layer.canTransition()) {\n statusnodes.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n statusnodes.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n statusnodes.exit().remove();\n // Render primary interval rects\n var rects = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-interval_rect').data([interval], function (d) {\n return d[data_layer.layout.id_field] + '_interval_rect';\n });\n rects.enter().append('rect').attr('class', 'lz-data_layer-intervals lz-interval_rect');\n height = data_layer.layout.track_height;\n width = function (d) {\n return d.display_range.width;\n };\n x = function (d) {\n return d.display_range.start;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight() + data_layer.layout.bounding_box_padding;\n };\n fill = function (d) {\n return data_layer.resolveScalableParameter(data_layer.layout.color, d);\n };\n fill_opacity = function (d) {\n return data_layer.resolveScalableParameter(data_layer.layout.fill_opacity, d);\n };\n if (data_layer.canTransition()) {\n rects.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y).attr('fill', fill).attr('fill-opacity', fill_opacity);\n } else {\n rects.attr('width', width).attr('height', height).attr('x', x).attr('y', y).attr('fill', fill).attr('fill-opacity', fill_opacity);\n }\n rects.exit().remove();\n // Render interval click areas\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-clickarea').data([interval], function (d) {\n return d.interval_name + '_clickarea';\n });\n clickareas.enter().append('rect').attr('class', 'lz-data_layer-intervals lz-clickarea');\n clickareas.attr('id', function (d) {\n return data_layer.getElementId(d) + '_clickarea';\n }).attr('rx', function () {\n return data_layer.layout.bounding_box_padding;\n }).attr('ry', function () {\n return data_layer.layout.bounding_box_padding;\n });\n width = function (d) {\n return d.display_range.width;\n };\n height = function () {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function (d) {\n return d.display_range.start;\n };\n y = function (d) {\n return (d.track - 1) * data_layer.getTrackHeight();\n };\n if (data_layer.canTransition()) {\n clickareas.transition().duration(data_layer.layout.transition.duration || 0).ease(data_layer.layout.transition.ease || 'cubic-in-out').attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas.attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n // Remove old clickareas as needed\n clickareas.exit().remove();\n // Apply default event emitters to clickareas\n clickareas.on('click', function (element_data) {\n element_data.parent.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n });\n // Remove old elements as needed\n selection.exit().remove();\n // Update the legend axis if the number of ticks changed\n if (this.previous_tracks !== this.tracks) {\n this.updateSplitTrackAxis();\n }\n return this;\n };\n // Reimplement the positionTooltip() method to be interval-specific\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var interval_bbox = d3.select('#' + this.getElementStatusNodeId(tooltip.data)).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the interval that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var interval_center_x = (tooltip.data.display_range.start + tooltip.data.display_range.end) / 2 - this.layout.bounding_box_padding / 2;\n var offset_right = Math.max(tooltip_box.width / 2 - interval_center_x, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + interval_center_x - data_layer_width, 0);\n var left = page_origin.x + interval_center_x - tooltip_box.width / 2 - offset_left + offset_right;\n var arrow_left = tooltip_box.width / 2 - arrow_width / 2 + offset_left - offset_right;\n // Position vertically below the interval unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (interval_bbox.y + interval_bbox.height)) {\n top = page_origin.y + interval_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + interval_bbox.y + interval_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n // Redraw split track axis or hide it, and show/hide the legend, as determined\n // by current layout parameters and data\n this.updateSplitTrackAxis = function () {\n var legend_axis = this.layout.track_split_legend_to_y_axis ? 'y' + this.layout.track_split_legend_to_y_axis : false;\n if (this.layout.split_tracks) {\n var tracks = +this.tracks || 0;\n var track_height = +this.layout.track_height || 0;\n var track_spacing = 2 * (+this.layout.bounding_box_padding || 0) + (+this.layout.track_vertical_spacing || 0);\n var target_height = tracks * track_height + (tracks - 1) * track_spacing;\n this.parent.scaleHeightToData(target_height);\n if (legend_axis && this.parent.legend) {\n this.parent.legend.hide();\n this.parent.layout.axes[legend_axis] = {\n render: true,\n ticks: [],\n range: {\n start: target_height - this.layout.track_height / 2,\n end: this.layout.track_height / 2\n }\n };\n this.layout.legend.forEach(function (element) {\n var key = element[this.layout.track_split_field];\n var track = this.track_split_field_index[key];\n if (track) {\n if (this.layout.track_split_order === 'DESC') {\n track = Math.abs(track - tracks - 1);\n }\n this.parent.layout.axes[legend_axis].ticks.push({\n y: track,\n text: element.label\n });\n }\n }.bind(this));\n this.layout.y_axis = {\n axis: this.layout.track_split_legend_to_y_axis,\n floor: 1,\n ceiling: tracks\n };\n this.parent.render();\n }\n this.parent_plot.positionPanels();\n } else {\n if (legend_axis && this.parent.legend) {\n if (!this.layout.always_hide_legend) {\n this.parent.legend.show();\n }\n this.parent.layout.axes[legend_axis] = { render: false };\n this.parent.render();\n }\n }\n return this;\n };\n // Method to not only toggle the split tracks boolean but also update\n // necessary display values to animate a complete merge/split\n this.toggleSplitTracks = function () {\n this.layout.split_tracks = !this.layout.split_tracks;\n if (this.parent.legend && !this.layout.always_hide_legend) {\n this.parent.layout.margin.bottom = 5 + (this.layout.split_tracks ? 0 : this.parent.legend.layout.height + 5);\n }\n this.render();\n this.updateSplitTrackAxis();\n return this;\n };\n return this;\n });\n 'use strict';\n /*********************\n * Line Data Layer\n * Implements a standard line plot, representing either a trace or a filled curve.\n * @class\n * @augments LocusZoom.DataLayer\n*/\n LocusZoom.DataLayers.add('line', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n /** @member {Object} */\n this.DefaultLayout = {\n style: {\n fill: 'none',\n 'stroke-width': '2px'\n },\n interpolate: 'linear',\n x_axis: { field: 'x' },\n y_axis: {\n field: 'y',\n axis: 1\n },\n hitarea_width: 5\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Var for storing mouse events for use in tool tip positioning\n /** @member {String} */\n this.mouse_event = null;\n /**\n * Var for storing the generated line function itself\n * @member {d3.svg.line}\n * */\n this.line = null;\n /**\n * The timeout identifier returned by setTimeout\n * @member {Number}\n */\n this.tooltip_timeout = null;\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n /**\n * Helper function to get display and data objects representing\n * the x/y coordinates of the current mouse event with respect to the line in terms of the display\n * and the interpolated values of the x/y fields with respect to the line\n * @returns {{display: {x: *, y: null}, data: {}, slope: null}}\n */\n this.getMouseDisplayAndData = function () {\n var ret = {\n display: {\n x: d3.mouse(this.mouse_event)[0],\n y: null\n },\n data: {},\n slope: null\n };\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n ret.data[x_field] = this.parent[x_scale].invert(ret.display.x);\n var bisect = d3.bisector(function (datum) {\n return +datum[x_field];\n }).left;\n var index = bisect(this.data, ret.data[x_field]) - 1;\n var startDatum = this.data[index];\n var endDatum = this.data[index + 1];\n var interpolate = d3.interpolateNumber(+startDatum[y_field], +endDatum[y_field]);\n var range = +endDatum[x_field] - +startDatum[x_field];\n ret.data[y_field] = interpolate(ret.data[x_field] % range / range);\n ret.display.y = this.parent[y_scale](ret.data[y_field]);\n if (this.layout.tooltip.x_precision) {\n ret.data[x_field] = ret.data[x_field].toPrecision(this.layout.tooltip.x_precision);\n }\n if (this.layout.tooltip.y_precision) {\n ret.data[y_field] = ret.data[y_field].toPrecision(this.layout.tooltip.y_precision);\n }\n ret.slope = (this.parent[y_scale](endDatum[y_field]) - this.parent[y_scale](startDatum[y_field])) / (this.parent[x_scale](endDatum[x_field]) - this.parent[x_scale](startDatum[x_field]));\n return ret;\n };\n /**\n * Reimplement the positionTooltip() method to be line-specific\n * @param {String} id Identify the tooltip to be positioned\n */\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var arrow_width = 7;\n // as defined in the default stylesheet\n var border_radius = 6;\n // as defined in the default stylesheet\n var stroke_width = parseFloat(this.layout.style['stroke-width']) || 1;\n var page_origin = this.getPageOrigin();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n var top, left, arrow_top, arrow_left, arrow_type;\n // Determine x/y coordinates for display and data\n var dd = this.getMouseDisplayAndData();\n // If the absolute value of the slope of the line at this point is above 1 (including Infinity)\n // then position the tool tip left/right. Otherwise position top/bottom.\n if (Math.abs(dd.slope) > 1) {\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (dd.display.x <= this.parent.layout.width / 2) {\n left = page_origin.x + dd.display.x + stroke_width + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + dd.display.x - tooltip_box.width - stroke_width - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n if (dd.display.y - tooltip_box.height / 2 <= 0) {\n // Too close to the top, push it down\n top = page_origin.y + dd.display.y - 1.5 * arrow_width - border_radius;\n arrow_top = border_radius;\n } else if (dd.display.y + tooltip_box.height / 2 >= data_layer_height) {\n // Too close to the bottom, pull it up\n top = page_origin.y + dd.display.y + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - 2 * arrow_width - border_radius;\n } else {\n // vertically centered\n top = page_origin.y + dd.display.y - tooltip_box.height / 2;\n arrow_top = tooltip_box.height / 2 - arrow_width;\n }\n } else {\n // Position horizontally: attempt to center on the mouse's x coordinate\n // pad to either side if bumping up against the edge of the data layer\n var offset_right = Math.max(tooltip_box.width / 2 - dd.display.x, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + dd.display.x - data_layer_width, 0);\n left = page_origin.x + dd.display.x - tooltip_box.width / 2 - offset_left + offset_right;\n var min_arrow_left = arrow_width / 2;\n var max_arrow_left = tooltip_box.width - 2.5 * arrow_width;\n arrow_left = tooltip_box.width / 2 - arrow_width + offset_left - offset_right;\n arrow_left = Math.min(Math.max(arrow_left, min_arrow_left), max_arrow_left);\n // Position vertically above the line unless there's insufficient space\n if (tooltip_box.height + stroke_width + arrow_width > dd.display.y) {\n top = page_origin.y + dd.display.y + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n } else {\n top = page_origin.y + dd.display.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n }\n }\n // Apply positions to the main div\n tooltip.selector.style({\n left: left + 'px',\n top: top + 'px'\n });\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style({\n 'left': arrow_left + 'px',\n top: arrow_top + 'px'\n });\n };\n /**\n * Implement the main render function\n */\n this.render = function () {\n // Several vars needed to be in scope\n var data_layer = this;\n var panel = this.parent;\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n // Join data to the line selection\n var selection = this.svg.group.selectAll('path.lz-data_layer-line').data([this.data]);\n // Create path element, apply class\n this.path = selection.enter().append('path').attr('class', 'lz-data_layer-line');\n // Generate the line\n if (this.layout.style.fill && this.layout.style.fill !== 'none') {\n // Filled curve: define the line as a filled boundary\n this.line = d3.svg.area().x(function (d) {\n return parseFloat(panel[x_scale](d[x_field]));\n }).y0(function (d) {\n return parseFloat(panel[y_scale](0));\n }).y1(function (d) {\n return parseFloat(panel[y_scale](d[y_field]));\n });\n } else {\n // Basic line\n this.line = d3.svg.line().x(function (d) {\n return parseFloat(panel[x_scale](d[x_field]));\n }).y(function (d) {\n return parseFloat(panel[y_scale](d[y_field]));\n }).interpolate(this.layout.interpolate);\n }\n // Apply line and style\n if (this.canTransition()) {\n selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('d', this.line).style(this.layout.style);\n } else {\n selection.attr('d', this.line).style(this.layout.style);\n }\n // Apply tooltip, etc\n if (this.layout.tooltip) {\n // Generate an overlaying transparent \"hit area\" line for more intuitive mouse events\n var hitarea_width = parseFloat(this.layout.hitarea_width).toString() + 'px';\n var hitarea = this.svg.group.selectAll('path.lz-data_layer-line-hitarea').data([this.data]);\n hitarea.enter().append('path').attr('class', 'lz-data_layer-line-hitarea').style('stroke-width', hitarea_width);\n var hitarea_line = d3.svg.line().x(function (d) {\n return parseFloat(panel[x_scale](d[x_field]));\n }).y(function (d) {\n return parseFloat(panel[y_scale](d[y_field]));\n }).interpolate(this.layout.interpolate);\n hitarea.attr('d', hitarea_line).on('mouseover', function () {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.createTooltip(dd.data);\n }).on('mousemove', function () {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.updateTooltip(dd.data);\n data_layer.positionTooltip(data_layer.getElementId());\n }).on('mouseout', function () {\n data_layer.tooltip_timeout = setTimeout(function () {\n data_layer.mouse_event = null;\n data_layer.destroyTooltip(data_layer.getElementId());\n }, 300);\n });\n hitarea.exit().remove();\n }\n // Remove old elements as needed\n selection.exit().remove();\n };\n /**\n * Redefine setElementStatus family of methods as line data layers will only ever have a single path element\n * @param {String} status A member of `LocusZoom.DataLayer.Statuses.adjectives`\n * @param {String|Object} element\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\n this.setElementStatus = function (status, element, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setElementStatusByFilters = function (status, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setAllElementStatus = function (status, toggle) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') {\n return this;\n }\n if (typeof toggle == 'undefined') {\n toggle = true;\n }\n // Update global status flag\n this.global_statuses[status] = toggle;\n // Apply class to path based on global status flags\n var path_class = 'lz-data_layer-line';\n Object.keys(this.global_statuses).forEach(function (global_status) {\n if (this.global_statuses[global_status]) {\n path_class += ' lz-data_layer-line-' + global_status;\n }\n }.bind(this));\n this.path.attr('class', path_class);\n // Trigger layout changed event hook\n this.parent.emit('layout_changed', true);\n return this;\n };\n return this;\n });\n /***************************\n * Orthogonal Line Data Layer\n * Implements a horizontal or vertical line given an orientation and an offset in the layout\n * Does not require a data source\n * @class\n * @augments LocusZoom.DataLayer\n*/\n LocusZoom.DataLayers.add('orthogonal_line', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n style: {\n 'stroke': '#D3D3D3',\n 'stroke-width': '3px',\n 'stroke-dasharray': '10px 10px'\n },\n orientation: 'horizontal',\n x_axis: {\n axis: 1,\n decoupled: true\n },\n y_axis: {\n axis: 1,\n decoupled: true\n },\n offset: 0\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Require that orientation be \"horizontal\" or \"vertical\" only\n if ([\n 'horizontal',\n 'vertical'\n ].indexOf(layout.orientation) === -1) {\n layout.orientation = 'horizontal';\n }\n // Vars for storing the data generated line\n /** @member {Array} */\n this.data = [];\n /** @member {d3.svg.line} */\n this.line = null;\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n /**\n * Implement the main render function\n */\n this.render = function () {\n // Several vars needed to be in scope\n var panel = this.parent;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var x_extent = 'x_extent';\n var y_extent = 'y' + this.layout.y_axis.axis + '_extent';\n var x_range = 'x_range';\n // Generate data using extents depending on orientation\n if (this.layout.orientation === 'horizontal') {\n this.data = [\n {\n x: panel[x_extent][0],\n y: this.layout.offset\n },\n {\n x: panel[x_extent][1],\n y: this.layout.offset\n }\n ];\n } else if (this.layout.orientation === 'vertical') {\n this.data = [\n {\n x: this.layout.offset,\n y: panel[y_extent][0]\n },\n {\n x: this.layout.offset,\n y: panel[y_extent][1]\n }\n ];\n } else {\n throw new Error('Unrecognized vertical line type. Must be \"vertical\" or \"horizontal\"');\n }\n // Join data to the line selection\n var selection = this.svg.group.selectAll('path.lz-data_layer-line').data([this.data]);\n // Create path element, apply class\n this.path = selection.enter().append('path').attr('class', 'lz-data_layer-line');\n // In some cases, a vertical line may overlay a track that has no inherent y-values (extent)\n // When that happens, provide a default height based on the current panel dimensions (accounting\n // for any resizing that happened after the panel was created)\n var default_y = [\n panel.layout.cliparea.height,\n 0\n ];\n // Generate the line\n this.line = d3.svg.line().x(function (d, i) {\n var x = parseFloat(panel[x_scale](d['x']));\n return isNaN(x) ? panel[x_range][i] : x;\n }).y(function (d, i) {\n var y = parseFloat(panel[y_scale](d['y']));\n return isNaN(y) ? default_y[i] : y;\n }).interpolate('linear');\n // Apply line and style\n if (this.canTransition()) {\n selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('d', this.line).style(this.layout.style);\n } else {\n selection.attr('d', this.line).style(this.layout.style);\n }\n // Remove old elements as needed\n selection.exit().remove();\n };\n return this;\n });\n 'use strict';\n /**\n * Scatter Data Layer\n * Implements a standard scatter plot\n * @class LocusZoom.DataLayers.scatter\n */\n LocusZoom.DataLayers.add('scatter', function (layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'circle',\n tooltip_positioning: 'horizontal',\n color: '#888888',\n fill_opacity: 1,\n y_axis: { axis: 1 },\n id_field: 'id'\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n // Extra default for layout spacing\n // Not in default layout since that would make the label attribute always present\n if (layout.label && isNaN(layout.label.spacing)) {\n layout.label.spacing = 4;\n }\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n // Reimplement the positionTooltip() method to be scatter-specific\n this.positionTooltip = function (id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var offset = Math.sqrt(point_size / Math.PI);\n var arrow_width = 7;\n // as defined in the default stylesheet\n var stroke_width = 1;\n // as defined in the default stylesheet\n var border_radius = 6;\n // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n if (this.layout.tooltip_positioning === 'vertical') {\n // Position horizontally centered above the point\n var offset_right = Math.max(tooltip_box.width / 2 - x_center, 0);\n var offset_left = Math.max(tooltip_box.width / 2 + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - tooltip_box.width / 2 - offset_left + offset_right;\n arrow_left = tooltip_box.width / 2 - arrow_width / 2 + offset_left - offset_right - offset;\n // Position vertically above the point unless there's insufficient space, then go below\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (y_center + offset)) {\n top = page_origin.y + y_center - (offset + tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + y_center + offset + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n } else {\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n if (y_center - tooltip_box.height / 2 <= 0) {\n // Too close to the top, push it down\n top = page_origin.y + y_center - 1.5 * arrow_width - border_radius;\n arrow_top = border_radius;\n } else if (y_center + tooltip_box.height / 2 >= data_layer_height) {\n // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - 2 * arrow_width - border_radius;\n } else {\n // vertically centered\n top = page_origin.y + y_center - tooltip_box.height / 2;\n arrow_top = tooltip_box.height / 2 - arrow_width;\n }\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow.attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type).style('left', arrow_left + 'px').style('top', arrow_top + 'px');\n };\n // Function to flip labels from being anchored at the start of the text to the end\n // Both to keep labels from running outside the data layer and also as a first\n // pass on recursive separation\n this.flip_labels = function () {\n var data_layer = this;\n var point_size = data_layer.resolveScalableParameter(data_layer.layout.point_size, {});\n var spacing = data_layer.layout.label.spacing;\n var handle_lines = Boolean(data_layer.layout.label.lines);\n var min_x = 2 * spacing;\n var max_x = data_layer.parent.layout.width - data_layer.parent.layout.margin.left - data_layer.parent.layout.margin.right - 2 * spacing;\n var flip = function (dn, dnl) {\n var dnx = +dn.attr('x');\n var text_swing = 2 * spacing + 2 * Math.sqrt(point_size);\n if (handle_lines) {\n var dnlx2 = +dnl.attr('x2');\n var line_swing = spacing + 2 * Math.sqrt(point_size);\n }\n if (dn.style('text-anchor') === 'start') {\n dn.style('text-anchor', 'end');\n dn.attr('x', dnx - text_swing);\n if (handle_lines) {\n dnl.attr('x2', dnlx2 - line_swing);\n }\n } else {\n dn.style('text-anchor', 'start');\n dn.attr('x', dnx + text_swing);\n if (handle_lines) {\n dnl.attr('x2', dnlx2 + line_swing);\n }\n }\n };\n // Flip any going over the right edge from the right side to the left side\n // (all labels start on the right side)\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n if (dax + abound.width + spacing > max_x) {\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n flip(da, dal);\n }\n });\n // Second pass to flip any others that haven't flipped yet if they collide with another label\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n if (da.style('text-anchor') === 'end') {\n return;\n }\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n data_layer.label_texts.each(function () {\n var b = this;\n var db = d3.select(b);\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + 2 * spacing && abound.left + abound.width + 2 * spacing > bbound.left && abound.top < bbound.top + bbound.height + 2 * spacing && abound.height + abound.top + 2 * spacing > bbound.top;\n if (collision) {\n flip(da, dal);\n // Double check that this flip didn't push the label past min_x. If it did, immediately flip back.\n dax = +da.attr('x');\n if (dax - abound.width - spacing < min_x) {\n flip(da, dal);\n }\n }\n return;\n });\n });\n };\n // Recursive function to space labels apart immediately after initial render\n // Adapted from thudfactor's fiddle here: https://jsfiddle.net/thudfactor/HdwTH/\n // TODO: Make labels also aware of data elements\n this.separate_labels = function () {\n this.seperate_iterations++;\n var data_layer = this;\n var alpha = 0.5;\n if (!this.layout.label) {\n // Guard against layout changing in the midst of iterative rerender\n return;\n }\n var spacing = this.layout.label.spacing;\n var again = false;\n data_layer.label_texts.each(function () {\n var a = this;\n var da = d3.select(a);\n var y1 = da.attr('y');\n data_layer.label_texts.each(function () {\n var b = this;\n // a & b are the same element and don't collide.\n if (a === b) {\n return;\n }\n var db = d3.select(b);\n // a & b are on opposite sides of the chart and\n // don't collide\n if (da.attr('text-anchor') !== db.attr('text-anchor')) {\n return;\n }\n // Determine if the bounding rects for the two text elements collide\n var abound = da.node().getBoundingClientRect();\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + 2 * spacing && abound.left + abound.width + 2 * spacing > bbound.left && abound.top < bbound.top + bbound.height + 2 * spacing && abound.height + abound.top + 2 * spacing > bbound.top;\n if (!collision) {\n return;\n }\n again = true;\n // If the labels collide, we'll push each\n // of the two labels up and down a little bit.\n var y2 = db.attr('y');\n var sign = abound.top < bbound.top ? 1 : -1;\n var adjust = sign * alpha;\n var new_a_y = +y1 - adjust;\n var new_b_y = +y2 + adjust;\n // Keep new values from extending outside the data layer\n var min_y = 2 * spacing;\n var max_y = data_layer.parent.layout.height - data_layer.parent.layout.margin.top - data_layer.parent.layout.margin.bottom - 2 * spacing;\n var delta;\n if (new_a_y - abound.height / 2 < min_y) {\n delta = +y1 - new_a_y;\n new_a_y = +y1;\n new_b_y += delta;\n } else if (new_b_y - bbound.height / 2 < min_y) {\n delta = +y2 - new_b_y;\n new_b_y = +y2;\n new_a_y += delta;\n }\n if (new_a_y + abound.height / 2 > max_y) {\n delta = new_a_y - +y1;\n new_a_y = +y1;\n new_b_y -= delta;\n } else if (new_b_y + bbound.height / 2 > max_y) {\n delta = new_b_y - +y2;\n new_b_y = +y2;\n new_a_y -= delta;\n }\n da.attr('y', new_a_y);\n db.attr('y', new_b_y);\n });\n });\n if (again) {\n // Adjust lines to follow the labels\n if (data_layer.layout.label.lines) {\n var label_elements = data_layer.label_texts[0];\n data_layer.label_lines.attr('y2', function (d, i) {\n var label_line = d3.select(label_elements[i]);\n return label_line.attr('y');\n });\n }\n // After ~150 iterations we're probably beyond diminising returns, so stop recursing\n if (this.seperate_iterations < 150) {\n setTimeout(function () {\n this.separate_labels();\n }.bind(this), 1);\n }\n }\n };\n // Implement the main render function\n this.render = function () {\n var data_layer = this;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n if (this.layout.label) {\n // Apply filters to generate a filtered data set\n var filtered_data = this.data.filter(function (d) {\n if (!data_layer.layout.label.filters) {\n return true;\n } else {\n // Start by assuming a match, run through all filters to test if not a match on any one\n var match = true;\n data_layer.layout.label.filters.forEach(function (filter) {\n var field_value = new LocusZoom.Data.Field(filter.field).resolve(d);\n if ([\n '!=',\n '='\n ].indexOf(filter.operator) === -1 && isNaN(field_value)) {\n // If the filter can only be used with numbers, then the value must be numeric.\n match = false;\n } else {\n switch (filter.operator) {\n case '<':\n if (!(field_value < filter.value)) {\n match = false;\n }\n break;\n case '<=':\n if (!(field_value <= filter.value)) {\n match = false;\n }\n break;\n case '>':\n if (!(field_value > filter.value)) {\n match = false;\n }\n break;\n case '>=':\n if (!(field_value >= filter.value)) {\n match = false;\n }\n break;\n case '=':\n if (!(field_value === filter.value)) {\n match = false;\n }\n break;\n case '!=':\n // Deliberately allow weak comparisons to test for \"anything with a value present\" (null or undefined)\n // eslint-disable-next-line eqeqeq\n if (field_value == filter.value) {\n match = false;\n }\n break;\n default:\n // If we got here the operator is not valid, so the filter should fail\n match = false;\n break;\n }\n }\n });\n return match;\n }\n });\n // Render label groups\n var self = this;\n this.label_groups = this.svg.group.selectAll('g.lz-data_layer-' + this.layout.type + '-label').data(filtered_data, function (d) {\n return d[self.layout.id_field] + '_label';\n });\n this.label_groups.enter().append('g').attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n // Render label texts\n if (this.label_texts) {\n this.label_texts.remove();\n }\n this.label_texts = this.label_groups.append('text').attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_texts.text(function (d) {\n return LocusZoom.parseFields(d, data_layer.layout.label.text || '');\n }).style(data_layer.layout.label.style || {}).attr({\n 'x': function (d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]) + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d)) + data_layer.layout.label.spacing;\n if (isNaN(x)) {\n x = -1000;\n }\n return x;\n },\n 'y': function (d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) {\n y = -1000;\n }\n return y;\n },\n 'text-anchor': function () {\n return 'start';\n }\n });\n // Render label lines\n if (data_layer.layout.label.lines) {\n if (this.label_lines) {\n this.label_lines.remove();\n }\n this.label_lines = this.label_groups.append('line').attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_lines.style(data_layer.layout.label.lines.style || {}).attr({\n 'x1': function (d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]);\n if (isNaN(x)) {\n x = -1000;\n }\n return x;\n },\n 'y1': function (d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) {\n y = -1000;\n }\n return y;\n },\n 'x2': function (d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]) + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d)) + data_layer.layout.label.spacing / 2;\n if (isNaN(x)) {\n x = -1000;\n }\n return x;\n },\n 'y2': function (d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) {\n y = -1000;\n }\n return y;\n }\n });\n }\n // Remove labels when they're no longer in the filtered data set\n this.label_groups.exit().remove();\n } else {\n // If the layout definition has changed (& no longer specifies labels), strip any previously rendered\n if (this.label_groups) {\n this.label_groups.remove();\n }\n if (this.label_lines) {\n this.label_lines.remove();\n }\n }\n // Generate main scatter data elements\n var selection = this.svg.group.selectAll('path.lz-data_layer-' + this.layout.type).data(this.data, function (d) {\n return d[this.layout.id_field];\n }.bind(this));\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n selection.enter().append('path').attr('class', 'lz-data_layer-' + this.layout.type).attr('id', function (d) {\n return this.getElementId(d);\n }.bind(this)).attr('transform', 'translate(0,' + initial_y + ')');\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function (d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) {\n x = -1000;\n }\n if (isNaN(y)) {\n y = -1000;\n }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var fill = function (d) {\n return this.resolveScalableParameter(this.layout.color, d);\n }.bind(this);\n var fill_opacity = function (d) {\n return this.resolveScalableParameter(this.layout.fill_opacity, d);\n }.bind(this);\n var shape = d3.svg.symbol().size(function (d) {\n return this.resolveScalableParameter(this.layout.point_size, d);\n }.bind(this)).type(function (d) {\n return this.resolveScalableParameter(this.layout.point_shape, d);\n }.bind(this));\n // Apply position and color, using a transition if necessary\n if (this.canTransition()) {\n selection.transition().duration(this.layout.transition.duration || 0).ease(this.layout.transition.ease || 'cubic-in-out').attr('transform', transform).attr('fill', fill).attr('fill-opacity', fill_opacity).attr('d', shape);\n } else {\n selection.attr('transform', transform).attr('fill', fill).attr('fill-opacity', fill_opacity).attr('d', shape);\n }\n // Remove old elements as needed\n selection.exit().remove();\n // Apply default event emitters to selection\n selection.on('click.event_emitter', function (element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n // Apply mouse behaviors\n this.applyBehaviors(selection);\n // Apply method to keep labels from overlapping each other\n if (this.layout.label) {\n this.flip_labels();\n this.seperate_iterations = 0;\n this.separate_labels();\n // Apply default event emitters to selection\n this.label_texts.on('click.event_emitter', function (element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n // Extend mouse behaviors to labels\n this.applyBehaviors(this.label_texts);\n }\n };\n // Method to set a passed element as the LD reference in the plot-level state\n this.makeLDReference = function (element) {\n var ref = null;\n if (typeof element == 'undefined') {\n throw new Error('makeLDReference requires one argument of any type');\n } else if (typeof element == 'object') {\n if (this.layout.id_field && typeof element[this.layout.id_field] != 'undefined') {\n ref = element[this.layout.id_field].toString();\n } else if (typeof element['id'] != 'undefined') {\n ref = element['id'].toString();\n } else {\n ref = element.toString();\n }\n } else {\n ref = element.toString();\n }\n this.parent_plot.applyState({ ldrefvar: ref });\n };\n return this;\n });\n /**\n * A scatter plot in which the x-axis represents categories, rather than individual positions.\n * For example, this can be used by PheWAS plots to show related groups. This plot allows the categories to be\n * determined dynamically when data is first loaded.\n *\n * @class LocusZoom.DataLayers.category_scatter\n * @augments LocusZoom.DataLayers.scatter\n */\n LocusZoom.DataLayers.extend('scatter', 'category_scatter', {\n /**\n * This plot layer makes certain assumptions about the data passed in. Transform the raw array of records from\n * the datasource to prepare it for plotting, as follows:\n * 1. The scatter plot assumes that all records are given in sequence (pre-grouped by `category_field`)\n * 2. It assumes that all records have an x coordinate for individual plotting\n * @private\n */\n _prepareData: function () {\n var xField = this.layout.x_axis.field || 'x';\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n // Sort the data so that things in the same category are adjacent (case-insensitive by specified field)\n var sourceData = this.data.sort(function (a, b) {\n var ak = a[category_field];\n var bk = b[category_field];\n var av = typeof ak === 'string' ? ak.toLowerCase() : ak;\n var bv = typeof bk === 'string' ? bk.toLowerCase() : bk;\n return av === bv ? 0 : av < bv ? -1 : 1;\n });\n sourceData.forEach(function (d, i) {\n // Implementation detail: Scatter plot requires specifying an x-axis value, and most datasources do not\n // specify plotting positions. If a point is missing this field, fill in a synthetic value.\n d[xField] = d[xField] || i;\n });\n return sourceData;\n },\n /**\n * Identify the unique categories on the plot, and update the layout with an appropriate color scheme.\n * Also identify the min and max x value associated with the category, which will be used to generate ticks\n * @private\n * @returns {Object.} Series of entries used to build category name ticks {category_name: [min_x, max_x]}\n */\n _generateCategoryBounds: function () {\n // TODO: API may return null values in category_field; should we add placeholder category label?\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n var xField = this.layout.x_axis.field || 'x';\n var uniqueCategories = {};\n this.data.forEach(function (item) {\n var category = item[category_field];\n var x = item[xField];\n var bounds = uniqueCategories[category] || [\n x,\n x\n ];\n uniqueCategories[category] = [\n Math.min(bounds[0], x),\n Math.max(bounds[1], x)\n ];\n });\n var categoryNames = Object.keys(uniqueCategories);\n this._setDynamicColorScheme(categoryNames);\n return uniqueCategories;\n },\n /**\n * This layer relies on defining its own category-based color scheme. Find the correct color config object to\n * be modified.\n * @param [from_source]\n * @returns {Object} A mutable reference to the layout configuration object\n * @private\n */\n _getColorScale: function (from_source) {\n from_source = from_source || this.layout;\n // If the layout does not use a supported coloring scheme, or is already complete, this method should do nothing\n // For legacy reasons, layouts can specify color as an object (only one way to set color), as opposed to the\n // preferred mechanism of array (multiple coloring options)\n var color_params = from_source.color || [];\n // Object or scalar, no other options allowed\n if (Array.isArray(color_params)) {\n color_params = color_params.find(function (item) {\n return item.scale_function === 'categorical_bin';\n });\n }\n if (!color_params || color_params.scale_function !== 'categorical_bin') {\n throw new Error('This layer requires that color options be provided as a `categorical_bin`');\n }\n return color_params;\n },\n /**\n * Automatically define a color scheme for the layer based on data returned from the server.\n * If part of the color scheme has been specified, it will fill in remaining missing information.\n *\n * There are three scenarios:\n * 1. The layout does not specify either category names or (color) values. Dynamically build both based on\n * the data and update the layout.\n * 2. The layout specifies colors, but not categories. Use that exact color information provided, and dynamically\n * determine what categories are present in the data. (cycle through the available colors, reusing if there\n * are a lot of categories)\n * 3. The layout specifies exactly what colors and categories to use (and they match the data!). This is useful to\n * specify an explicit mapping between color scheme and category names, when you want to be sure that the\n * plot matches a standard color scheme.\n * (If the layout specifies categories that do not match the data, the user specified categories will be ignored)\n *\n * This method will only act if the layout defines a `categorical_bin` scale function for coloring. It may be\n * overridden in a subclass to suit other types of coloring methods.\n *\n * @param {String[]} categoryNames\n * @private\n */\n _setDynamicColorScheme: function (categoryNames) {\n var colorParams = this._getColorScale(this.layout).parameters;\n var baseParams = this._getColorScale(this._base_layout).parameters;\n if (baseParams.categories.length && baseParams.values.length) {\n // If there are preset category/color combos, make sure that they apply to the actual dataset\n var parameters_categories_hash = {};\n baseParams.categories.forEach(function (category) {\n parameters_categories_hash[category] = 1;\n });\n if (categoryNames.every(function (name) {\n return parameters_categories_hash.hasOwnProperty(name);\n })) {\n // The layout doesn't have to specify categories in order, but make sure they are all there\n colorParams.categories = baseParams.categories;\n } else {\n colorParams.categories = categoryNames;\n }\n } else {\n colorParams.categories = categoryNames;\n }\n // Prefer user-specified colors if provided. Make sure that there are enough colors for all the categories.\n var colors;\n if (baseParams.values.length) {\n colors = baseParams.values;\n } else {\n var color_scale = categoryNames.length <= 10 ? d3.scale.category10 : d3.scale.category20;\n colors = color_scale().range();\n }\n while (colors.length < categoryNames.length) {\n colors = colors.concat(colors);\n }\n colors = colors.slice(0, categoryNames.length);\n // List of hex values, should be of same length as categories array\n colorParams.values = colors;\n },\n /**\n *\n * @param dimension\n * @param {Object} [config] Parameters that customize how ticks are calculated (not style)\n * @param {('left'|'center'|'right')} [config.position='left'] Align ticks with the center or edge of category\n * @returns {Array}\n */\n getTicks: function (dimension, config) {\n // Overrides parent method\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier');\n }\n var position = config.position || 'left';\n if ([\n 'left',\n 'center',\n 'right'\n ].indexOf(position) === -1) {\n throw new Error('Invalid tick position');\n }\n var categoryBounds = this._categories;\n if (!categoryBounds || !Object.keys(categoryBounds).length) {\n return [];\n }\n if (dimension === 'y') {\n return [];\n }\n if (dimension === 'x') {\n // If colors have been defined by this layer, use them to make tick colors match scatterplot point colors\n var colors = this._getColorScale(this.layout);\n var knownCategories = colors.parameters.categories || [];\n var knownColors = colors.parameters.values || [];\n return Object.keys(categoryBounds).map(function (category, index) {\n var bounds = categoryBounds[category];\n var xPos;\n switch (position) {\n case 'left':\n xPos = bounds[0];\n break;\n case 'center':\n // Center tick under one or many elements as appropriate\n var diff = bounds[1] - bounds[0];\n xPos = bounds[0] + (diff !== 0 ? diff : bounds[0]) / 2;\n break;\n case 'right':\n xPos = bounds[1];\n break;\n }\n return {\n x: xPos,\n text: category,\n style: { 'fill': knownColors[knownCategories.indexOf(category)] || '#000000' }\n };\n });\n }\n },\n applyCustomDataMethods: function () {\n this.data = this._prepareData();\n /**\n * Define category names and extents (boundaries) for plotting. TODO: properties in constructor\n * @member {Object.} Category names and extents, in the form {category_name: [min_x, max_x]}\n */\n this._categories = this._generateCategoryBounds();\n return this;\n }\n });\n /* global LocusZoom */\n 'use strict';\n /**\n *\n * LocusZoom has various singleton objects that are used for registering functions or classes.\n * These objects provide safe, standard methods to redefine or delete existing functions/classes\n * as well as define new custom functions/classes to be used in a plot.\n *\n * @namespace Singletons\n */\n /*\n * The Collection of \"Known\" Data Sources. This registry is used internally by the `DataSources` class\n * @class\n * @static\n */\n LocusZoom.KnownDataSources = function () {\n /** @lends LocusZoom.KnownDataSources */\n var obj = {};\n /* @member {function[]} */\n var sources = [];\n var findSourceByName = function (x) {\n for (var i = 0; i < sources.length; i++) {\n if (!sources[i].SOURCE_NAME) {\n throw new Error('KnownDataSources at position ' + i + ' does not have a \\'SOURCE_NAME\\' static property');\n }\n if (sources[i].SOURCE_NAME === x) {\n return sources[i];\n }\n }\n return null;\n };\n /**\n * Identify the datasource associated with a given name\n * @param {String} name\n * @returns {function} The constructor for the data source; will usually extend `Data.Source`\n */\n obj.get = function (name) {\n return findSourceByName(name);\n };\n /**\n * Register a data source constructor so that it may be located by name\n * @param {function} source A constructor function for a data source; will usually extend `Data.Source`,\n * and should have a `SOURCE_NAME` property\n */\n obj.add = function (source) {\n if (!source.SOURCE_NAME) {\n console.warn('Data source added does not have a SOURCE_NAME');\n }\n sources.push(source);\n };\n /**\n * Create a custom source type that extends the behavior of an existing source, and registers that\n * source by the provided name\n * @param {String} parent_name The name of a previously registered data source type to use as a template\n * @param {String} source_name The new name to use when registering this data source\n * @param {Object} overrides An object of additional properties and methods to add/override behavior\n * @returns {LocusZoom.Data.Source} The newly defined class for this source\n */\n obj.extend = function (parent_name, source_name, overrides) {\n var parent = findSourceByName(parent_name);\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered data source');\n }\n if (!source_name) {\n throw new Error('Must provide a name for the new data source');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n child.SOURCE_NAME = source_name;\n sources.push(child);\n return child;\n };\n /** @deprecated */\n obj.push = function (source) {\n console.warn('Warning: KnownDataSources.push() is deprecated. Use .add() instead');\n obj.add(source);\n };\n /**\n * List the names of all registered datasources\n * @returns {String[]}\n */\n obj.list = function () {\n return sources.map(function (x) {\n return x.SOURCE_NAME;\n });\n };\n /**\n * Create a datasource instance\n * @param {String} name The name of the desired datasource to instantiate (must be defined in the registry)\n * @returns {LocusZoom.Data.Source}\n */\n obj.create = function (name) {\n //create new object (pass additional parameters to constructor)\n var newObj = findSourceByName(name);\n if (newObj) {\n var params = arguments;\n params[0] = null;\n return new (Function.prototype.bind.apply(newObj, params))();\n } else {\n throw new Error('Unable to find data source for name: ' + name);\n }\n };\n /**\n * Get the array of all registered constructors\n * Generally only used for unit tests internally\n * @private\n * @returns {function[]}\n */\n obj.getAll = function () {\n return sources;\n };\n /**\n * Register an entire collection of data sources\n * Generally only used for unit tests internally\n * @private\n * @param {function[]} x An array of datasource constructors\n */\n obj.setAll = function (x) {\n sources = x;\n };\n /**\n * Unregister all known data sources\n * Generally only used for unit tests internally\n * @private\n */\n obj.clear = function () {\n sources = [];\n };\n return obj;\n }();\n /**************************\n * Transformation Functions\n *\n * Singleton for formatting or transforming a single input, for instance turning raw p values into negative log10 form\n * Transformation functions are chainable with a pipe on a field name, like so: \"pvalue|neglog10\"\n *\n * NOTE: Because these functions are chainable the FUNCTION is returned by get(), not the result of that function.\n *\n * All transformation functions must accept an object of parameters and a value to process.\n * @class\n */\n LocusZoom.TransformationFunctions = function () {\n /** @lends LocusZoom.TransformationFunctions */\n var obj = {};\n var transformations = {};\n var getTrans = function (name) {\n if (!name) {\n return null;\n }\n var fun = transformations[name];\n if (fun) {\n return fun;\n } else {\n throw new Error('transformation ' + name + ' not found');\n }\n };\n //a single transformation with any parameters\n //(parameters not currently supported)\n var parseTrans = function (name) {\n return getTrans(name);\n };\n //a \"raw\" transformation string with a leading pipe\n //and one or more transformations\n var parseTransString = function (x) {\n var funs = [];\n var re = /\\|([^|]+)/g;\n var result;\n while ((result = re.exec(x)) !== null) {\n funs.push(result[1]);\n }\n if (funs.length === 1) {\n return parseTrans(funs[0]);\n } else if (funs.length > 1) {\n return function (x) {\n var val = x;\n for (var i = 0; i < funs.length; i++) {\n val = parseTrans(funs[i])(val);\n }\n return val;\n };\n }\n return null;\n };\n /**\n * Retrieve a transformation function by name\n * @param {String} name The name of the transformation function to retrieve. May optionally be prefixed with a\n * pipe (`|`) when chaining multiple transformation functions.\n * @returns {function} The constructor for the transformation function\n */\n obj.get = function (name) {\n if (name && name.substring(0, 1) === '|') {\n return parseTransString(name);\n } else {\n return parseTrans(name);\n }\n };\n /**\n * Internal logic that registers a transformation function\n * @protected\n * @param {String} name\n * @param {function} fn\n */\n obj.set = function (name, fn) {\n if (name.substring(0, 1) === '|') {\n throw new Error('transformation name should not start with a pipe');\n } else {\n if (fn) {\n transformations[name] = fn;\n } else {\n delete transformations[name];\n }\n }\n };\n /**\n * Register a transformation function\n * @param {String} name\n * @param {function} fn A transformation function (should accept one argument with the value)\n */\n obj.add = function (name, fn) {\n if (transformations[name]) {\n throw new Error('transformation already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n /**\n * List the names of all registered transformation functions\n * @returns {String[]}\n */\n obj.list = function () {\n return Object.keys(transformations);\n };\n return obj;\n }();\n /**\n * Return the -log (base 10)\n * @function neglog10\n */\n LocusZoom.TransformationFunctions.add('neglog10', function (x) {\n if (isNaN(x) || x <= 0) {\n return null;\n }\n return -Math.log(x) / Math.LN10;\n });\n /**\n * Convert a number from logarithm to scientific notation. Useful for, eg, a datasource that returns -log(p) by default\n * @function logtoscinotation\n */\n LocusZoom.TransformationFunctions.add('logtoscinotation', function (x) {\n if (isNaN(x)) {\n return 'NaN';\n }\n if (x === 0) {\n return '1';\n }\n var exp = Math.ceil(x);\n var diff = exp - x;\n var base = Math.pow(10, diff);\n if (exp === 1) {\n return (base / 10).toFixed(4);\n } else if (exp === 2) {\n return (base / 100).toFixed(3);\n } else {\n return base.toFixed(2) + ' \\xD7 10^-' + exp;\n }\n });\n /**\n * Represent a number in scientific notation\n * @function scinotation\n * @param {Number} x\n * @returns {String}\n */\n LocusZoom.TransformationFunctions.add('scinotation', function (x) {\n if (isNaN(x)) {\n return 'NaN';\n }\n if (x === 0) {\n return '0';\n }\n var abs = Math.abs(x);\n var log;\n if (abs > 1) {\n log = Math.ceil(Math.log(abs) / Math.LN10);\n } else {\n // 0...1\n log = Math.floor(Math.log(abs) / Math.LN10);\n }\n if (Math.abs(log) <= 3) {\n return x.toFixed(3);\n } else {\n return x.toExponential(2).replace('+', '').replace('e', ' \\xD7 10^');\n }\n });\n /**\n * URL-encode the provided text, eg for constructing hyperlinks\n * @function urlencode\n * @param {String} str\n */\n LocusZoom.TransformationFunctions.add('urlencode', function (str) {\n return encodeURIComponent(str);\n });\n /**\n * HTML-escape user entered values for use in constructed HTML fragments\n *\n * For example, this filter can be used on tooltips with custom HTML display\n * @function htmlescape\n * @param {String} str HTML-escape the provided value\n */\n LocusZoom.TransformationFunctions.add('htmlescape', function (str) {\n if (!str) {\n return '';\n }\n str = str + '';\n return str.replace(/['\"<>&`]/g, function (s) {\n switch (s) {\n case '\\'':\n return ''';\n case '\"':\n return '"';\n case '<':\n return '<';\n case '>':\n return '>';\n case '&':\n return '&';\n case '`':\n return '`';\n }\n });\n });\n /**\n * Singleton for accessing/storing functions that will convert arbitrary data points to values in a given scale\n * Useful for anything that needs to scale discretely with data (e.g. color, point size, etc.)\n *\n * A Scale Function can be thought of as a modifier to a layout directive that adds extra logic to how a piece of data\n * can be resolved to a value.\n *\n * All scale functions must accept an object of parameters and a value to process.\n * @class\n * @static\n */\n LocusZoom.ScaleFunctions = function () {\n /** @lends LocusZoom.ScaleFunctions */\n var obj = {};\n var functions = {};\n /**\n * Find a scale function and return it. If parameters and values are passed, calls the function directly; otherwise\n * returns a callable.\n * @param {String} name\n * @param {Object} [parameters] Configuration parameters specific to the specified scale function\n * @param {*} [value] The value to operate on\n * @returns {*}\n */\n obj.get = function (name, parameters, value) {\n if (!name) {\n return null;\n } else if (functions[name]) {\n if (typeof parameters === 'undefined' && typeof value === 'undefined') {\n return functions[name];\n } else {\n return functions[name](parameters, value);\n }\n } else {\n throw new Error('scale function [' + name + '] not found');\n }\n };\n /**\n * @protected\n * @param {String} name The name of the function to set/unset\n * @param {Function} [fn] The function to register. If blank, removes this function name from the registry.\n */\n obj.set = function (name, fn) {\n if (fn) {\n functions[name] = fn;\n } else {\n delete functions[name];\n }\n };\n /**\n * Add a new scale function to the registry\n * @param {String} name The name of the scale function\n * @param {function} fn A scale function that accepts two parameters: an object of configuration and a value\n */\n obj.add = function (name, fn) {\n if (functions[name]) {\n throw new Error('scale function already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n /**\n * List the names of all registered scale functions\n * @returns {String[]}\n */\n obj.list = function () {\n return Object.keys(functions);\n };\n return obj;\n }();\n /**\n * Basic conditional function to evaluate the value of the input field and return based on equality.\n * @param {Object} parameters\n * @param {*} parameters.field_value The value against which to test the input value.\n * @param {*} parameters.then The value to return if the input value matches the field value\n * @param {*} parameters.else The value to return if the input value does not match the field value. Optional. If not\n * defined this scale function will return null (or value of null_value parameter, if defined) when input value fails\n * to match field_value.\n * @param {*} input value\n */\n LocusZoom.ScaleFunctions.add('if', function (parameters, input) {\n if (typeof input == 'undefined' || parameters.field_value !== input) {\n if (typeof parameters.else != 'undefined') {\n return parameters.else;\n } else {\n return null;\n }\n } else {\n return parameters.then;\n }\n });\n /**\n * Function to sort numerical values into bins based on numerical break points. Will only operate on numbers and\n * return null (or value of null_value parameter, if defined) if provided a non-numeric input value. Parameters:\n * @function numerical_bin\n * @param {Object} parameters\n * @param {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter. If the input value is greater than or equal to break n and less than\n * or equal to break n+1 (or break n+1 doesn't exist) then returned value is the nth entry in the values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against break points. Must be of\n * equal length to breaks parameter. Each entry n represents the value to return if the input value is greater than\n * or equal to break n and less than or equal to break n+1 (or break n+1 doesn't exist).\n * @param {*} null_value\n * @param {*} input value\n * @returns\n */\n LocusZoom.ScaleFunctions.add('numerical_bin', function (parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n if (typeof input == 'undefined' || input === null || isNaN(+input)) {\n return parameters.null_value ? parameters.null_value : null;\n }\n var threshold = breaks.reduce(function (prev, curr) {\n if (+input < prev || +input >= prev && +input < curr) {\n return prev;\n } else {\n return curr;\n }\n });\n return values[breaks.indexOf(threshold)];\n });\n /**\n * Function to sort values of any type into bins based on direct equality testing with a list of categories.\n * Will return null if provided an input value that does not match to a listed category.\n * @function categorical_bin\n * @param {Object} parameters\n * @param {Array} parameters.categories Array of values against which to evaluate the input value. Must be of equal\n * length to values parameter. If the input value is equal to category n then returned value is the nth entry in the\n * values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against categories. Must be of equal\n * length to categories parameter. Each entry n represents the value to return if the input value is equal to the nth\n * value in the categories parameter.\n * @param {*} parameters.null_value Value to return if the input value fails to match to any categories. Optional.\n */\n LocusZoom.ScaleFunctions.add('categorical_bin', function (parameters, value) {\n if (typeof value == 'undefined' || parameters.categories.indexOf(value) === -1) {\n return parameters.null_value ? parameters.null_value : null;\n } else {\n return parameters.values[parameters.categories.indexOf(value)];\n }\n });\n /**\n * Function for continuous interpolation of numerical values along a gradient with arbitrarily many break points.\n * @function interpolate\n * @parameters {Object} parameters\n * @parameters {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter and contain at least two elements. Input value will be evaluated for\n * relative position between two break points n and n+1 and the returned value will be interpolated at a relative\n * position between values n and n+1.\n * @parameters {*[]} parameters.values Array of values to interpolate and return given evaluations against break\n * points. Must be of equal length to breaks parameter and contain at least two elements. Each entry n represents\n * the value to return if the input value matches the nth entry in breaks exactly. Note that this scale function\n * uses d3.interpolate to provide for effective interpolation of many different value types, including numbers,\n * colors, shapes, etc.\n * @parameters {*} parameters.null_value\n */\n LocusZoom.ScaleFunctions.add('interpolate', function (parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n var nullval = parameters.null_value ? parameters.null_value : null;\n if (breaks.length < 2 || breaks.length !== values.length) {\n return nullval;\n }\n if (typeof input == 'undefined' || input === null || isNaN(+input)) {\n return nullval;\n }\n if (+input <= parameters.breaks[0]) {\n return values[0];\n } else if (+input >= parameters.breaks[parameters.breaks.length - 1]) {\n return values[breaks.length - 1];\n } else {\n var upper_idx = null;\n breaks.forEach(function (brk, idx) {\n if (!idx) {\n return;\n }\n if (breaks[idx - 1] <= +input && breaks[idx] >= +input) {\n upper_idx = idx;\n }\n });\n if (upper_idx === null) {\n return nullval;\n }\n var normalized_input = (+input - breaks[upper_idx - 1]) / (breaks[upper_idx] - breaks[upper_idx - 1]);\n if (!isFinite(normalized_input)) {\n return nullval;\n }\n return d3.interpolate(values[upper_idx - 1], values[upper_idx])(normalized_input);\n }\n });\n /* global LocusZoom */\n 'use strict';\n /**\n * A Dashboard is an HTML element used for presenting arbitrary user interface components. Dashboards are anchored\n * to either the entire Plot or to individual Panels.\n *\n * Each dashboard is an HTML-based (read: not SVG) collection of components used to display information or provide\n * user interface. Dashboards can exist on entire plots, where their visibility is permanent and vertically adjacent\n * to the plot, or on individual panels, where their visibility is tied to a behavior (e.g. a mouseover) and is as\n * an overlay.\n * @class\n */\n LocusZoom.Dashboard = function (parent) {\n // parent must be a locuszoom plot or panel\n if (!(parent instanceof LocusZoom.Plot) && !(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create dashboard, parent must be a locuszoom plot or panel');\n }\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.dashboard';\n /** @member {('plot'|'panel')} */\n this.type = this.parent instanceof LocusZoom.Plot ? 'plot' : 'panel';\n /** @member {LocusZoom.Plot} */\n this.parent_plot = this.type === 'plot' ? this.parent : this.parent.parent;\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {LocusZoom.Dashboard.Component[]} */\n this.components = [];\n /**\n * The timer identifier as returned by setTimeout\n * @member {Number}\n */\n this.hide_timeout = null;\n /**\n * Whether to hide the dashboard. Can be overridden by a child component. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n // TODO: Return value from constructor function?\n return this.initialize();\n };\n /**\n * Prepare the dashboard for first use: generate all component instances for this dashboard, based on the provided\n * layout of the parent. Connects event listeners and shows/hides as appropriate.\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.initialize = function () {\n // Parse layout to generate component instances\n if (Array.isArray(this.parent.layout.dashboard.components)) {\n this.parent.layout.dashboard.components.forEach(function (layout) {\n try {\n var component = LocusZoom.Dashboard.Components.get(layout.type, layout, this);\n this.components.push(component);\n } catch (e) {\n console.warn(e);\n }\n }.bind(this));\n }\n // Add mouseover event handlers to show/hide panel dashboard\n if (this.type === 'panel') {\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseover.' + this.id, function () {\n clearTimeout(this.hide_timeout);\n if (!this.selector || this.selector.style('visibility') === 'hidden') {\n this.show();\n }\n }.bind(this));\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseout.' + this.id, function () {\n clearTimeout(this.hide_timeout);\n this.hide_timeout = setTimeout(function () {\n this.hide();\n }.bind(this), 300);\n }.bind(this));\n }\n return this;\n };\n /**\n * Whether to persist the dashboard. Returns true if at least one component should persist, or if the panel is engaged\n * in an active drag event.\n * @returns {boolean}\n */\n LocusZoom.Dashboard.prototype.shouldPersist = function () {\n if (this.persist) {\n return true;\n }\n var persist = false;\n // Persist if at least one component should also persist\n this.components.forEach(function (component) {\n persist = persist || component.shouldPersist();\n });\n // Persist if in a parent drag event\n persist = persist || (this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.dragging);\n return !!persist;\n };\n /**\n * Make the dashboard appear. If it doesn't exist yet create it, including creating/positioning all components within,\n * and make sure it is set to be visible.\n */\n LocusZoom.Dashboard.prototype.show = function () {\n if (!this.selector) {\n switch (this.type) {\n case 'plot':\n this.selector = d3.select(this.parent.svg.node().parentNode).insert('div', ':first-child');\n break;\n case 'panel':\n this.selector = d3.select(this.parent.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip, .lz-dashboard-menu, .lz-curtain').classed('lz-panel-dashboard', true);\n break;\n }\n this.selector.classed('lz-dashboard', true).classed('lz-' + this.type + '-dashboard', true).attr('id', this.id);\n }\n this.components.forEach(function (component) {\n component.show();\n });\n this.selector.style({ visibility: 'visible' });\n return this.update();\n };\n /**\n * Update the dashboard and rerender all child components. This can be called whenever plot state changes.\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.update = function () {\n if (!this.selector) {\n return this;\n }\n this.components.forEach(function (component) {\n component.update();\n });\n return this.position();\n };\n /**\n * Position the dashboard (and child components) within the panel\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.position = function () {\n if (!this.selector) {\n return this;\n }\n // Position the dashboard itself (panel only)\n if (this.type === 'panel') {\n var page_origin = this.parent.getPageOrigin();\n var top = (page_origin.y + 3.5).toString() + 'px';\n var left = page_origin.x.toString() + 'px';\n var width = (this.parent.layout.width - 4).toString() + 'px';\n this.selector.style({\n position: 'absolute',\n top: top,\n left: left,\n width: width\n });\n }\n // Recursively position components\n this.components.forEach(function (component) {\n component.position();\n });\n return this;\n };\n /**\n * Hide the dashboard (make invisible but do not destroy). Will do nothing if `shouldPersist` returns true.\n *\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.hide = function () {\n if (!this.selector || this.shouldPersist()) {\n return this;\n }\n this.components.forEach(function (component) {\n component.hide();\n });\n this.selector.style({ visibility: 'hidden' });\n return this;\n };\n /**\n * Completely remove dashboard and all child components. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.prototype.destroy = function (force) {\n if (typeof force == 'undefined') {\n force = false;\n }\n if (!this.selector) {\n return this;\n }\n if (this.shouldPersist() && !force) {\n return this;\n }\n this.components.forEach(function (component) {\n component.destroy(true);\n });\n this.components = [];\n this.selector.remove();\n this.selector = null;\n return this;\n };\n /**\n *\n * A dashboard component is an empty div rendered on a dashboard that can display custom\n * html of user interface elements. LocusZoom.Dashboard.Components is a singleton used to\n * define and manage an extendable collection of dashboard components.\n * (e.g. by LocusZoom.Dashboard.Components.add())\n * @class\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @param {('left'|'right')} [layout.position='left'] Whether to float the component left or right.\n * @param {('start'|'middle'|'end')} [layout.group_position] Buttons can optionally be gathered into a visually\n * distinctive group whose elements are closer together. If a button is identified as the start or end of a group,\n * it will be drawn with rounded corners and an extra margin of spacing from any button not part of the group.\n * For example, the region_nav_plot dashboard is a defined as a group.\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple'} [layout.color='gray'] Color scheme for the\n * component. Applies to buttons and menus.\n * @param {LocusZoom.Dashboard} parent The dashboard that contains this component\n*/\n LocusZoom.Dashboard.Component = function (layout, parent) {\n /** @member {Object} */\n this.layout = layout || {};\n if (!this.layout.color) {\n this.layout.color = 'gray';\n }\n /** @member {LocusZoom.Dashboard|*} */\n this.parent = parent || null;\n /**\n * Some dashboards are attached to a panel, rather than directly to a plot\n * @member {LocusZoom.Panel|null}\n */\n this.parent_panel = null;\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n /**\n * This is a reference to either the panel or the plot, depending on what the dashboard is\n * tied to. Useful when absolutely positioning dashboard components relative to their SVG anchor.\n * @member {LocusZoom.Plot|LocusZoom.Panel}\n */\n this.parent_svg = null;\n if (this.parent instanceof LocusZoom.Dashboard) {\n // TODO: when is the immediate parent *not* a dashboard?\n if (this.parent.type === 'panel') {\n this.parent_panel = this.parent.parent;\n this.parent_plot = this.parent.parent.parent;\n this.parent_svg = this.parent_panel;\n } else {\n this.parent_plot = this.parent.parent;\n this.parent_svg = this.parent_plot;\n }\n }\n /** @member {d3.selection} */\n this.selector = null;\n /**\n * If this is an interactive component, it will contain a button or menu instance that handles the interactivity.\n * There is a 1-to-1 relationship of dashboard component to button\n * @member {null|LocusZoom.Dashboard.Component.Button}\n */\n this.button = null;\n /**\n * If any single component is marked persistent, it will bubble up to prevent automatic hide behavior on a\n * component's parent dashboard. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n if (!this.layout.position) {\n this.layout.position = 'left';\n }\n // TODO: Return value in constructor\n return this;\n };\n /**\n * Perform all rendering of component, including toggling visibility to true. Will initialize and create SVG element\n * if necessary, as well as updating with new data and performing layout actions.\n */\n LocusZoom.Dashboard.Component.prototype.show = function () {\n if (!this.parent || !this.parent.selector) {\n return;\n }\n if (!this.selector) {\n var group_position = [\n 'start',\n 'middle',\n 'end'\n ].indexOf(this.layout.group_position) !== -1 ? ' lz-dashboard-group-' + this.layout.group_position : '';\n this.selector = this.parent.selector.append('div').attr('class', 'lz-dashboard-' + this.layout.position + group_position);\n if (this.layout.style) {\n this.selector.style(this.layout.style);\n }\n if (typeof this.initialize == 'function') {\n this.initialize();\n }\n }\n if (this.button && this.button.status === 'highlighted') {\n this.button.menu.show();\n }\n this.selector.style({ visibility: 'visible' });\n this.update();\n return this.position();\n };\n /**\n * Update the dashboard component with any new data or plot state as appropriate. This method performs all\n * necessary rendering steps.\n */\n LocusZoom.Dashboard.Component.prototype.update = function () {\n };\n /**\n * Place the component correctly in the plot\n * @returns {LocusZoom.Dashboard.Component}\n */\n LocusZoom.Dashboard.Component.prototype.position = function () {\n if (this.button) {\n this.button.menu.position();\n }\n return this;\n };\n /**\n * Determine whether the component should persist (will bubble up to parent dashboard)\n * @returns {boolean}\n */\n LocusZoom.Dashboard.Component.prototype.shouldPersist = function () {\n if (this.persist) {\n return true;\n }\n if (this.button && this.button.persist) {\n return true;\n }\n return false;\n };\n /**\n * Toggle visibility to hidden, unless marked as persistent\n * @returns {LocusZoom.Dashboard.Component}\n */\n LocusZoom.Dashboard.Component.prototype.hide = function () {\n if (!this.selector || this.shouldPersist()) {\n return this;\n }\n if (this.button) {\n this.button.menu.hide();\n }\n this.selector.style({ visibility: 'hidden' });\n return this;\n };\n /**\n * Completely remove component and button. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\n LocusZoom.Dashboard.Component.prototype.destroy = function (force) {\n if (typeof force == 'undefined') {\n force = false;\n }\n if (!this.selector) {\n return this;\n }\n if (this.shouldPersist() && !force) {\n return this;\n }\n if (this.button && this.button.menu) {\n this.button.menu.destroy();\n }\n this.selector.remove();\n this.selector = null;\n this.button = null;\n return this;\n };\n /**\n * Singleton registry of all known components\n * @class\n * @static\n */\n LocusZoom.Dashboard.Components = function () {\n /** @lends LocusZoom.Dashboard.Components */\n var obj = {};\n var components = {};\n /**\n * Create a new component instance by name\n * @param {String} name The string identifier of the desired component\n * @param {Object} layout The layout to use to create the component\n * @param {LocusZoom.Dashboard} parent The containing dashboard to use when creating the component\n * @returns {LocusZoom.Dashboard.Component}\n */\n obj.get = function (name, layout, parent) {\n if (!name) {\n return null;\n } else if (components[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for dashboard component [' + name + ']');\n } else {\n return new components[name](layout, parent);\n }\n } else {\n throw new Error('dashboard component [' + name + '] not found');\n }\n };\n /**\n * Add a new component constructor to the registry and ensure that it extends the correct parent class\n * @protected\n * @param name\n * @param component\n */\n obj.set = function (name, component) {\n if (component) {\n if (typeof component != 'function') {\n throw new Error('unable to set dashboard component [' + name + '], argument provided is not a function');\n } else {\n components[name] = component;\n components[name].prototype = new LocusZoom.Dashboard.Component();\n }\n } else {\n delete components[name];\n }\n };\n /**\n * Register a new component constructor by name\n * @param {String} name\n * @param {function} component The component constructor\n */\n obj.add = function (name, component) {\n if (components[name]) {\n throw new Error('dashboard component already exists with name: ' + name);\n } else {\n obj.set(name, component);\n }\n };\n /**\n * List the names of all registered components\n * @returns {String[]}\n */\n obj.list = function () {\n return Object.keys(components);\n };\n return obj;\n }();\n /**\n * Plots and panels may have a \"dashboard\" element suited for showing HTML components that may be interactive.\n * When components need to incorporate a generic button, or additionally a button that generates a menu, this\n * class provides much of the necessary framework.\n * @class\n * @param {LocusZoom.Dashboard.Component} parent\n */\n LocusZoom.Dashboard.Component.Button = function (parent) {\n if (!(parent instanceof LocusZoom.Dashboard.Component)) {\n throw new Error('Unable to create dashboard component button, invalid parent');\n }\n /** @member {LocusZoom.Dashboard.Component} */\n this.parent = parent;\n /** @member {LocusZoom.Dashboard.Panel} */\n this.parent_panel = this.parent.parent_panel;\n /** @member {LocusZoom.Dashboard.Plot} */\n this.parent_plot = this.parent.parent_plot;\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent_svg = this.parent.parent_svg;\n /** @member {LocusZoom.Dashboard|null|*} */\n this.parent_dashboard = this.parent.parent;\n /** @member {d3.selection} */\n this.selector = null;\n /**\n * Tag to use for the button (default: a)\n * @member {String}\n */\n this.tag = 'a';\n /**\n * TODO This method does not appear to be used anywhere\n * @param {String} tag\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTag = function (tag) {\n if (typeof tag != 'undefined') {\n this.tag = tag.toString();\n }\n return this;\n };\n /**\n * HTML for the button to show.\n * @protected\n * @member {String}\n */\n this.html = '';\n /**\n * Specify the HTML content of this button.\n * WARNING: The string provided will be inserted into the document as raw markup; XSS mitigation is the\n * responsibility of each button implementation.\n * @param {String} html\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setHtml = function (html) {\n if (typeof html != 'undefined') {\n this.html = html.toString();\n }\n return this;\n };\n /**\n * @deprecated since 0.5.6; use setHtml instead\n */\n this.setText = this.setHtml;\n /**\n * Mouseover title text for the button to show\n * @protected\n * @member {String}\n */\n this.title = '';\n /**\n * Set the mouseover title text for the button (if any)\n * @param {String} title Simple text to display\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTitle = function (title) {\n if (typeof title != 'undefined') {\n this.title = title.toString();\n }\n return this;\n };\n /**\n * Color of the button\n * @member {String}\n */\n this.color = 'gray';\n /**\n * Set the color associated with this button\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple')} color Any selection not in the preset list\n * will be replaced with gray.\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setColor = function (color) {\n if (typeof color != 'undefined') {\n if ([\n 'gray',\n 'red',\n 'orange',\n 'yellow',\n 'green',\n 'blue',\n 'purple'\n ].indexOf(color) !== -1) {\n this.color = color;\n } else {\n this.color = 'gray';\n }\n }\n return this;\n };\n /**\n * Hash of arbitrary button styles to apply as {name: value} entries\n * @protected\n * @member {Object}\n */\n this.style = {};\n /**\n * Set a collection of custom styles to be used by the button\n * @param {Object} style Hash of {name:value} entries\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setStyle = function (style) {\n if (typeof style != 'undefined') {\n this.style = style;\n }\n return this;\n };\n //\n /**\n * Method to generate a CSS class string\n * @returns {string}\n */\n this.getClass = function () {\n var group_position = [\n 'start',\n 'middle',\n 'end'\n ].indexOf(this.parent.layout.group_position) !== -1 ? ' lz-dashboard-button-group-' + this.parent.layout.group_position : '';\n return 'lz-dashboard-button lz-dashboard-button-' + this.color + (this.status ? '-' + this.status : '') + group_position;\n };\n // Permanence\n /**\n * Track internal state on whether to keep showing the button/ menu contents at the moment\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n /**\n * Configuration when defining a button: track whether this component should be allowed to keep open\n * menu/button contents in response to certain events\n * @protected\n * @member {Boolean}\n */\n this.permanent = false;\n /**\n * Allow code to change whether the button is allowed to be `permanent`\n * @param {boolean} bool\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setPermanent = function (bool) {\n if (typeof bool == 'undefined') {\n bool = true;\n } else {\n bool = Boolean(bool);\n }\n this.permanent = bool;\n if (this.permanent) {\n this.persist = true;\n }\n return this;\n };\n /**\n * Determine whether the button/menu contents should persist in response to a specific event\n * @returns {Boolean}\n */\n this.shouldPersist = function () {\n return this.permanent || this.persist;\n };\n /**\n * Button status (highlighted / disabled/ etc)\n * @protected\n * @member {String}\n */\n this.status = '';\n /**\n * Change button state\n * @param {('highlighted'|'disabled'|'')} status\n */\n this.setStatus = function (status) {\n if (typeof status != 'undefined' && [\n '',\n 'highlighted',\n 'disabled'\n ].indexOf(status) !== -1) {\n this.status = status;\n }\n return this.update();\n };\n /**\n * Toggle whether the button is highlighted\n * @param {boolean} bool If provided, explicitly set highlighted state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.highlight = function (bool) {\n if (typeof bool == 'undefined') {\n bool = true;\n } else {\n bool = Boolean(bool);\n }\n if (bool) {\n return this.setStatus('highlighted');\n } else if (this.status === 'highlighted') {\n return this.setStatus('');\n }\n return this;\n };\n /**\n * Toggle whether the button is disabled\n * @param {boolean} bool If provided, explicitly set disabled state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.disable = function (bool) {\n if (typeof bool == 'undefined') {\n bool = true;\n } else {\n bool = Boolean(bool);\n }\n if (bool) {\n return this.setStatus('disabled');\n } else if (this.status === 'disabled') {\n return this.setStatus('');\n }\n return this;\n };\n // Mouse events\n /** @member {function} */\n this.onmouseover = function () {\n };\n this.setOnMouseover = function (onmouseover) {\n if (typeof onmouseover == 'function') {\n this.onmouseover = onmouseover;\n } else {\n this.onmouseover = function () {\n };\n }\n return this;\n };\n /** @member {function} */\n this.onmouseout = function () {\n };\n this.setOnMouseout = function (onmouseout) {\n if (typeof onmouseout == 'function') {\n this.onmouseout = onmouseout;\n } else {\n this.onmouseout = function () {\n };\n }\n return this;\n };\n /** @member {function} */\n this.onclick = function () {\n };\n this.setOnclick = function (onclick) {\n if (typeof onclick == 'function') {\n this.onclick = onclick;\n } else {\n this.onclick = function () {\n };\n }\n return this;\n };\n // Primary behavior functions\n /**\n * Show the button, including creating DOM elements if necessary for first render\n */\n this.show = function () {\n if (!this.parent) {\n return;\n }\n if (!this.selector) {\n this.selector = this.parent.selector.append(this.tag).attr('class', this.getClass());\n }\n return this.update();\n };\n /**\n * Hook for any actions or state cleanup to be performed before rerendering\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.preUpdate = function () {\n return this;\n };\n /**\n * Update button state and contents, and fully rerender\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.update = function () {\n if (!this.selector) {\n return this;\n }\n this.preUpdate();\n this.selector.attr('class', this.getClass()).attr('title', this.title).style(this.style).on('mouseover', this.status === 'disabled' ? null : this.onmouseover).on('mouseout', this.status === 'disabled' ? null : this.onmouseout).on('click', this.status === 'disabled' ? null : this.onclick).html(this.html);\n this.menu.update();\n this.postUpdate();\n return this;\n };\n /**\n * Hook for any behavior to be added/changed after the button has been re-rendered\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.postUpdate = function () {\n return this;\n };\n /**\n * Hide the button by removing it from the DOM (may be overridden by current persistence setting)\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.hide = function () {\n if (this.selector && !this.shouldPersist()) {\n this.selector.remove();\n this.selector = null;\n }\n return this;\n };\n /**\n * Button Menu Object\n * The menu is an HTML overlay that can appear below a button. It can contain arbitrary HTML and\n * has logic to be automatically positioned and sized to behave more or less like a dropdown menu.\n * @member {Object}\n */\n this.menu = {\n outer_selector: null,\n inner_selector: null,\n scroll_position: 0,\n hidden: true,\n /**\n * Show the button menu, including setting up any DOM elements needed for first rendering\n */\n show: function () {\n if (!this.menu.outer_selector) {\n this.menu.outer_selector = d3.select(this.parent_plot.svg.node().parentNode).append('div').attr('class', 'lz-dashboard-menu lz-dashboard-menu-' + this.color).attr('id', this.parent_svg.getBaseId() + '.dashboard.menu');\n this.menu.inner_selector = this.menu.outer_selector.append('div').attr('class', 'lz-dashboard-menu-content');\n this.menu.inner_selector.on('scroll', function () {\n this.menu.scroll_position = this.menu.inner_selector.node().scrollTop;\n }.bind(this));\n }\n this.menu.outer_selector.style({ visibility: 'visible' });\n this.menu.hidden = false;\n return this.menu.update();\n }.bind(this),\n /**\n * Update the rendering of the menu\n */\n update: function () {\n if (!this.menu.outer_selector) {\n return this.menu;\n }\n this.menu.populate();\n // This function is stubbed for all buttons by default and custom implemented in component definition\n if (this.menu.inner_selector) {\n this.menu.inner_selector.node().scrollTop = this.menu.scroll_position;\n }\n return this.menu.position();\n }.bind(this),\n position: function () {\n if (!this.menu.outer_selector) {\n return this.menu;\n }\n // Unset any explicitly defined outer selector height so that menus dynamically shrink if content is removed\n this.menu.outer_selector.style({ height: null });\n var padding = 3;\n var scrollbar_padding = 20;\n var menu_height_padding = 14;\n // 14: 2x 6px padding, 2x 1px border\n var page_origin = this.parent_svg.getPageOrigin();\n var page_scroll_top = document.documentElement.scrollTop || document.body.scrollTop;\n var container_offset = this.parent_plot.getContainerOffset();\n var dashboard_client_rect = this.parent_dashboard.selector.node().getBoundingClientRect();\n var button_client_rect = this.selector.node().getBoundingClientRect();\n var menu_client_rect = this.menu.outer_selector.node().getBoundingClientRect();\n var total_content_height = this.menu.inner_selector.node().scrollHeight;\n var top = 0;\n var left = 0;\n if (this.parent_dashboard.type === 'panel') {\n top = page_origin.y + dashboard_client_rect.height + 2 * padding;\n left = Math.max(page_origin.x + this.parent_svg.layout.width - menu_client_rect.width - padding, page_origin.x + padding);\n } else {\n top = button_client_rect.bottom + page_scroll_top + padding - container_offset.top;\n left = Math.max(button_client_rect.left + button_client_rect.width - menu_client_rect.width - container_offset.left, page_origin.x + padding);\n }\n var base_max_width = Math.max(this.parent_svg.layout.width - 2 * padding - scrollbar_padding, scrollbar_padding);\n var container_max_width = base_max_width;\n var content_max_width = base_max_width - 4 * padding;\n var base_max_height = Math.max(this.parent_svg.layout.height - 10 * padding - menu_height_padding, menu_height_padding);\n var height = Math.min(total_content_height, base_max_height);\n var max_height = base_max_height;\n this.menu.outer_selector.style({\n 'top': top.toString() + 'px',\n 'left': left.toString() + 'px',\n 'max-width': container_max_width.toString() + 'px',\n 'max-height': max_height.toString() + 'px',\n 'height': height.toString() + 'px'\n });\n this.menu.inner_selector.style({ 'max-width': content_max_width.toString() + 'px' });\n this.menu.inner_selector.node().scrollTop = this.menu.scroll_position;\n return this.menu;\n }.bind(this),\n hide: function () {\n if (!this.menu.outer_selector) {\n return this.menu;\n }\n this.menu.outer_selector.style({ visibility: 'hidden' });\n this.menu.hidden = true;\n return this.menu;\n }.bind(this),\n destroy: function () {\n if (!this.menu.outer_selector) {\n return this.menu;\n }\n this.menu.inner_selector.remove();\n this.menu.outer_selector.remove();\n this.menu.inner_selector = null;\n this.menu.outer_selector = null;\n return this.menu;\n }.bind(this),\n /**\n * Internal method definition\n * By convention populate() does nothing and should be reimplemented with each dashboard button definition\n * Reimplement by way of Dashboard.Component.Button.menu.setPopulate to define the populate method and hook\n * up standard menu click-toggle behavior prototype.\n * @protected\n */\n populate: function () {\n }.bind(this),\n /**\n * Define how the menu is populated with items, and set up click and display properties as appropriate\n * @public\n */\n setPopulate: function (menu_populate_function) {\n if (typeof menu_populate_function == 'function') {\n this.menu.populate = menu_populate_function;\n this.setOnclick(function () {\n if (this.menu.hidden) {\n this.menu.show();\n this.highlight().update();\n this.persist = true;\n } else {\n this.menu.hide();\n this.highlight(false).update();\n if (!this.permanent) {\n this.persist = false;\n }\n }\n }.bind(this));\n } else {\n this.setOnclick();\n }\n return this;\n }.bind(this)\n };\n };\n /**\n * Renders arbitrary text with title formatting\n * @class LocusZoom.Dashboard.Components.title\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.title Text to render\n */\n LocusZoom.Dashboard.Components.add('title', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.show = function () {\n if (!this.div_selector) {\n this.div_selector = this.parent.selector.append('div').attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position);\n this.title_selector = this.div_selector.append('h3');\n }\n return this.update();\n };\n this.update = function () {\n var title = layout.title.toString();\n if (this.layout.subtitle) {\n title += ' ' + this.layout.subtitle + '';\n }\n this.title_selector.html(title);\n return this;\n };\n });\n /**\n * Renders text to display the current dimensions of the plot. Automatically updated as plot dimensions change\n * @class LocusZoom.Dashboard.Components.dimensions\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('dimensions', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n var display_width = this.parent_plot.layout.width.toString().indexOf('.') === -1 ? this.parent_plot.layout.width : this.parent_plot.layout.width.toFixed(2);\n var display_height = this.parent_plot.layout.height.toString().indexOf('.') === -1 ? this.parent_plot.layout.height : this.parent_plot.layout.height.toFixed(2);\n this.selector.html(display_width + 'px \\xD7 ' + display_height + 'px');\n if (layout.class) {\n this.selector.attr('class', layout.class);\n }\n if (layout.style) {\n this.selector.style(layout.style);\n }\n return this;\n };\n });\n /**\n * Display the current scale of the genome region displayed in the plot, as defined by the difference between\n * `state.end` and `state.start`.\n * @class LocusZoom.Dashboard.Components.region_scale\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('region_scale', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (!isNaN(this.parent_plot.state.start) && !isNaN(this.parent_plot.state.end) && this.parent_plot.state.start !== null && this.parent_plot.state.end !== null) {\n this.selector.style('display', null);\n this.selector.html(LocusZoom.positionIntToString(this.parent_plot.state.end - this.parent_plot.state.start, null, true));\n } else {\n this.selector.style('display', 'none');\n }\n if (layout.class) {\n this.selector.attr('class', layout.class);\n }\n if (layout.style) {\n this.selector.style(layout.style);\n }\n return this;\n };\n });\n /**\n * Button to export current plot to an SVG image\n * @class LocusZoom.Dashboard.Components.download\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Download Image\"]\n * @param {string} [layout.button_title=\"Download image of the current plot as locuszoom.svg\"]\n * @param {string} [layout.filename=\"locuszoom.svg\"] The default filename to use when saving the image\n */\n LocusZoom.Dashboard.Components.add('download', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html || 'Download Image').setTitle(layout.button_title || 'Download image of the current plot as locuszoom.svg').setOnMouseover(function () {\n this.button.selector.classed('lz-dashboard-button-gray-disabled', true).html('Preparing Image');\n this.generateBase64SVG().then(function (url) {\n var old = this.button.selector.attr('href');\n if (old) {\n URL.revokeObjectURL(old);\n }\n // Clean up old url instance to prevent memory leaks\n this.button.selector.attr('href', url).classed('lz-dashboard-button-gray-disabled', false).classed('lz-dashboard-button-gray-highlighted', true).html(layout.button_html || 'Download Image');\n }.bind(this));\n }.bind(this)).setOnMouseout(function () {\n this.button.selector.classed('lz-dashboard-button-gray-highlighted', false);\n }.bind(this));\n this.button.show();\n this.button.selector.attr('href-lang', 'image/svg+xml').attr('download', layout.filename || 'locuszoom.svg');\n return this;\n };\n this.css_string = '';\n for (var stylesheet in Object.keys(document.styleSheets)) {\n if (document.styleSheets[stylesheet].href !== null && document.styleSheets[stylesheet].href.indexOf('locuszoom.css') !== -1) {\n // TODO: \"Download image\" button will render the image incorrectly if the stylesheet has been renamed or concatenated\n LocusZoom.createCORSPromise('GET', document.styleSheets[stylesheet].href).then(function (response) {\n this.css_string = response.replace(/[\\r\\n]/g, ' ').replace(/\\s+/g, ' ');\n if (this.css_string.indexOf('/* ! LocusZoom HTML Styles */')) {\n this.css_string = this.css_string.substring(0, this.css_string.indexOf('/* ! LocusZoom HTML Styles */'));\n }\n }.bind(this));\n break;\n }\n }\n this.generateBase64SVG = function () {\n return new Promise(function (resolve, reject) {\n // Insert a hidden div, clone the node into that so we can modify it with d3\n var container = this.parent.selector.append('div').style('display', 'none').html(this.parent_plot.svg.node().outerHTML);\n // Remove unnecessary elements\n container.selectAll('g.lz-curtain').remove();\n container.selectAll('g.lz-mouse_guide').remove();\n // Convert units on axis tick dy attributes from ems to pixels\n container.selectAll('g.tick text').each(function () {\n var dy = +d3.select(this).attr('dy').substring(-2).slice(0, -2) * 10;\n d3.select(this).attr('dy', dy);\n });\n // Pull the svg into a string and add the contents of the locuszoom stylesheet\n // Don't add this with d3 because it will escape the CDATA declaration incorrectly\n var initial_html = d3.select(container.select('svg').node().parentNode).html();\n var style_def = '';\n var insert_at = initial_html.indexOf('>') + 1;\n initial_html = initial_html.slice(0, insert_at) + style_def + initial_html.slice(insert_at);\n // Delete the container node\n container.remove();\n // Create an object URL based on the rendered markup\n var content = new Blob([initial_html], { type: 'image/svg+xml' });\n resolve(URL.createObjectURL(content));\n }.bind(this));\n };\n });\n /**\n * Button to remove panel from plot.\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.remove_panel\n * @augments LocusZoom.Dashboard.Component\n * @param {Boolean} [layout.suppress_confirm=false] If true, removes the panel without prompting user for confirmation\n */\n LocusZoom.Dashboard.Components.add('remove_panel', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml('\\xD7').setTitle('Remove panel').setOnclick(function () {\n if (!layout.suppress_confirm && !confirm('Are you sure you want to remove this panel? This cannot be undone!')) {\n return false;\n }\n var panel = this.parent_panel;\n panel.dashboard.hide(true);\n d3.select(panel.parent.svg.node().parentNode).on('mouseover.' + panel.getBaseId() + '.dashboard', null);\n d3.select(panel.parent.svg.node().parentNode).on('mouseout.' + panel.getBaseId() + '.dashboard', null);\n return panel.parent.removePanel(panel.id);\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Button to move panel up relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_up\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('move_panel_up', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n var is_at_top = this.parent_panel.layout.y_index === 0;\n this.button.disable(is_at_top);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml('\\u25B4').setTitle('Move panel up').setOnclick(function () {\n this.parent_panel.moveUp();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n });\n /**\n * Button to move panel down relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_down\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('move_panel_down', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n var is_at_bottom = this.parent_panel.layout.y_index === this.parent_plot.panel_ids_by_y_index.length - 1;\n this.button.disable(is_at_bottom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml('\\u25BE').setTitle('Move panel down').setOnclick(function () {\n this.parent_panel.moveDown();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n });\n /**\n * Button to shift plot region forwards or back by a `step` increment provided in the layout\n * @class LocusZoom.Dashboard.Components.shift_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=50000] The stepsize to change the region by\n * @param {string} [layout.button_html]\n * @param {string} [layout.button_title]\n */\n LocusZoom.Dashboard.Components.add('shift_region', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function () {\n };\n console.warn('Unable to add shift_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) {\n layout.step = 50000;\n }\n if (typeof layout.button_html !== 'string') {\n layout.button_html = layout.step > 0 ? '>' : '<';\n }\n if (typeof layout.button_title !== 'string') {\n layout.button_title = 'Shift region by ' + (layout.step > 0 ? '+' : '-') + LocusZoom.positionIntToString(Math.abs(layout.step), null, true);\n }\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start + layout.step, 1),\n end: this.parent_plot.state.end + layout.step\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Zoom in or out on the plot, centered on the middle of the plot region, by the specified amount\n * @class LocusZoom.Dashboard.Components.zoom_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=0.2] The amount to zoom in by (where 1 indicates 100%)\n */\n LocusZoom.Dashboard.Components.add('zoom_region', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function () {\n };\n console.warn('Unable to add zoom_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) {\n layout.step = 0.2;\n }\n if (typeof layout.button_html != 'string') {\n layout.button_html = layout.step > 0 ? 'z\\u2013' : 'z+';\n }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Zoom region ' + (layout.step > 0 ? 'out' : 'in') + ' by ' + (Math.abs(layout.step) * 100).toFixed(1) + '%';\n }\n this.update = function () {\n if (this.button) {\n var can_zoom = true;\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n if (layout.step > 0 && !isNaN(this.parent_plot.layout.max_region_scale) && current_region_scale >= this.parent_plot.layout.max_region_scale) {\n can_zoom = false;\n }\n if (layout.step < 0 && !isNaN(this.parent_plot.layout.min_region_scale) && current_region_scale <= this.parent_plot.layout.min_region_scale) {\n can_zoom = false;\n }\n this.button.disable(!can_zoom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n var zoom_factor = 1 + layout.step;\n var new_region_scale = current_region_scale * zoom_factor;\n if (!isNaN(this.parent_plot.layout.max_region_scale)) {\n new_region_scale = Math.min(new_region_scale, this.parent_plot.layout.max_region_scale);\n }\n if (!isNaN(this.parent_plot.layout.min_region_scale)) {\n new_region_scale = Math.max(new_region_scale, this.parent_plot.layout.min_region_scale);\n }\n var delta = Math.floor((new_region_scale - current_region_scale) / 2);\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start - delta, 1),\n end: this.parent_plot.state.end + delta\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Renders button with arbitrary text that, when clicked, shows a dropdown containing arbitrary HTML\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @class LocusZoom.Dashboard.Components.menu\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n * @param {string} layout.menu_html The HTML content of the dropdown menu\n */\n LocusZoom.Dashboard.Components.add('menu', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title);\n this.button.menu.setPopulate(function () {\n this.button.menu.inner_selector.html(layout.menu_html);\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Special button/menu to allow model building by tracking individual covariants. Will track a list of covariate\n * objects and store them in the special `model.covariates` field of plot `state`.\n * @class LocusZoom.Dashboard.Components.covariates_model\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n */\n LocusZoom.Dashboard.Components.add('covariates_model', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.initialize = function () {\n // Initialize state.model.covariates\n this.parent_plot.state.model = this.parent_plot.state.model || {};\n this.parent_plot.state.model.covariates = this.parent_plot.state.model.covariates || [];\n // Create an object at the plot level for easy access to interface methods in custom client-side JS\n /**\n * When a covariates model dashboard element is present, create (one) object at the plot level that exposes\n * component data and state for custom interactions with other plot elements.\n * @class LocusZoom.Plot.CovariatesModel\n */\n this.parent_plot.CovariatesModel = {\n /** @member {LocusZoom.Dashboard.Component.Button} */\n button: this,\n /**\n * Add an element to the model and show a representation of it in the dashboard component menu. If the\n * element is already part of the model, do nothing (to avoid adding duplicates).\n * When plot state is changed, this will automatically trigger requests for new data accordingly.\n * @param {string|object} element_reference Can be any value that can be put through JSON.stringify()\n * to create a serialized representation of itself.\n */\n add: function (element_reference) {\n var element = JSON.parse(JSON.stringify(element_reference));\n if (typeof element_reference == 'object' && typeof element.html != 'string') {\n element.html = typeof element_reference.toHTML == 'function' ? element_reference.toHTML() : element_reference.toString();\n }\n // Check if the element is already in the model covariates array and return if it is.\n for (var i = 0; i < this.state.model.covariates.length; i++) {\n if (JSON.stringify(this.state.model.covariates[i]) === JSON.stringify(element)) {\n return this;\n }\n }\n this.state.model.covariates.push(element);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Remove an element from `state.model.covariates` (and from the dashboard component menu's\n * representation of the state model). When plot state is changed, this will automatically trigger\n * requests for new data accordingly.\n * @param {number} idx Array index of the element, in the `state.model.covariates array`.\n */\n removeByIdx: function (idx) {\n if (typeof this.state.model.covariates[idx] == 'undefined') {\n throw new Error('Unable to remove model covariate, invalid index: ' + idx.toString());\n }\n this.state.model.covariates.splice(idx, 1);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Empty the `state.model.covariates` array (and dashboard component menu representation thereof) of all\n * elements. When plot state is changed, this will automatically trigger requests for new data accordingly\n */\n removeAll: function () {\n this.state.model.covariates = [];\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Manually trigger the update methods on the dashboard component's button and menu elements to force\n * display of most up-to-date content. Can be used to force the dashboard to reflect changes made, eg if\n * modifying `state.model.covariates` directly instead of via `plot.CovariatesModel`\n */\n updateComponent: function () {\n this.button.update();\n this.button.menu.update();\n }.bind(this)\n };\n }.bind(this);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n this.button.menu.populate();\n }.bind(this));\n this.button.menu.setPopulate(function () {\n var selector = this.button.menu.inner_selector;\n selector.html('');\n // General model HTML representation\n if (typeof this.parent_plot.state.model.html != 'undefined') {\n selector.append('div').html(this.parent_plot.state.model.html);\n }\n // Model covariates table\n if (!this.parent_plot.state.model.covariates.length) {\n selector.append('i').html('no covariates in model');\n } else {\n selector.append('h5').html('Model Covariates (' + this.parent_plot.state.model.covariates.length + ')');\n var table = selector.append('table');\n this.parent_plot.state.model.covariates.forEach(function (covariate, idx) {\n var html = typeof covariate == 'object' && typeof covariate.html == 'string' ? covariate.html : covariate.toString();\n var row = table.append('tr');\n row.append('td').append('button').attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color).style({ 'margin-left': '0em' }).on('click', function () {\n this.parent_plot.CovariatesModel.removeByIdx(idx);\n }.bind(this)).html('\\xD7');\n row.append('td').html(html);\n }.bind(this));\n selector.append('button').attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color).style({ 'margin-left': '4px' }).html('\\xD7 Remove All Covariates').on('click', function () {\n this.parent_plot.CovariatesModel.removeAll();\n }.bind(this));\n }\n }.bind(this));\n this.button.preUpdate = function () {\n var html = 'Model';\n if (this.parent_plot.state.model.covariates.length) {\n var cov = this.parent_plot.state.model.covariates.length > 1 ? 'covariates' : 'covariate';\n html += ' (' + this.parent_plot.state.model.covariates.length + ' ' + cov + ')';\n }\n this.button.setHtml(html).disable(false);\n }.bind(this);\n this.button.show();\n return this;\n };\n });\n /**\n * Button to toggle split tracks\n * @class LocusZoom.Dashboard.Components.toggle_split_tracks\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('toggle_split_tracks', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (!layout.data_layer_id) {\n layout.data_layer_id = 'intervals';\n }\n if (!this.parent_panel.data_layers[layout.data_layer_id]) {\n throw new Error('Dashboard toggle split tracks component missing valid data layer ID');\n }\n this.update = function () {\n var data_layer = this.parent_panel.data_layers[layout.data_layer_id];\n var html = data_layer.layout.split_tracks ? 'Merge Tracks' : 'Split Tracks';\n if (this.button) {\n this.button.setHtml(html);\n this.button.show();\n this.parent.position();\n return this;\n } else {\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(html).setTitle('Toggle whether tracks are split apart or merged together').setOnclick(function () {\n data_layer.toggleSplitTracks();\n if (this.scale_timeout) {\n clearTimeout(this.scale_timeout);\n }\n var timeout = data_layer.layout.transition ? +data_layer.layout.transition.duration || 0 : 0;\n this.scale_timeout = setTimeout(function () {\n this.parent_panel.scaleHeightToData();\n this.parent_plot.positionPanels();\n }.bind(this), timeout);\n this.update();\n }.bind(this));\n return this.update();\n }\n };\n });\n /**\n * Button to resize panel height to fit available data (eg when showing a list of tracks)\n * @class LocusZoom.Dashboard.Components.resize_to_data\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Resize to Data\"]\n * @param {string} [layout.button_title]\n */\n LocusZoom.Dashboard.Components.add('resize_to_data', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html || 'Resize to Data').setTitle(layout.button_title || 'Automatically resize this panel to show all data available').setOnclick(function () {\n this.parent_panel.scaleHeightToData();\n this.update();\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Button to toggle legend\n * @class LocusZoom.Dashboard.Components.toggle_legend\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('toggle_legend', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n var html = this.parent_panel.legend.layout.hidden ? 'Show Legend' : 'Hide Legend';\n if (this.button) {\n this.button.setHtml(html).show();\n this.parent.position();\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setTitle('Show or hide the legend for this panel').setOnclick(function () {\n this.parent_panel.legend.layout.hidden = !this.parent_panel.legend.layout.hidden;\n this.parent_panel.legend.render();\n this.update();\n }.bind(this));\n return this.update();\n };\n });\n /**\n * Menu for manipulating multiple data layers in a single panel: show/hide, change order, etc.\n * @class LocusZoom.Dashboard.Components.data_layers\n * @augments LocusZoom.Dashboard.Component\n */\n LocusZoom.Dashboard.Components.add('data_layers', function (layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function () {\n if (typeof layout.button_html != 'string') {\n layout.button_html = 'Data Layers';\n }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Manipulate Data Layers (sort, dim, show/hide, etc.)';\n }\n if (this.button) {\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n this.button.menu.populate();\n }.bind(this));\n this.button.menu.setPopulate(function () {\n this.button.menu.inner_selector.html('');\n var table = this.button.menu.inner_selector.append('table');\n this.parent_panel.data_layer_ids_by_z_index.slice().reverse().forEach(function (id, idx) {\n var data_layer = this.parent_panel.data_layers[id];\n var name = typeof data_layer.layout.name != 'string' ? data_layer.id : data_layer.layout.name;\n var row = table.append('tr');\n // Layer name\n row.append('td').html(name);\n // Status toggle buttons\n layout.statuses.forEach(function (status_adj) {\n var status_idx = LocusZoom.DataLayer.Statuses.adjectives.indexOf(status_adj);\n var status_verb = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n var html, onclick, highlight;\n if (data_layer.global_statuses[status_adj]) {\n html = LocusZoom.DataLayer.Statuses.menu_antiverbs[status_idx];\n onclick = 'un' + status_verb + 'AllElements';\n highlight = '-highlighted';\n } else {\n html = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n onclick = status_verb + 'AllElements';\n highlight = '';\n }\n row.append('td').append('a').attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color + highlight).style({ 'margin-left': '0em' }).on('click', function () {\n data_layer[onclick]();\n this.button.menu.populate();\n }.bind(this)).html(html);\n }.bind(this));\n // Sort layer buttons\n var at_top = idx === 0;\n var at_bottom = idx === this.parent_panel.data_layer_ids_by_z_index.length - 1;\n var td = row.append('td');\n td.append('a').attr('class', 'lz-dashboard-button lz-dashboard-button-group-start lz-dashboard-button-' + this.layout.color + (at_bottom ? '-disabled' : '')).style({ 'margin-left': '0em' }).on('click', function () {\n data_layer.moveDown();\n this.button.menu.populate();\n }.bind(this)).html('\\u25BE').attr('title', 'Move layer down (further back)');\n td.append('a').attr('class', 'lz-dashboard-button lz-dashboard-button-group-middle lz-dashboard-button-' + this.layout.color + (at_top ? '-disabled' : '')).style({ 'margin-left': '0em' }).on('click', function () {\n data_layer.moveUp();\n this.button.menu.populate();\n }.bind(this)).html('\\u25B4').attr('title', 'Move layer up (further front)');\n td.append('a').attr('class', 'lz-dashboard-button lz-dashboard-button-group-end lz-dashboard-button-red').style({ 'margin-left': '0em' }).on('click', function () {\n if (confirm('Are you sure you want to remove the ' + name + ' layer? This cannot be undone!')) {\n data_layer.parent.removeDataLayer(id);\n }\n return this.button.menu.populate();\n }.bind(this)).html('\\xD7').attr('title', 'Remove layer');\n }.bind(this));\n return this;\n }.bind(this));\n this.button.show();\n return this;\n };\n });\n /**\n * Dropdown menu allowing the user to choose between different display options for a single specific data layer\n * within a panel.\n *\n * This allows controlling how points on a datalayer can be displayed- any display options supported via the layout for the target datalayer. This includes point\n * size/shape, coloring, etc.\n *\n * This button intentionally limits display options it can control to those available on common plot types.\n * Although the list of options it sets can be overridden (to control very special custom plot types), this\n * capability should be used sparingly if at all.\n *\n * @class LocusZoom.Dashboard.Components.display_options\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Display options...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Control how plot items are displayed\"] Hover text for the toolbar button\n * @param {string} layout.layer_name Specify the datalayer that this button should affect\n * @param {string} [layout.default_config_display_name] Store the default configuration for this datalayer\n * configuration, and show a button to revert to the \"default\" (listing the human-readable display name provided)\n * @param {Array} [layout.fields_whitelist='see code'] The list of presentation fields that this button can control.\n * This can be overridden if this button needs to be used on a custom layer type with special options.\n * @typedef {{display_name: string, display: Object}} DisplayOptionsButtonConfigField\n * @param {DisplayOptionsButtonConfigField[]} layout.options Specify a label and set of layout directives associated\n * with this `display` option. Display field should include all changes to datalayer presentation options.\n */\n LocusZoom.Dashboard.Components.add('display_options', function (layout) {\n if (typeof layout.button_html != 'string') {\n layout.button_html = 'Display options...';\n }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Control how plot items are displayed';\n }\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n // List of layout fields that this button is allowed to control. This ensures that we don't override any other\n // information (like plot height etc) while changing point rendering\n var allowed_fields = layout.fields_whitelist || [\n 'color',\n 'fill_opacity',\n 'label',\n 'legend',\n 'point_shape',\n 'point_size',\n 'tooltip',\n 'tooltip_positioning'\n ];\n var dataLayer = this.parent_panel.data_layers[layout.layer_name];\n if (!dataLayer) {\n throw new Error('Display options could not locate the specified layer_name: \\'' + layout.layer_name + '\\'');\n }\n var dataLayerLayout = dataLayer.layout;\n // Store default configuration for the layer as a clean deep copy, so we may revert later\n var defaultConfig = {};\n allowed_fields.forEach(function (name) {\n var configSlot = dataLayerLayout[name];\n if (configSlot !== undefined) {\n defaultConfig[name] = JSON.parse(JSON.stringify(configSlot));\n }\n });\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n this._selected_item = 'default';\n // Define the button + menu that provides the real functionality for this dashboard component\n var self = this;\n this.button = new LocusZoom.Dashboard.Component.Button(self).setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title).setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 10000).toString();\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n var menuLayout = self.layout;\n var renderRow = function (display_name, display_options, row_id) {\n // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td').append('input').attr({\n id: radioId,\n type: 'radio',\n name: 'display-option-' + uniqueID,\n value: row_id\n }).style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n.property('checked', row_id === self._selected_item).on('click', function () {\n // If an option is not specified in these display options, use the original defaults\n allowed_fields.forEach(function (field_name) {\n dataLayer.layout[field_name] = display_options[field_name] || defaultConfig[field_name];\n });\n self._selected_item = row_id;\n self.parent_panel.render();\n var legend = self.parent_panel.legend;\n if (legend) {\n legend.render();\n }\n });\n row.append('td').append('label').style('font-weight', 'normal').attr('for', radioId).text(display_name);\n };\n // Render the \"display options\" menu: default and special custom options\n var defaultName = menuLayout.default_config_display_name || 'Default style';\n renderRow(defaultName, defaultConfig, 'default');\n menuLayout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.display, index);\n });\n return self;\n });\n this.update = function () {\n this.button.show();\n return this;\n };\n });\n /**\n * Dropdown menu allowing the user to set the value of a specific `state_field` in plot.state\n * This is useful for things (like datasources) that allow dynamic configuration based on global information in state\n *\n * For example, the LDLZ2 data source can use it to change LD reference population (for all panels) after render\n *\n * @class LocusZoom.Dashboard.Components.set_state\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Set option...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Choose an option to customize the plot\"] Hover text for the toolbar button\n * @param {bool} [layout.show_selected=false] Whether to append the selected value to the button label\n * @param {string} [layout.state_field] The name of the field in plot.state that will be set by this button\n * @typedef {{display_name: string, value: *}} SetStateOptionsConfigField\n * @param {SetStateOptionsConfigField[]} layout.options Specify human labels and associated values for the dropdown menu\n */\n LocusZoom.Dashboard.Components.add('set_state', function (layout) {\n var self = this;\n if (typeof layout.button_html != 'string') {\n layout.button_html = 'Set option...';\n }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Choose an option to customize the plot';\n }\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (this.parent_panel) {\n throw new Error('This widget is designed to set global options, so it can only be used at the top (plot) level');\n }\n if (!layout.state_field) {\n throw new Error('Must specify the `state_field` that this widget controls');\n }\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n // The first option listed is automatically assumed to be the default, unless a value exists in plot.state\n this._selected_item = this.parent_plot.state[layout.state_field] || layout.options[0].value;\n if (!layout.options.find(function (item) {\n return item.value === self._selected_item;\n })) {\n // Check only gets run at widget creation, but generally this widget is assumed to be an exclusive list of options\n throw new Error('There is an existing state value that does not match the known values in this widget');\n }\n // Define the button + menu that provides the real functionality for this dashboard component\n this.button = new LocusZoom.Dashboard.Component.Button(self).setColor(layout.color).setHtml(layout.button_html + (layout.show_selected ? this._selected_item : '')).setTitle(layout.button_title).setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 10000).toString();\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n var renderRow = function (display_name, value, row_id) {\n // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td').append('input').attr({\n id: radioId,\n type: 'radio',\n name: 'set-state-' + uniqueID,\n value: row_id\n }).style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n.property('checked', value === self._selected_item).on('click', function () {\n var new_state = {};\n new_state[layout.state_field] = value;\n self._selected_item = value;\n self.parent_plot.applyState(new_state);\n self.button.setHtml(layout.button_html + (layout.show_selected ? self._selected_item : ''));\n });\n row.append('td').append('label').style('font-weight', 'normal').attr('for', radioId).text(display_name);\n };\n layout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.value, index);\n });\n return self;\n });\n this.update = function () {\n this.button.show();\n return this;\n };\n });\n /* global LocusZoom */\n 'use strict';\n /**\n * An SVG object used to display contextual information about a panel.\n * Panel layouts determine basic features of a legend - its position in the panel, orientation, title, etc.\n * Layouts of child data layers of the panel determine the actual content of the legend.\n *\n * @class\n * @param {LocusZoom.Panel} parent\n*/\n LocusZoom.Legend = function (parent) {\n if (!(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create legend, parent must be a locuszoom panel');\n }\n /** @member {LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.legend';\n this.parent.layout.legend = LocusZoom.Layouts.merge(this.parent.layout.legend || {}, LocusZoom.Legend.DefaultLayout);\n /** @member {Object} */\n this.layout = this.parent.layout.legend;\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {d3.selection} */\n this.background_rect = null;\n /** @member {d3.selection[]} */\n this.elements = [];\n /**\n * SVG selector for the group containing all elements in the legend\n * @protected\n * @member {d3.selection|null}\n */\n this.elements_group = null;\n /**\n * TODO: Not sure if this property is used; the external-facing methods are setting `layout.hidden` instead. Tentatively mark deprecated.\n * @deprecated\n * @protected\n * @member {Boolean}\n */\n this.hidden = false;\n // TODO Revisit constructor return value; see https://stackoverflow.com/a/3350364/1422268\n return this.render();\n };\n /**\n * The default layout used by legends (used internally)\n * @protected\n * @member {Object}\n */\n LocusZoom.Legend.DefaultLayout = {\n orientation: 'vertical',\n origin: {\n x: 0,\n y: 0\n },\n width: 10,\n height: 10,\n padding: 5,\n label_size: 12,\n hidden: false\n };\n /**\n * Render the legend in the parent panel\n */\n LocusZoom.Legend.prototype.render = function () {\n // Get a legend group selector if not yet defined\n if (!this.selector) {\n this.selector = this.parent.svg.group.append('g').attr('id', this.parent.getBaseId() + '.legend').attr('class', 'lz-legend');\n }\n // Get a legend background rect selector if not yet defined\n if (!this.background_rect) {\n this.background_rect = this.selector.append('rect').attr('width', 100).attr('height', 100).attr('class', 'lz-legend-background');\n }\n // Get a legend elements group selector if not yet defined\n if (!this.elements_group) {\n this.elements_group = this.selector.append('g');\n }\n // Remove all elements from the document and re-render from scratch\n this.elements.forEach(function (element) {\n element.remove();\n });\n this.elements = [];\n // Gather all elements from data layers in order (top to bottom) and render them\n var padding = +this.layout.padding || 1;\n var x = padding;\n var y = padding;\n var line_height = 0;\n this.parent.data_layer_ids_by_z_index.slice().reverse().forEach(function (id) {\n if (Array.isArray(this.parent.data_layers[id].layout.legend)) {\n this.parent.data_layers[id].layout.legend.forEach(function (element) {\n var selector = this.elements_group.append('g').attr('transform', 'translate(' + x + ',' + y + ')');\n var label_size = +element.label_size || +this.layout.label_size || 12;\n var label_x = 0;\n var label_y = label_size / 2 + padding / 2;\n line_height = Math.max(line_height, label_size + padding);\n // Draw the legend element symbol (line, rect, shape, etc)\n if (element.shape === 'line') {\n // Line symbol\n var length = +element.length || 16;\n var path_y = label_size / 4 + padding / 2;\n selector.append('path').attr('class', element.class || '').attr('d', 'M0,' + path_y + 'L' + length + ',' + path_y).style(element.style || {});\n label_x = length + padding;\n } else if (element.shape === 'rect') {\n // Rect symbol\n var width = +element.width || 16;\n var height = +element.height || width;\n selector.append('rect').attr('class', element.class || '').attr('width', width).attr('height', height).attr('fill', element.color || {}).style(element.style || {});\n label_x = width + padding;\n line_height = Math.max(line_height, height + padding);\n } else if (d3.svg.symbolTypes.indexOf(element.shape) !== -1) {\n // Shape symbol (circle, diamond, etc.)\n var size = +element.size || 40;\n var radius = Math.ceil(Math.sqrt(size / Math.PI));\n selector.append('path').attr('class', element.class || '').attr('d', d3.svg.symbol().size(size).type(element.shape)).attr('transform', 'translate(' + radius + ',' + (radius + padding / 2) + ')').attr('fill', element.color || {}).style(element.style || {});\n label_x = 2 * radius + padding;\n label_y = Math.max(2 * radius + padding / 2, label_y);\n line_height = Math.max(line_height, 2 * radius + padding);\n }\n // Draw the legend element label\n selector.append('text').attr('text-anchor', 'left').attr('class', 'lz-label').attr('x', label_x).attr('y', label_y).style({ 'font-size': label_size }).text(element.label);\n // Position the legend element group based on legend layout orientation\n var bcr = selector.node().getBoundingClientRect();\n if (this.layout.orientation === 'vertical') {\n y += bcr.height + padding;\n line_height = 0;\n } else {\n // Ensure this element does not exceed the panel width\n // (E.g. drop to the next line if it does, but only if it's not the only element on this line)\n var right_x = this.layout.origin.x + x + bcr.width;\n if (x > padding && right_x > this.parent.layout.width) {\n y += line_height;\n x = padding;\n selector.attr('transform', 'translate(' + x + ',' + y + ')');\n }\n x += bcr.width + 3 * padding;\n }\n // Store the element\n this.elements.push(selector);\n }.bind(this));\n }\n }.bind(this));\n // Scale the background rect to the elements in the legend\n var bcr = this.elements_group.node().getBoundingClientRect();\n this.layout.width = bcr.width + 2 * this.layout.padding;\n this.layout.height = bcr.height + 2 * this.layout.padding;\n this.background_rect.attr('width', this.layout.width).attr('height', this.layout.height);\n // Set the visibility on the legend from the \"hidden\" flag\n // TODO: `show()` and `hide()` call a full rerender; might be able to make this more lightweight?\n this.selector.style({ visibility: this.layout.hidden ? 'hidden' : 'visible' });\n // TODO: Annotate return type and make consistent\n return this.position();\n };\n /**\n * Place the legend in position relative to the panel, as specified in the layout configuration\n * @returns {LocusZoom.Legend | null}\n * TODO: should this always be chainable?\n */\n LocusZoom.Legend.prototype.position = function () {\n if (!this.selector) {\n return this;\n }\n var bcr = this.selector.node().getBoundingClientRect();\n if (!isNaN(+this.layout.pad_from_bottom)) {\n this.layout.origin.y = this.parent.layout.height - bcr.height - +this.layout.pad_from_bottom;\n }\n if (!isNaN(+this.layout.pad_from_right)) {\n this.layout.origin.x = this.parent.layout.width - bcr.width - +this.layout.pad_from_right;\n }\n this.selector.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n };\n /**\n * Hide the legend (triggers a re-render)\n * @public\n */\n LocusZoom.Legend.prototype.hide = function () {\n this.layout.hidden = true;\n this.render();\n };\n /**\n * Show the legend (triggers a re-render)\n * @public\n */\n LocusZoom.Legend.prototype.show = function () {\n this.layout.hidden = false;\n this.render();\n };\n /* global LocusZoom */\n 'use strict';\n function validateBuildSource(class_name, build, source) {\n // Build OR Source, not both\n if (build && source || !(build || source)) {\n throw new Error(class_name + ' must provide a parameter specifying either \"build\" or \"source\". It should not specify both.');\n }\n // If the build isn't recognized, our APIs can't transparently select a source to match\n if (build && [\n 'GRCh37',\n 'GRCh38'\n ].indexOf(build) === -1) {\n throw new Error(class_name + ' must specify a valid genome build number');\n }\n }\n /**\n * LocusZoom functionality used for data parsing and retrieval\n * @namespace\n * @public\n */\n LocusZoom.Data = LocusZoom.Data || {};\n /**\n * Create and coordinate an ensemble of (namespaced) data source instances\n * @public\n * @class\n */\n LocusZoom.DataSources = function () {\n /** @member {Object.} */\n this.sources = {};\n };\n /** @deprecated */\n LocusZoom.DataSources.prototype.addSource = function (ns, x) {\n console.warn('Warning: .addSource() is deprecated. Use .add() instead');\n return this.add(ns, x);\n };\n /**\n * Add a (namespaced) datasource to the plot\n * @public\n * @param {String} ns A namespace used for fields from this data source\n * @param {LocusZoom.Data.Source|Array|null} x An instantiated datasource, or an array of arguments that can be used to\n * create a known datasource type.\n */\n LocusZoom.DataSources.prototype.add = function (ns, x) {\n // FIXME: Some existing sites create sources with arbitrary names. This leads to subtle breakage\n // of namespaced fields in layouts. To avoid breaking existing usages outright, issue a deprecation warning.\n if (ns.match(/[^A-Za-z0-9_]/)) {\n console.warn('Deprecation warning: source name \\'' + ns + '\\' should contain only alphanumeric characters or underscores. Use of other characters may break layouts, and will be disallowed in the future.');\n }\n return this.set(ns, x);\n };\n /** @protected */\n LocusZoom.DataSources.prototype.set = function (ns, x) {\n if (Array.isArray(x)) {\n // If passed array of source name and options, make the source\n var dsobj = LocusZoom.KnownDataSources.create.apply(null, x);\n // Each datasource in the chain should be aware of its assigned namespace\n dsobj.source_id = ns;\n this.sources[ns] = dsobj;\n } else {\n // If passed the already-created source object\n if (x !== null) {\n x.source_id = ns;\n this.sources[ns] = x;\n } else {\n delete this.sources[ns];\n }\n }\n return this;\n };\n /** @deprecated */\n LocusZoom.DataSources.prototype.getSource = function (ns) {\n console.warn('Warning: .getSource() is deprecated. Use .get() instead');\n return this.get(ns);\n };\n /**\n * Return the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n * @returns {LocusZoom.Data.Source}\n */\n LocusZoom.DataSources.prototype.get = function (ns) {\n return this.sources[ns];\n };\n /** @deprecated */\n LocusZoom.DataSources.prototype.removeSource = function (ns) {\n console.warn('Warning: .removeSource() is deprecated. Use .remove() instead');\n return this.remove(ns);\n };\n /**\n * Remove the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n */\n LocusZoom.DataSources.prototype.remove = function (ns) {\n return this.set(ns, null);\n };\n /**\n * Populate a list of datasources specified as a JSON object\n * @public\n * @param {String|Object} x An object or JSON representation containing {ns: configArray} entries\n * @returns {LocusZoom.DataSources}\n */\n LocusZoom.DataSources.prototype.fromJSON = function (x) {\n if (typeof x === 'string') {\n x = JSON.parse(x);\n }\n var ds = this;\n Object.keys(x).forEach(function (ns) {\n ds.set(ns, x[ns]);\n });\n return ds;\n };\n /**\n * Return the names of all currently recognized datasources\n * @public\n * @returns {Array}\n */\n LocusZoom.DataSources.prototype.keys = function () {\n return Object.keys(this.sources);\n };\n /**\n * Datasources can be instantiated from a JSON object instead of code. This represents existing sources in that format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n * @public\n */\n LocusZoom.DataSources.prototype.toJSON = function () {\n return this.sources;\n };\n /**\n * Represents an addressable unit of data from a namespaced datasource, subject to specified value transformations.\n *\n * When used by a data layer, fields will automatically be re-fetched from the appropriate data source whenever the\n * state of a plot fetches, eg pan or zoom operations that would affect what data is displayed.\n *\n * @public\n * @class\n * @param {String} field A string representing the namespace of the datasource, the name of the desired field to fetch\n * from that datasource, and arbitrarily many transformations to apply to the value. The namespace and\n * transformation(s) are optional and information is delimited according to the general syntax\n * `[namespace:]name[|transformation][|transformation]`. For example, `association:pvalue|neglog10`\n */\n LocusZoom.Data.Field = function (field) {\n var parts = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/.exec(field);\n /** @member {String} */\n this.full_name = field;\n /** @member {String} */\n this.namespace = parts[1] || null;\n /** @member {String} */\n this.name = parts[2] || null;\n /** @member {Array} */\n this.transformations = [];\n if (typeof parts[3] == 'string' && parts[3].length > 1) {\n this.transformations = parts[3].substring(1).split('|');\n this.transformations.forEach(function (transform, i) {\n this.transformations[i] = LocusZoom.TransformationFunctions.get(transform);\n }.bind(this));\n }\n this.applyTransformations = function (val) {\n this.transformations.forEach(function (transform) {\n val = transform(val);\n });\n return val;\n };\n // Resolve the field for a given data element.\n // First look for a full match with transformations already applied by the data requester.\n // Otherwise prefer a namespace match and fall back to just a name match, applying transformations on the fly.\n this.resolve = function (d) {\n if (typeof d[this.full_name] == 'undefined') {\n var val = null;\n if (typeof d[this.namespace + ':' + this.name] != 'undefined') {\n val = d[this.namespace + ':' + this.name];\n } else if (typeof d[this.name] != 'undefined') {\n val = d[this.name];\n }\n d[this.full_name] = this.applyTransformations(val);\n }\n return d[this.full_name];\n };\n };\n /**\n * The Requester manages fetching of data across multiple data sources. It is used internally by LocusZoom data layers.\n * It passes state information and ensures that data is formatted in the manner expected by the plot.\n *\n * It is also responsible for constructing a \"chain\" of dependent requests, by requesting each datasource\n * sequentially in the order specified in the datalayer `fields` array. Data sources are only chained within a\n * data layer, and only if that layer requests more than one kind of data source.\n * @param {LocusZoom.DataSources} sources An object of {ns: LocusZoom.Data.Source} instances\n * @class\n */\n LocusZoom.Data.Requester = function (sources) {\n function split_requests(fields) {\n // Given a fields array, return an object specifying what datasource names the data layer should make requests\n // to, and how to handle the returned data\n var requests = {};\n // Regular expression finds namespace:field|trans\n var re = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/;\n fields.forEach(function (raw) {\n var parts = re.exec(raw);\n var ns = parts[1] || 'base';\n var field = parts[2];\n var trans = LocusZoom.TransformationFunctions.get(parts[3]);\n if (typeof requests[ns] == 'undefined') {\n requests[ns] = {\n outnames: [],\n fields: [],\n trans: []\n };\n }\n requests[ns].outnames.push(raw);\n requests[ns].fields.push(field);\n requests[ns].trans.push(trans);\n });\n return requests;\n }\n /**\n * Fetch data, and create a chain that only connects two data sources if they depend on each other\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields The list of data fields specified in the `layout` for a specific data layer\n * @returns {Promise}\n */\n this.getData = function (state, fields) {\n var requests = split_requests(fields);\n // Create an array of functions that, when called, will trigger the request to the specified datasource\n var request_handles = Object.keys(requests).map(function (key) {\n if (!sources.get(key)) {\n throw new Error('Datasource for namespace ' + key + ' not found');\n }\n return sources.get(key).getData(state, requests[key].fields, requests[key].outnames, requests[key].trans);\n });\n //assume the fields are requested in dependent order\n //TODO: better manage dependencies\n var ret = Promise.resolve({\n header: {},\n body: [],\n discrete: {}\n });\n for (var i = 0; i < request_handles.length; i++) {\n // If a single datalayer uses multiple sources, perform the next request when the previous one completes\n ret = ret.then(request_handles[i]);\n }\n return ret;\n };\n };\n /**\n * Base class for LocusZoom data sources\n * This can be extended with .extend() to create custom data sources\n * @class\n * @public\n */\n LocusZoom.Data.Source = function () {\n /**\n * Whether this source should enable caching\n * @member {Boolean}\n */\n this.enableCache = true;\n /**\n * Whether this data source type is dependent on previous requests- for example, the LD source cannot annotate\n * association data if no data was found for that region.\n * @member {boolean}\n */\n this.dependentSource = false;\n };\n /**\n * A default constructor that can be used when creating new data sources\n * @param {String|Object} init Basic configuration- either a url, or a config object\n * @param {String} [init.url] The datasource URL\n * @param {String} [init.params] Initial config params for the datasource\n */\n LocusZoom.Data.Source.prototype.parseInit = function (init) {\n if (typeof init === 'string') {\n /** @member {String} */\n this.url = init;\n /** @member {String} */\n this.params = {};\n } else {\n this.url = init.url;\n this.params = init.params || {};\n }\n if (!this.url) {\n throw new Error('Source not initialized with required URL');\n }\n };\n /**\n * A unique identifier that indicates whether cached data is valid for this request\n * @protected\n * @param state\n * @param chain\n * @param fields\n * @returns {String|undefined}\n */\n LocusZoom.Data.Source.prototype.getCacheKey = function (state, chain, fields) {\n return this.getURL && this.getURL(state, chain, fields);\n };\n /**\n * Stub: build the URL for any requests made by this source.\n */\n LocusZoom.Data.Source.prototype.getURL = function (state, chain, fields) {\n return this.url;\n };\n /**\n * Perform a network request to fetch data for this source\n * @protected\n * @param {Object} state The state of the parent plot\n * @param chain\n * @param fields\n * @returns {Promise}\n */\n LocusZoom.Data.Source.prototype.fetchRequest = function (state, chain, fields) {\n var url = this.getURL(state, chain, fields);\n return LocusZoom.createCORSPromise('GET', url);\n };\n /**\n * Gets the data for just this source, typically via a network request (caching where possible)\n * @protected\n */\n LocusZoom.Data.Source.prototype.getRequest = function (state, chain, fields) {\n var req;\n var cacheKey = this.getCacheKey(state, chain, fields);\n if (this.enableCache && typeof cacheKey !== 'undefined' && cacheKey === this._cachedKey) {\n req = Promise.resolve(this._cachedResponse); // Resolve to the value of the current promise\n } else {\n req = this.fetchRequest(state, chain, fields);\n if (this.enableCache) {\n this._cachedKey = cacheKey;\n this._cachedResponse = req;\n }\n }\n return req;\n };\n /**\n * Fetch the data from the specified data source, and apply transformations requested by an external consumer.\n * This is the public-facing datasource method that will most commonly be called by external code.\n *\n * @public\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields Array of field names that the plot has requested from this data source. (without the \"namespace\" prefix)\n * @param {String[]} outnames Array describing how the output data should refer to this field. This represents the\n * originally requested field name, including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {function} A callable operation that can be used as part of the data chain\n */\n LocusZoom.Data.Source.prototype.getData = function (state, fields, outnames, trans) {\n if (this.preGetData) {\n var pre = this.preGetData(state, fields, outnames, trans);\n if (this.pre) {\n state = pre.state || state;\n fields = pre.fields || fields;\n outnames = pre.outnames || outnames;\n trans = pre.trans || trans;\n }\n }\n var self = this;\n return function (chain) {\n if (self.dependentSource && chain && chain.body && !chain.body.length) {\n // A \"dependent\" source should not attempt to fire a request if there is no data for it to act on.\n // Therefore, it should simply return the previous data chain.\n return Promise.resolve(chain);\n }\n return self.getRequest(state, chain, fields).then(function (resp) {\n return self.parseResponse(resp, chain, fields, outnames, trans);\n });\n };\n };\n /**\n * Ensure the server response is in a canonical form, an array of one object per record. [ {field: oneval} ].\n * If the server response contains columns, reformats the response from {column1: [], column2: []} to the above.\n *\n * Does not apply namespacing, transformations, or field extraction.\n *\n * May be overridden by data sources that inherently return more complex payloads, or that exist to annotate other\n * sources (eg, if the payload provides extra data rather than a series of records).\n *\n * @param {Object[]|Object} data The original parsed server response\n * @protected\n */\n LocusZoom.Data.Source.prototype.normalizeResponse = function (data) {\n if (Array.isArray(data)) {\n // Already in the desired form\n return data;\n }\n // Otherwise, assume the server response is an object representing columns of data.\n // Each array should have the same length (verify), and a given array index corresponds to a single row.\n var keys = Object.keys(data);\n var N = data[keys[0]].length;\n var sameLength = keys.every(function (key) {\n var item = data[key];\n return item.length === N;\n });\n if (!sameLength) {\n throw new Error(this.constructor.SOURCE_NAME + ' expects a response in which all arrays of data are the same length');\n }\n // Go down the rows, and create an object for each record\n var records = [];\n var fields = Object.keys(data);\n for (var i = 0; i < N; i++) {\n var record = {};\n for (var j = 0; j < fields.length; j++) {\n record[fields[j]] = data[fields[j]][i];\n }\n records.push(record);\n }\n return records;\n };\n /** @deprecated */\n LocusZoom.Data.Source.prototype.prepareData = function (records) {\n console.warn('Warning: .prepareData() is deprecated. Use .annotateData() instead');\n return this.annotateData(records);\n };\n /**\n * Hook to post-process the data returned by this source with new, additional behavior.\n * (eg cleaning up API values or performing complex calculations on the returned data)\n *\n * @param {Object[]} records The parsed data from the source (eg standardized api response)\n * @param {Object} chain The data chain object. For example, chain.headers may provide useful annotation metadata\n * @returns {Object[]|Promise} The modified set of records\n */\n LocusZoom.Data.Source.prototype.annotateData = function (records, chain) {\n // Default behavior: no transformations\n return records;\n };\n /**\n * Clean up the server records for use by datalayers: extract only certain fields, with the specified names.\n * Apply per-field transformations as appropriate.\n *\n * This hook can be overridden, eg to create a source that always returns all records and ignores the \"fields\" array.\n * This is particularly common for sources at the end of a chain- many \"dependent\" sources do not allow\n * cherry-picking individual fields, in which case by **convention** the fields array specifies \"last_source_name:all\"\n *\n * @param {Object[]} data One record object per element\n * @param {String[]} fields The names of fields to extract (as named in the source data). Eg \"afield\"\n * @param {String[]} outnames How to represent the source fields in the output. Eg \"namespace:afield|atransform\"\n * @param {function[]} trans An array of transformation functions (if any). One function per data element, or null.\n * @protected\n */\n LocusZoom.Data.Source.prototype.extractFields = function (data, fields, outnames, trans) {\n //intended for an array of objects\n // [ {\"id\":1, \"val\":5}, {\"id\":2, \"val\":10}]\n // Since a number of sources exist that do not obey this format, we will provide a convenient pass-through\n if (!Array.isArray(data)) {\n return data;\n }\n if (!data.length) {\n // Sometimes there are regions that just don't have data- this should not trigger a missing field error message!\n return data;\n }\n var fieldFound = [];\n for (var k = 0; k < fields.length; k++) {\n fieldFound[k] = 0;\n }\n var records = data.map(function (item) {\n var output_record = {};\n for (var j = 0; j < fields.length; j++) {\n var val = item[fields[j]];\n if (typeof val != 'undefined') {\n fieldFound[j] = 1;\n }\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n output_record[outnames[j]] = val;\n }\n return output_record;\n });\n fieldFound.forEach(function (v, i) {\n if (!v) {\n throw new Error('field ' + fields[i] + ' not found in response for ' + outnames[i]);\n }\n });\n return records;\n };\n /**\n * Combine records from this source with others in the chain to yield final chain body.\n * Handles merging this data with other sources (if applicable).\n *\n * @param {Object[]} data The data That would be returned from this source alone\n * @param {Object} chain The data chain built up during previous requests\n * @param {String[]} fields\n * @param {String[]} outnames\n * @return {Promise|Object[]} The new chain body\n * @protected\n */\n LocusZoom.Data.Source.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n return data;\n };\n /**\n * Coordinates the work of parsing a response and returning records. This is broken into 4 steps, which may be\n * overridden separately for fine-grained control. Each step can return either raw data or a promise.\n *\n * @public\n * @param {String|Object} resp The raw data associated with the response\n * @param {Object} chain The combined parsed response data from this and all other requests made in the chain\n * @param {String[]} fields Array of requested field names (as they would appear in the response payload)\n * @param {String[]} outnames Array of field names as they will be represented in the data returned by this source,\n * including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {Promise|{header: ({}|*), discrete: {}, body: []}} A promise that resolves to an object containing\n * request metadata (headers), the consolidated data for plotting (body), and the individual responses that would be\n * returned by each source in the chain in isolation (discrete)\n */\n LocusZoom.Data.Source.prototype.parseResponse = function (resp, chain, fields, outnames, trans) {\n var source_id = this.source_id || this.constructor.SOURCE_NAME;\n if (!chain.discrete) {\n chain.discrete = {};\n }\n if (!resp) {\n // FIXME: Hack. Certain browser issues (such as mixed content warnings) are reported as a successful promise\n // resolution, even though the request was aborted. This is difficult to reliably detect, and is most likely\n // to occur for annotation sources (such as from ExAC). If empty response is received, skip parsing and log.\n // FIXME: Throw an error after pending, eg https://github.com/konradjk/exac_browser/issues/345\n console.error('No usable response was returned for source: \\'' + source_id + '\\'. Parsing will be skipped.');\n return Promise.resolve(chain);\n }\n var json = typeof resp == 'string' ? JSON.parse(resp) : resp;\n var self = this;\n // Perform the 4 steps of parsing the payload and return a combined chain object\n return Promise.resolve(self.normalizeResponse(json.data || json)).then(function (standardized) {\n // Perform calculations on the data from just this source\n return Promise.resolve(self.annotateData(standardized, chain));\n }).then(function (data) {\n return Promise.resolve(self.extractFields(data, fields, outnames, trans));\n }).then(function (one_source_body) {\n // Store a copy of the data that would be returned by parsing this source in isolation (and taking the\n // fields array into account). This is useful when we want to re-use the source output in many ways.\n chain.discrete[source_id] = one_source_body;\n return Promise.resolve(self.combineChainBody(one_source_body, chain, fields, outnames, trans));\n }).then(function (new_body) {\n return {\n header: chain.header || {},\n discrete: chain.discrete,\n body: new_body\n };\n });\n };\n /** @deprecated */\n LocusZoom.Data.Source.prototype.parseArraysToObjects = function (data, fields, outnames, trans) {\n console.warn('Warning: .parseArraysToObjects() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n };\n /** @deprecated */\n LocusZoom.Data.Source.prototype.parseObjectsToObjects = function (data, fields, outnames, trans) {\n console.warn('Warning: .parseObjectsToObjects() is deprecated. Use .extractFields() instead');\n return this.extractFields(data, fields, outnames, trans);\n };\n /** @deprecated */\n LocusZoom.Data.Source.prototype.parseData = function (data, fields, outnames, trans) {\n console.warn('Warning: .parseData() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n };\n /**\n * Method to define new custom datasources based on a provided constructor. (does not allow registering any additional methods)\n * @public\n * @param {Function} constructorFun Constructor function that is used to create the specified class\n * @param {String} [uniqueName] The name by which the class should be listed in `KnownDataSources`\n * @param {String|Function} [base=LocusZoomData.Source] The name or constructor of a base class to use\n * @returns {*|Function}\n */\n LocusZoom.Data.Source.extend = function (constructorFun, uniqueName, base) {\n if (base) {\n if (Array.isArray(base)) {\n base = LocusZoom.KnownDataSources.create.apply(null, base);\n } else if (typeof base === 'string') {\n base = LocusZoom.KnownDataSources.get(base).prototype;\n } else if (typeof base === 'function') {\n base = base.prototype;\n }\n } else {\n base = new LocusZoom.Data.Source();\n }\n constructorFun = constructorFun || function () {\n };\n constructorFun.prototype = base;\n constructorFun.prototype.constructor = constructorFun;\n if (uniqueName) {\n /** @member {String} LocusZoom.Data.Source.SOURCENAME */\n constructorFun.SOURCE_NAME = uniqueName;\n LocusZoom.KnownDataSources.add(constructorFun);\n }\n return constructorFun;\n };\n /**\n * Datasources can be instantiated from a JSON object instead of code. This represents an existing source in that data format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n *\n * Custom sources with their own parameters may need to re-implement this method\n *\n * @public\n * @returns {Object}\n */\n LocusZoom.Data.Source.prototype.toJSON = function () {\n return [\n Object.getPrototypeOf(this).constructor.SOURCE_NAME,\n {\n url: this.url,\n params: this.params\n }\n ];\n };\n /**\n * Data Source for Association Data, as fetched from the LocusZoom API server (or compatible)\n * @class\n * @public\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.AssociationSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'AssociationLZ');\n LocusZoom.Data.AssociationSource.prototype.preGetData = function (state, fields, outnames, trans) {\n var id_field = this.params.id_field || 'id';\n [\n id_field,\n 'position'\n ].forEach(function (x) {\n if (fields.indexOf(x) === -1) {\n fields.unshift(x);\n outnames.unshift(x);\n trans.unshift(null);\n }\n });\n return {\n fields: fields,\n outnames: outnames,\n trans: trans\n };\n };\n LocusZoom.Data.AssociationSource.prototype.getURL = function (state, chain, fields) {\n var analysis = chain.header.analysis || this.params.source || this.params.analysis;\n // Old usages called this param \"analysis\"\n if (typeof analysis == 'undefined') {\n throw new Error('Association source must specify an analysis ID to plot');\n }\n return this.url + 'results/?filter=analysis in ' + analysis + ' and chromosome in \\'' + state.chr + '\\'' + ' and position ge ' + state.start + ' and position le ' + state.end;\n };\n LocusZoom.Data.AssociationSource.prototype.normalizeResponse = function (data) {\n // Some association sources do not sort their data in a predictable order, which makes it hard to reliably\n // align with other sources (such as LD). For performance reasons, sorting is an opt-in argument.\n // TODO: Consider more fine grained sorting control in the future\n data = LocusZoom.Data.Source.prototype.normalizeResponse.call(this, data);\n if (this.params && this.params.sort && data.length && data[0]['position']) {\n data.sort(function (a, b) {\n return a['position'] - b['position'];\n });\n }\n return data;\n };\n /**\n * Data Source for LD Data, as fetched from the LocusZoom API server (or compatible)\n * This source is designed to connect its results to association data, and therefore depends on association data having\n * been loaded by a previous request in the data chain.\n *\n * This source is deprecated in favor of a new, standalone LD server. For new usages, see LDLZ2.\n *\n * @class\n * @deprecated\n * @public\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.LDSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n this.dependentSource = true;\n }, 'LDLZ');\n LocusZoom.Data.LDSource.prototype.preGetData = function (state, fields) {\n if (fields.length > 1) {\n if (fields.length !== 2 || fields.indexOf('isrefvar') === -1) {\n throw new Error('LD does not know how to get all fields: ' + fields.join(', '));\n }\n }\n };\n LocusZoom.Data.LDSource.prototype.findMergeFields = function (chain) {\n // Find the fields (as provided by a previous step in the chain, like an association source) that will be needed to\n // combine LD data with existing information\n // Since LD information may be shared across multiple assoc sources with different namespaces,\n // we use regex to find columns to join on, rather than requiring exact matches\n var exactMatch = function (arr) {\n return function () {\n var regexes = arguments;\n for (var i = 0; i < regexes.length; i++) {\n var regex = regexes[i];\n var m = arr.filter(function (x) {\n return x.match(regex);\n });\n if (m.length) {\n return m[0];\n }\n }\n return null;\n };\n };\n var dataFields = {\n id: this.params.id_field,\n position: this.params.position_field,\n pvalue: this.params.pvalue_field,\n _names_: null\n };\n if (chain && chain.body && chain.body.length > 0) {\n var names = Object.keys(chain.body[0]);\n var nameMatch = exactMatch(names);\n // Internally, fields are generally prefixed with the name of the source they come from.\n // If the user provides an id_field (like `variant`), it should work across data sources( `assoc1:variant`,\n // assoc2:variant), but not match fragments of other field names (assoc1:variant_thing)\n // Note: these lookups hard-code a couple of common fields that will work based on known APIs in the wild\n var id_match = dataFields.id && nameMatch(new RegExp(dataFields.id + '\\\\b'));\n dataFields.id = id_match || nameMatch(/\\bvariant\\b/) || nameMatch(/\\bid\\b/);\n dataFields.position = dataFields.position || nameMatch(/\\bposition\\b/i, /\\bpos\\b/i);\n dataFields.pvalue = dataFields.pvalue || nameMatch(/\\bpvalue\\b/i, /\\blog_pvalue\\b/i);\n dataFields._names_ = names;\n }\n return dataFields;\n };\n LocusZoom.Data.LDSource.prototype.findRequestedFields = function (fields, outnames) {\n // Assumption: all usages of this source will only ever ask for \"isrefvar\" or \"state\". This maps to output names.\n var obj = {};\n for (var i = 0; i < fields.length; i++) {\n if (fields[i] === 'isrefvar') {\n obj.isrefvarin = fields[i];\n obj.isrefvarout = outnames && outnames[i];\n } else {\n obj.ldin = fields[i];\n obj.ldout = outnames && outnames[i];\n }\n }\n return obj;\n };\n LocusZoom.Data.LDSource.prototype.normalizeResponse = function (data) {\n return data;\n };\n /**\n * Get the LD reference variant, which by default will be the most significant hit in the assoc results\n * This will be used in making the original query to the LD server for pairwise LD information\n * @returns {*|string} The marker id (expected to be in `chr:pos_ref/alt` format) of the reference variant\n */\n LocusZoom.Data.LDSource.prototype.getRefvar = function (state, chain, fields) {\n var findExtremeValue = function (records, pval_field) {\n // Finds the most significant hit (smallest pvalue, or largest -log10p). Will try to auto-detect the appropriate comparison.\n pval_field = pval_field || 'log_pvalue';\n // The official LZ API returns log_pvalue\n var is_log = /log/.test(pval_field);\n var cmp;\n if (is_log) {\n cmp = function (a, b) {\n return a > b;\n };\n } else {\n cmp = function (a, b) {\n return a < b;\n };\n }\n var extremeVal = records[0][pval_field], extremeIdx = 0;\n for (var i = 1; i < records.length; i++) {\n if (cmp(records[i][pval_field], extremeVal)) {\n extremeVal = records[i][pval_field];\n extremeIdx = i;\n }\n }\n return extremeIdx;\n };\n var reqFields = this.findRequestedFields(fields);\n var refVar = reqFields.ldin;\n if (refVar === 'state') {\n refVar = state.ldrefvar || chain.header.ldrefvar || 'best';\n }\n if (refVar === 'best') {\n if (!chain.body) {\n throw new Error('No association data found to find best pvalue');\n }\n var keys = this.findMergeFields(chain);\n if (!keys.pvalue || !keys.id) {\n var columns = '';\n if (!keys.id) {\n columns += (columns.length ? ', ' : '') + 'id';\n }\n if (!keys.pvalue) {\n columns += (columns.length ? ', ' : '') + 'pvalue';\n }\n throw new Error('Unable to find necessary column(s) for merge: ' + columns + ' (available: ' + keys._names_ + ')');\n }\n refVar = chain.body[findExtremeValue(chain.body, keys.pvalue)][keys.id];\n }\n return refVar;\n };\n LocusZoom.Data.LDSource.prototype.getURL = function (state, chain, fields) {\n var refSource = state.ldrefsource || chain.header.ldrefsource || 1;\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n return this.url + 'results/?filter=reference eq ' + refSource + ' and chromosome2 eq \\'' + state.chr + '\\'' + ' and position2 ge ' + state.start + ' and position2 le ' + state.end + ' and variant1 eq \\'' + refVar + '\\'' + '&fields=chr,pos,rsquare';\n };\n LocusZoom.Data.LDSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n var keys = this.findMergeFields(chain);\n var reqFields = this.findRequestedFields(fields, outnames);\n if (!keys.position) {\n throw new Error('Unable to find position field for merge: ' + keys._names_);\n }\n var leftJoin = function (left, right, lfield, rfield) {\n var i = 0, j = 0;\n while (i < left.length && j < right.position2.length) {\n if (left[i][keys.position] === right.position2[j]) {\n left[i][lfield] = right[rfield][j];\n i++;\n j++;\n } else if (left[i][keys.position] < right.position2[j]) {\n i++;\n } else {\n j++;\n }\n }\n };\n var tagRefVariant = function (data, refvar, idfield, outrefname, outldname) {\n for (var i = 0; i < data.length; i++) {\n if (data[i][idfield] && data[i][idfield] === refvar) {\n data[i][outrefname] = 1;\n data[i][outldname] = 1; // For label/filter purposes, implicitly mark the ref var as LD=1 to itself\n } else {\n data[i][outrefname] = 0;\n }\n }\n };\n // LD servers vary slightly. Some report corr as \"rsquare\", others as \"correlation\"\n var corrField = data.rsquare ? 'rsquare' : 'correlation';\n leftJoin(chain.body, data, reqFields.ldout, corrField);\n if (reqFields.isrefvarin && chain.header.ldrefvar) {\n tagRefVariant(chain.body, chain.header.ldrefvar, keys.id, reqFields.isrefvarout, reqFields.ldout);\n }\n return chain.body;\n };\n /**\n * Fetch LD directly from the standalone Portal LD server\n *\n * @class\n * @public\n * @augments LocusZoom.Data.LDSource\n */\n LocusZoom.Data.LDSource2 = LocusZoom.KnownDataSources.extend('LDLZ', 'LDLZ2', {\n getURL: function (state, chain, fields) {\n // Accept the following params in this.params:\n // - method (r, rsquare, cov)\n // - source (aka panel)\n // - population (ALL, AFR, EUR, etc)\n // - build\n // The LD source/pop can be overridden from plot.state for dynamic layouts\n var build = state.genome_build || this.params.build || 'GRCh37';\n var source = state.ld_source || this.params.source || '1000G';\n var population = state.ld_pop || this.params.population || 'ALL';\n // LDServer panels will always have an ALL\n var method = this.params.method || 'rsquare';\n validateBuildSource(this.constructor.SOURCE_NAME, build, null);\n // LD doesn't need to validate `source` option\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n return [\n this.url,\n 'genome_builds/',\n build,\n '/references/',\n source,\n '/populations/',\n population,\n '/variants',\n '?correlation=',\n method,\n '&variant=',\n encodeURIComponent(refVar),\n '&chrom=',\n encodeURIComponent(state.chr),\n '&start=',\n encodeURIComponent(state.start),\n '&stop=',\n encodeURIComponent(state.end)\n ].join('');\n },\n fetchRequest: function (state, chain, fields) {\n // The API is paginated, but we need all of the data to render a plot. Depaginate and combine where appropriate.\n var url = this.getURL(state, chain, fields);\n var combined = { data: {} };\n var chainRequests = function (url) {\n return LocusZoom.createCORSPromise('GET', url).then(function (payload) {\n payload = JSON.parse(payload);\n Object.keys(payload.data).forEach(function (key) {\n combined.data[key] = (combined.data[key] || []).concat(payload.data[key]);\n });\n if (payload.next) {\n return chainRequests(payload.next);\n }\n return combined;\n });\n };\n return chainRequests(url);\n }\n });\n /**\n * Data source for GWAS catalogs of known variants\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object|String} init Configuration (URL or object)\n * @param {Object} [init.params] Optional configuration parameters\n * @param {Number} [init.params.source=2] The ID of the chosen catalog. Defaults to EBI GWAS catalog, GRCh37\n * @param {('strict'|'loose')} [init.params.match_type='strict'] Whether to match on exact variant, or just position.\n */\n LocusZoom.Data.GwasCatalog = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n this.dependentSource = true;\n }, 'GwasCatalogLZ');\n LocusZoom.Data.GwasCatalog.prototype.getURL = function (state, chain, fields) {\n // This is intended to be aligned with another source- we will assume they are always ordered by position, asc\n // (regardless of the actual match field)\n var build_option = state.genome_build || this.params.build;\n validateBuildSource(this.constructor.SOURCE_NAME, build_option, null);\n // Source can override build- not mutually exclusive\n // Most of our annotations will respect genome build before any other option.\n // But there can be more than one GWAS catalog for the same build, so an explicit config option will always take\n // precedence.\n var default_source = build_option === 'GRCh38' ? 1 : 2;\n // EBI GWAS catalog\n var source = this.params.source || default_source;\n return this.url + '?format=objects&sort=pos&filter=id eq ' + source + ' and chrom eq \\'' + state.chr + '\\'' + ' and pos ge ' + state.start + ' and pos le ' + state.end;\n };\n LocusZoom.Data.GwasCatalog.prototype.findMergeFields = function (records) {\n // Data from previous sources is already namespaced. Find the alignment field by matching.\n var knownFields = Object.keys(records);\n // Note: All API endoints involved only give results for 1 chromosome at a time; match is implied\n var posMatch = knownFields.find(function (item) {\n return item.match(/\\b(position|pos)\\b/i);\n });\n if (!posMatch) {\n throw new Error('Could not find data to align with GWAS catalog results');\n }\n return { 'pos': posMatch };\n };\n // Skip the \"individual field extraction\" step; extraction will be handled when building chain body instead\n LocusZoom.Data.GwasCatalog.prototype.extractFields = function (data, fields, outnames, trans) {\n return data;\n };\n LocusZoom.Data.GwasCatalog.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data.length) {\n return chain.body;\n }\n var decider = 'log_pvalue';\n // TODO: Better reuse options in the future\n var decider_out = outnames[fields.indexOf(decider)];\n function leftJoin(left, right, fields, outnames, trans) {\n // Add `fields` from `right` to `left`\n // Add a synthetic, un-namespaced field to all matching records\n var n_matches = left['n_catalog_matches'] || 0;\n left['n_catalog_matches'] = n_matches + 1;\n if (decider && left[decider_out] && left[decider_out] > right[decider]) {\n // There may be more than one GWAS catalog entry for the same SNP. This source is intended for a 1:1\n // annotation scenario, so for now it only joins the catalog entry that has the best -log10 pvalue\n return;\n }\n for (var j = 0; j < fields.length; j++) {\n var fn = fields[j];\n var outn = outnames[j];\n var val = right[fn];\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n left[outn] = val;\n }\n }\n var chainNames = this.findMergeFields(chain.body[0]);\n var catNames = this.findMergeFields(data[0]);\n var i = 0, j = 0;\n while (i < chain.body.length && j < data.length) {\n var left = chain.body[i];\n var right = data[j];\n if (left[chainNames.pos] === right[catNames.pos]) {\n // There may be multiple catalog entries for each matching SNP; evaluate match one at a time\n leftJoin(left, right, fields, outnames, trans);\n j += 1;\n } else if (left[chainNames.pos] < right[catNames.pos]) {\n i += 1;\n } else {\n j += 1;\n }\n }\n return chain.body;\n };\n /**\n * Data Source for Gene Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.GeneSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'GeneLZ');\n LocusZoom.Data.GeneSource.prototype.getURL = function (state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n if (build) {\n // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = build === 'GRCh38' ? 1 : 3;\n }\n return this.url + '?filter=source in ' + source + ' and chrom eq \\'' + state.chr + '\\'' + ' and start le ' + state.end + ' and end ge ' + state.start;\n };\n // Genes have a very complex internal data format. Bypass any record parsing, and provide the data layer with the\n // exact information returned by the API. (ignoring the fields array in the layout)\n LocusZoom.Data.GeneSource.prototype.normalizeResponse = function (data) {\n return data;\n };\n LocusZoom.Data.GeneSource.prototype.extractFields = function (data, fields, outnames, trans) {\n return data;\n };\n /**\n * Data Source for Gene Constraint Data, as fetched from the gnomAD server (or compatible)\n *\n * In the past, this source used ExAC, which has been completely decommissioned. Since the old source referenced a\n * server that no longer exists, this was redefined in 0.11.0 in a backwards-incompatible manner.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n*/\n LocusZoom.Data.GeneConstraintSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'GeneConstraintLZ');\n LocusZoom.Data.GeneConstraintSource.prototype.getURL = function () {\n return this.url;\n };\n LocusZoom.Data.GeneConstraintSource.prototype.normalizeResponse = function (data) {\n return data;\n };\n LocusZoom.Data.GeneConstraintSource.prototype.getCacheKey = function (state, chain, fields) {\n return this.url + JSON.stringify(state);\n };\n LocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function (state, chain, fields) {\n var build = state.genome_build || this.params.build;\n if (!build) {\n throw new Error([\n 'Data source',\n this.constructor.SOURCE_NAME,\n 'requires that you specify a genome_build'\n ].join(' '));\n }\n var query = chain.body.map(function (gene) {\n var gene_name = gene.gene_name;\n // GraphQL alias names must match a specific set of allowed characters: https://stackoverflow.com/a/45757065/1422268\n var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_');\n // Each gene is a separate graphQL query, grouped into one request using aliases\n return alias + ': gene(gene_symbol: \"' + gene_name + '\", reference_genome: ' + build + ') { gnomad_constraint { exp_syn obs_syn syn_z oe_syn oe_syn_lower oe_syn_upper exp_mis obs_mis mis_z oe_mis oe_mis_lower oe_mis_upper exp_lof obs_lof pLI oe_lof oe_lof_lower oe_lof_upper } } ';\n });\n if (!query.length) {\n // If there are no genes, skip the network request\n return Promise.resolve({ data: null });\n }\n query = '{' + query.join(' ') + ' }';\n // GraphQL isn't quite JSON; items are separated by spaces but not commas\n var url = this.getURL(state, chain, fields);\n // See: https://graphql.org/learn/serving-over-http/\n var body = JSON.stringify({ query: query });\n var headers = { 'Content-Type': 'application/json' };\n return LocusZoom.createCORSPromise('POST', url, body, headers);\n };\n LocusZoom.Data.GeneConstraintSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data) {\n return chain;\n }\n chain.body.forEach(function (gene) {\n // Find payload keys that match gene names in this response\n var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_');\n // aliases are modified gene names\n var constraint = data[alias] && data[alias]['gnomad_constraint'];\n // gnomad API has two ways of specifying missing data for a requested gene\n if (constraint) {\n // Add all fields from constraint data- do not override fields present in the gene source\n Object.keys(constraint).forEach(function (key) {\n var val = constraint[key];\n if (typeof gene[key] === 'undefined') {\n if (typeof val == 'number' && val.toString().indexOf('.') !== -1) {\n val = parseFloat(val.toFixed(2));\n }\n gene[key] = val; // These two sources are both designed to bypass namespacing\n }\n });\n }\n });\n return chain.body;\n };\n /**\n * Data Source for Recombination Rate Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.RecombinationRateSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'RecombLZ');\n LocusZoom.Data.RecombinationRateSource.prototype.getURL = function (state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n if (build) {\n // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = build === 'GRCh38' ? 16 : 15;\n }\n return this.url + '?filter=id in ' + source + ' and chromosome eq \\'' + state.chr + '\\'' + ' and position le ' + state.end + ' and position ge ' + state.start;\n };\n /**\n * Data Source for Interval Annotation Data (e.g. BED Tracks), as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.IntervalSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'IntervalLZ');\n LocusZoom.Data.IntervalSource.prototype.getURL = function (state, chain, fields) {\n var source = chain.header.bedtracksource || this.params.source;\n return this.url + '?filter=id in ' + source + ' and chromosome eq \\'' + state.chr + '\\'' + ' and start le ' + state.end + ' and end ge ' + state.start;\n };\n /**\n * Data Source for static blobs of JSON Data. This does not perform additional parsing, and therefore it is the\n * responsibility of the user to pass information in a format that can be read and understood by the chosen plot.\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\n LocusZoom.Data.StaticSource = LocusZoom.Data.Source.extend(function (data) {\n /** @member {Object} */\n this._data = data;\n }, 'StaticJSON');\n LocusZoom.Data.StaticSource.prototype.getRequest = function (state, chain, fields) {\n return Promise.resolve(this._data);\n };\n LocusZoom.Data.StaticSource.prototype.toJSON = function () {\n return [\n Object.getPrototypeOf(this).constructor.SOURCE_NAME,\n this._data\n ];\n };\n /**\n * Data source for PheWAS data\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {String[]} init.params.build This datasource expects to be provided the name of the genome build that will\n * be used to provide pheWAS results for this position. Note positions may not translate between builds.\n */\n LocusZoom.Data.PheWASSource = LocusZoom.Data.Source.extend(function (init) {\n this.parseInit(init);\n }, 'PheWASLZ');\n LocusZoom.Data.PheWASSource.prototype.getURL = function (state, chain, fields) {\n var build = (state.genome_build ? [state.genome_build] : null) || this.params.build;\n if (!build || !Array.isArray(build) || !build.length) {\n throw new Error([\n 'Data source',\n this.constructor.SOURCE_NAME,\n 'requires that you specify array of one or more desired genome build names'\n ].join(' '));\n }\n var url = [\n this.url,\n '?filter=variant eq \\'',\n encodeURIComponent(state.variant),\n '\\'&format=objects&',\n build.map(function (item) {\n return 'build=' + encodeURIComponent(item);\n }).join('&')\n ];\n return url.join('');\n };\n /**\n * Base class for \"connectors\"- this is meant to be subclassed, rather than used directly.\n *\n * A connector is a source that makes no server requests and caches no data of its own. Instead, it decides how to\n * combine data from other sources in the chain. Connectors are useful when we want to request (or calculate) some\n * useful piece of information once, but apply it to many different kinds of record types.\n *\n * Typically, a subclass will implement the field merging logic in `combineChainBody`.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object} init Configuration for this source\n * @param {Object} init.sources Specify how the hard-coded logic should find the data it relies on in the chain,\n * as {internal_name: chain_source_id} pairs. This allows writing a reusable connector that does not need to make\n * assumptions about what namespaces a source is using.\n * @type {*|Function}\n */\n LocusZoom.Data.ConnectorSource = LocusZoom.Data.Source.extend(function (init) {\n if (!init || !init.sources) {\n throw new Error('Connectors must specify the data they require as init.sources = {internal_name: chain_source_id}} pairs');\n }\n /**\n * Tells the connector how to find the data it relies on\n *\n * For example, a connector that applies burden test information to the genes layer might specify:\n * {gene_ns: \"gene\", aggregation_ns: \"aggregation\"}\n *\n * @member {Object}\n */\n this._source_name_mapping = init.sources;\n // Validate that this source has been told how to find the required information\n var specified_ids = Object.keys(init.sources);\n var self = this;\n this.REQUIRED_SOURCES.forEach(function (k) {\n if (specified_ids.indexOf(k) === -1) {\n throw new Error('Configuration for ' + self.constructor.SOURCE_NAME + ' must specify a source ID corresponding to ' + k);\n }\n });\n this.parseInit(init);\n }, 'ConnectorSource');\n /** @property {String[]} Specifies the sources that must be provided in the original config object */\n LocusZoom.Data.ConnectorSource.prototype.REQUIRED_SOURCES = [];\n LocusZoom.Data.ConnectorSource.prototype.parseInit = function (init) {\n };\n // Stub\n LocusZoom.Data.ConnectorSource.prototype.getRequest = function (state, chain, fields) {\n // Connectors do not request their own data by definition, but they *do* depend on other sources having been loaded\n // first. This method performs basic validation, and preserves the accumulated body from the chain so far.\n var self = this;\n Object.keys(this._source_name_mapping).forEach(function (ns) {\n var chain_source_id = self._source_name_mapping[ns];\n if (chain.discrete && !chain.discrete[chain_source_id]) {\n throw new Error(self.constructor.SOURCE_NAME + ' cannot be used before loading required data for: ' + chain_source_id);\n }\n });\n return Promise.resolve(chain.body || []);\n };\n LocusZoom.Data.ConnectorSource.prototype.parseResponse = function (data, chain, fields, outnames, trans) {\n // A connector source does not update chain.discrete, but it may use it. It bypasses data formatting\n // and field selection (both are assumed to have been done already, by the previous sources this draws from)\n // Because of how the chain works, connectors are not very good at applying new transformations or namespacing.\n // Typically connectors are called with `connector_name:all` in the fields array.\n return Promise.resolve(this.combineChainBody(data, chain, fields, outnames, trans)).then(function (new_body) {\n return {\n header: chain.header || {},\n discrete: chain.discrete || {},\n body: new_body\n };\n });\n };\n LocusZoom.Data.ConnectorSource.prototype.combineChainBody = function (records, chain) {\n // Stub method: specifies how to combine the data\n throw new Error('This method must be implemented in a subclass');\n };\n /* global LocusZoom */\n 'use strict';\n /**\n * An independent LocusZoom object that renders a unique set of data and subpanels.\n * Many such LocusZoom objects can exist simultaneously on a single page, each having its own layout.\n *\n * This creates a new plot instance, but does not immediately render it. For practical use, it may be more convenient\n * to use the `LocusZoom.populate` helper method.\n *\n * @class\n * @param {String} id The ID of the plot. Often corresponds to the ID of the container element on the page\n * where the plot is rendered..\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n*/\n LocusZoom.Plot = function (id, datasource, layout) {\n /** @member Boolean} */\n this.initialized = false;\n // TODO: This makes sense for all other locuszoom elements to have; determine whether this is interface boilerplate or something that can be removed\n this.parent_plot = this;\n /** @member {String} */\n this.id = id;\n /** @member {Element} */\n this.container = null;\n /**\n * Selector for a node that will contain the plot. (set externally by populate methods)\n * @member {d3.selection}\n */\n this.svg = null;\n /** @member {Object.} */\n this.panels = {};\n /**\n * TODO: This is currently used by external classes that manipulate the parent and may indicate room for a helper method in the api to coordinate boilerplate\n * @protected\n * @member {String[]}\n */\n this.panel_ids_by_y_index = [];\n /**\n * Notify each child panel of the plot of changes in panel ordering/ arrangement\n */\n this.applyPanelYIndexesToPanelLayouts = function () {\n this.panel_ids_by_y_index.forEach(function (pid, idx) {\n this.panels[pid].layout.y_index = idx;\n }.bind(this));\n };\n /**\n * Get the qualified ID pathname for the plot\n * @returns {String}\n */\n this.getBaseId = function () {\n return this.id;\n };\n /**\n * Track update operations (reMap) performed on all child panels, and notify the parent plot when complete\n * TODO: Reconsider whether we need to be tracking this as global state outside of context of specific operations\n * @protected\n * @member {Promise[]}\n */\n this.remap_promises = [];\n if (typeof layout == 'undefined') {\n /**\n * The layout is a serializable object used to describe the composition of the Plot\n * If no layout was passed, use the Standard Association Layout\n * Otherwise merge whatever was passed with the Default Layout\n * TODO: Review description; we *always* merge with default layout?\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge({}, LocusZoom.Layouts.get('plot', 'standard_association'));\n } else {\n this.layout = layout;\n }\n LocusZoom.Layouts.merge(this.layout, LocusZoom.Plot.DefaultLayout);\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original plot state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n /**\n * Create a shortcut to the state in the layout on the Plot. Tracking in the layout allows the plot to be created\n * with initial state/setup.\n *\n * Tracks state of the plot, eg start and end position\n * @member {Object}\n */\n this.state = this.layout.state;\n /** @member {LocusZoom.Data.Requester} */\n this.lzd = new LocusZoom.Data.Requester(datasource);\n /**\n * Window.onresize listener (responsive layouts only)\n * TODO: .on appears to return a selection, not a listener? Check logic here\n * https://github.com/d3/d3-selection/blob/00b904b9bcec4dfaf154ae0bbc777b1fc1d7bc08/test/selection/on-test.js#L11\n * @deprecated\n * @member {d3.selection}\n */\n this.window_onresize = null;\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [],\n // Select or unselect\n 'element_selection': [],\n // Element becomes active (only)\n 'match_requested': [],\n // A data layer is attempting to highlight matching points (internal use only)\n 'panel_removed': [],\n 'state_changed': [] // Only triggered when a state change causes rerender\n };\n /**\n * @callback eventCallback\n * @param {object} eventData A description of the event\n * @param {String|null} eventData.sourceID The unique identifier (eg plot or parent name) of the element that\n * triggered the event. Will be automatically filled in if not explicitly provided.\n * @param {Object|null} eventData.context Any additional information to be passed to the callback, eg the data\n * associated with a clicked plot element\n */\n /**\n * There are several events that a LocusZoom plot can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following plot-level events are currently supported:\n * - `layout_changed` - context: plot - Any aspect of the plot's layout (including dimensions or state) has changed.\n * - `data_requested` - context: plot - A request for new data from any data source used in the plot has been made.\n * - `data_rendered` - context: plot - Data from a request has been received and rendered in the plot.\n * - `element_clicked` - context: plot - A data element in any of the plot's data layers has been clicked.\n * - `element_selection` - context: plot - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `plot.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * plot itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} hook\n * @returns {function} The registered event listener\n */\n this.on = function (event, hook) {\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Plot}\n */\n this.off = function (event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n * @param {string} event A known event name\n * @param {*} eventData Data or event description that will be passed to the event listener\n * @returns {LocusZoom.Plot}\n */\n this.emit = function (event, eventData) {\n // TODO: there are small differences between the emit implementation between plots and panels. In the future,\n // DRY this code via mixins, and make sure to keep the interfaces compatible when refactoring.\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n var sourceID = this.getBaseId();\n var self = this;\n this.event_hooks[event].forEach(function (hookToRun) {\n var eventContext;\n if (eventData && eventData.sourceID) {\n // If we detect that an event originated elsewhere (via bubbling or externally), preserve the context\n // when re-emitting the event to plot-level listeners\n eventContext = eventData;\n } else {\n eventContext = {\n sourceID: sourceID,\n data: eventData || null\n };\n }\n // By default, any handlers fired here (either directly, or bubbled) will see the plot as the\n // value of `this`. If a bound function is registered as a handler, the previously bound `this` will\n // override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n return this;\n };\n /**\n * Get an object with the x and y coordinates of the plot's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the plot\n * @returns {{x: Number, y: Number, width: Number, height: Number}}\n */\n this.getPageOrigin = function () {\n var bounding_client_rect = this.svg.node().getBoundingClientRect();\n var x_offset = document.documentElement.scrollLeft || document.body.scrollLeft;\n var y_offset = document.documentElement.scrollTop || document.body.scrollTop;\n var container = this.svg.node();\n while (container.parentNode !== null) {\n container = container.parentNode;\n if (container !== document && d3.select(container).style('position') !== 'static') {\n x_offset = -1 * container.getBoundingClientRect().left;\n y_offset = -1 * container.getBoundingClientRect().top;\n break;\n }\n }\n return {\n x: x_offset + bounding_client_rect.left,\n y: y_offset + bounding_client_rect.top,\n width: bounding_client_rect.width,\n height: bounding_client_rect.height\n };\n };\n /**\n * Get the top and left offset values for the plot's container element (the div that was populated)\n * @returns {{top: number, left: number}}\n */\n this.getContainerOffset = function () {\n var offset = {\n top: 0,\n left: 0\n };\n var container = this.container.offsetParent || null;\n while (container !== null) {\n offset.top += container.offsetTop;\n offset.left += container.offsetLeft;\n container = container.offsetParent || null;\n }\n return offset;\n };\n //\n /**\n * Event information describing interaction (e.g. panning and zooming) is stored on the plot\n * TODO: Add/ document details of interaction structure as we expand\n * @member {{panel_id: String, linked_panel_ids: Array, x_linked: *, dragging: *, zooming: *}}\n * @returns {LocusZoom.Plot}\n */\n this.interaction = {};\n /**\n * Track whether the target panel can respond to mouse interaction events\n * @param {String} panel_id\n * @returns {boolean}\n */\n this.canInteract = function (panel_id) {\n panel_id = panel_id || null;\n if (panel_id) {\n return (typeof this.interaction.panel_id == 'undefined' || this.interaction.panel_id === panel_id) && !this.loading_data;\n } else {\n return !(this.interaction.dragging || this.interaction.zooming || this.loading_data);\n }\n };\n // Initialize the layout\n this.initializeLayout();\n return this;\n };\n /**\n * Default/ expected configuration parameters for basic plotting; most plots will override\n *\n * @protected\n * @static\n * @type {Object}\n */\n LocusZoom.Plot.DefaultLayout = {\n state: {},\n width: 1,\n height: 1,\n min_width: 1,\n min_height: 1,\n responsive_resize: false,\n // Allowed values: false, \"width_only\", \"both\" (synonym for true)\n aspect_ratio: 1,\n panels: [],\n dashboard: { components: [] },\n panel_boundaries: true,\n mouse_guide: true\n };\n /**\n * Helper method to sum the proportional dimensions of panels, a value that's checked often as panels are added/removed\n * @param {('Height'|'Width')} dimension\n * @returns {number}\n */\n LocusZoom.Plot.prototype.sumProportional = function (dimension) {\n if (dimension !== 'height' && dimension !== 'width') {\n throw new Error('Bad dimension value passed to LocusZoom.Plot.prototype.sumProportional');\n }\n var total = 0;\n for (var id in this.panels) {\n // Ensure every panel contributing to the sum has a non-zero proportional dimension\n if (!this.panels[id].layout['proportional_' + dimension]) {\n this.panels[id].layout['proportional_' + dimension] = 1 / Object.keys(this.panels).length;\n }\n total += this.panels[id].layout['proportional_' + dimension];\n }\n return total;\n };\n /**\n * Resize the plot to fit the bounding container\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.rescaleSVG = function () {\n var clientRect = this.svg.node().getBoundingClientRect();\n this.setDimensions(clientRect.width, clientRect.height);\n return this;\n };\n /**\n * Prepare the plot for first use by performing parameter validation, setting up panels, and calculating dimensions\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.initializeLayout = function () {\n // Sanity check layout values\n if (isNaN(this.layout.width) || this.layout.width <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.height) || this.layout.height <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.aspect_ratio) || this.layout.aspect_ratio <= 0) {\n throw new Error('Plot layout parameter `aspect_ratio` must be a positive number');\n }\n if (this.layout.responsive_resize === true) {\n // Backwards compatible support\n console.warn('LocusZoom \"responsive_resize\" specifies a deprecated value. The new value should be \"both\". Please update your layout.');\n this.layout.responsive_resize = 'both';\n }\n var RESIZE_MODES = [\n false,\n 'both',\n 'width_only'\n ];\n if (RESIZE_MODES.indexOf(this.layout.responsive_resize) === -1) {\n throw new Error('LocusZoom option \"responsive_resize\" should specify one of the following modes: ' + RESIZE_MODES.join(', '));\n }\n // If this is a responsive layout then set a namespaced/unique onresize event listener on the window\n if (this.layout.responsive_resize) {\n this.window_onresize = d3.select(window).on('resize.lz-' + this.id, function () {\n this.rescaleSVG();\n }.bind(this));\n // Forcing one additional setDimensions() call after the page is loaded clears up\n // any disagreements between the initial layout and the loaded responsive container's size\n d3.select(window).on('load.lz-' + this.id, function () {\n this.setDimensions();\n }.bind(this));\n }\n // Add panels\n this.layout.panels.forEach(function (panel_layout) {\n this.addPanel(panel_layout);\n }.bind(this));\n return this;\n };\n /**\n * Set the dimensions for a plot, and ensure that panels are sized and positioned correctly.\n *\n * If dimensions are provided, resizes each panel proportionally to match the new plot dimensions. Otherwise,\n * calculates the appropriate plot dimensions based on all panels.\n * @param {Number} [width] If provided and larger than minimum size, set plot to this width\n * @param {Number} [height] If provided and larger than minimum size, set plot to this height\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.setDimensions = function (width, height) {\n var id;\n // Update minimum allowable width and height by aggregating minimums from panels, then apply minimums to containing element.\n var min_width = parseFloat(this.layout.min_width) || 0;\n var min_height = parseFloat(this.layout.min_height) || 0;\n for (id in this.panels) {\n min_width = Math.max(min_width, this.panels[id].layout.min_width);\n if (parseFloat(this.panels[id].layout.min_height) > 0 && parseFloat(this.panels[id].layout.proportional_height) > 0) {\n min_height = Math.max(min_height, this.panels[id].layout.min_height / this.panels[id].layout.proportional_height);\n }\n }\n this.layout.min_width = Math.max(min_width, 1);\n this.layout.min_height = Math.max(min_height, 1);\n d3.select(this.svg.node().parentNode).style({\n 'min-width': this.layout.min_width + 'px',\n 'min-height': this.layout.min_height + 'px'\n });\n // If width and height arguments were passed then adjust them against plot minimums if necessary.\n // Then resize the plot and proportionally resize panels to fit inside the new plot dimensions.\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n // Override discrete values if resizing responsively\n if (this.layout.responsive_resize) {\n // All resize modes will affect width\n if (this.svg) {\n this.layout.width = Math.max(this.svg.node().parentNode.getBoundingClientRect().width, this.layout.min_width);\n }\n if (this.layout.responsive_resize === 'both') {\n // Then also change the height\n this.layout.height = this.layout.width / this.layout.aspect_ratio;\n if (this.layout.height < this.layout.min_height) {\n this.layout.height = this.layout.min_height;\n this.layout.width = this.layout.height * this.layout.aspect_ratio;\n }\n }\n }\n // Resize/reposition panels to fit, update proportional origins if necessary\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n var panel_width = this.layout.width;\n var panel_height = this.panels[panel_id].layout.proportional_height * this.layout.height;\n this.panels[panel_id].setDimensions(panel_width, panel_height);\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n this.panels[panel_id].layout.proportional_origin.y = y_offset / this.layout.height;\n y_offset += panel_height;\n this.panels[panel_id].dashboard.update();\n }.bind(this));\n } // If width and height arguments were NOT passed (and panels exist) then determine the plot dimensions\n // by making it conform to panel dimensions, assuming panels are already positioned correctly.\n else if (Object.keys(this.panels).length) {\n this.layout.width = 0;\n this.layout.height = 0;\n for (id in this.panels) {\n this.layout.width = Math.max(this.panels[id].layout.width, this.layout.width);\n this.layout.height += this.panels[id].layout.height;\n }\n this.layout.width = Math.max(this.layout.width, this.layout.min_width);\n this.layout.height = Math.max(this.layout.height, this.layout.min_height);\n }\n // Keep aspect ratio in agreement with dimensions\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n // Apply layout width and height as discrete values or viewbox values\n if (this.svg !== null) {\n if (this.layout.responsive_resize === 'both') {\n this.svg.attr('viewBox', '0 0 ' + this.layout.width + ' ' + this.layout.height).attr('preserveAspectRatio', 'xMinYMin meet');\n } else {\n this.svg.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n }\n // If the plot has been initialized then trigger some necessary render functions\n if (this.initialized) {\n this.panel_boundaries.position();\n this.dashboard.update();\n this.curtain.update();\n this.loader.update();\n }\n return this.emit('layout_changed');\n };\n /**\n * Create a new panel from a layout, and handle the work of initializing and placing the panel on the plot\n * @param {Object} layout\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Plot.prototype.addPanel = function (layout) {\n // Sanity checks\n if (typeof layout !== 'object') {\n throw new Error('Invalid panel layout passed to LocusZoom.Plot.prototype.addPanel()');\n }\n // Create the Panel and set its parent\n var panel = new LocusZoom.Panel(layout, this);\n // Store the Panel on the Plot\n this.panels[panel.id] = panel;\n // If a discrete y_index was set in the layout then adjust other panel y_index values to accommodate this one\n if (panel.layout.y_index !== null && !isNaN(panel.layout.y_index) && this.panel_ids_by_y_index.length > 0) {\n // Negative y_index values should count backwards from the end, so convert negatives to appropriate values here\n if (panel.layout.y_index < 0) {\n panel.layout.y_index = Math.max(this.panel_ids_by_y_index.length + panel.layout.y_index, 0);\n }\n this.panel_ids_by_y_index.splice(panel.layout.y_index, 0, panel.id);\n this.applyPanelYIndexesToPanelLayouts();\n } else {\n var length = this.panel_ids_by_y_index.push(panel.id);\n this.panels[panel.id].layout.y_index = length - 1;\n }\n // Determine if this panel was already in the layout.panels array.\n // If it wasn't, add it. Either way store the layout.panels array index on the panel.\n var layout_idx = null;\n this.layout.panels.forEach(function (panel_layout, idx) {\n if (panel_layout.id === panel.id) {\n layout_idx = idx;\n }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.panels.push(this.panels[panel.id].layout) - 1;\n }\n this.panels[panel.id].layout_idx = layout_idx;\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n this.positionPanels();\n // Initialize and load data into the new panel\n this.panels[panel.id].initialize();\n this.panels[panel.id].reMap();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n return this.panels[panel.id];\n };\n /**\n * Clear all state, tooltips, and other persisted data associated with one (or all) panel(s) in the plot\n *\n * This is useful when reloading an existing plot with new data, eg \"click for genome region\" links.\n * This is a utility method for custom usage. It is not fired automatically during normal rerender of existing panels\n * @param {String} [panelId] If provided, clear state for only this panel. Otherwise, clear state for all panels.\n * @param {('wipe'|'reset')} [mode='wipe'] Optionally specify how state should be cleared. `wipe` deletes all data\n * and is useful for when the panel is being removed; `reset` is best when the panel will be reused in place.\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.clearPanelData = function (panelId, mode) {\n mode = mode || 'wipe';\n // TODO: Add unit tests for this method\n var panelsList;\n if (panelId) {\n panelsList = [panelId];\n } else {\n panelsList = Object.keys(this.panels);\n }\n var self = this;\n panelsList.forEach(function (pid) {\n self.panels[pid].data_layer_ids_by_z_index.forEach(function (dlid) {\n var layer = self.panels[pid].data_layers[dlid];\n layer.destroyAllTooltips();\n delete self.layout.state[pid + '.' + dlid];\n if (mode === 'reset') {\n layer.setDefaultState();\n }\n });\n });\n return this;\n };\n /**\n * Remove the panel from the plot, and clear any state, tooltips, or other visual elements belonging to nested content\n * @param {String} id\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.removePanel = function (id) {\n if (!this.panels[id]) {\n throw new Error('Unable to remove panel, ID not found: ' + id);\n }\n // Hide all panel boundaries\n this.panel_boundaries.hide();\n // Destroy all tooltips and state vars for all data layers on the panel\n this.clearPanelData(id);\n // Remove all panel-level HTML overlay elements\n this.panels[id].loader.hide();\n this.panels[id].dashboard.destroy(true);\n this.panels[id].curtain.hide();\n // Remove the svg container for the panel if it exists\n if (this.panels[id].svg.container) {\n this.panels[id].svg.container.remove();\n }\n // Delete the panel and its presence in the plot layout and state\n this.layout.panels.splice(this.panels[id].layout_idx, 1);\n delete this.panels[id];\n delete this.layout.state[id];\n // Update layout_idx values for all remaining panels\n this.layout.panels.forEach(function (panel_layout, idx) {\n this.panels[panel_layout.id].layout_idx = idx;\n }.bind(this));\n // Remove the panel id from the y_index array\n this.panel_ids_by_y_index.splice(this.panel_ids_by_y_index.indexOf(id), 1);\n this.applyPanelYIndexesToPanelLayouts();\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n // Allow the plot to shrink when panels are removed, by forcing it to recalculate min dimensions from scratch\n this.layout.min_height = this._base_layout.min_height;\n this.layout.min_width = this._base_layout.min_width;\n this.positionPanels();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n this.emit('panel_removed', id);\n return this;\n };\n /**\n * Automatically position panels based on panel positioning rules and values.\n * Keep panels from overlapping vertically by adjusting origins, and keep the sum of proportional heights at 1.\n *\n * TODO: This logic currently only supports dynamic positioning of panels to prevent overlap in a VERTICAL orientation.\n * Some framework exists for positioning panels in horizontal orientations as well (width, proportional_width, origin.x, etc.)\n * but the logic for keeping these user-definable values straight approaches the complexity of a 2D box-packing algorithm.\n * That's complexity we don't need right now, and may not ever need, so it's on hiatus until a use case materializes.\n */\n LocusZoom.Plot.prototype.positionPanels = function () {\n var id;\n // We want to enforce that all x-linked panels have consistent horizontal margins\n // (to ensure that aligned items stay aligned despite inconsistent initial layout parameters)\n // NOTE: This assumes panels have consistent widths already. That should probably be enforced too!\n var x_linked_margins = {\n left: 0,\n right: 0\n };\n // Proportional heights for newly added panels default to null unless explicitly set, so determine appropriate\n // proportional heights for all panels with a null value from discretely set dimensions.\n // Likewise handle default nulls for proportional widths, but instead just force a value of 1 (full width)\n for (id in this.panels) {\n if (this.panels[id].layout.proportional_height === null) {\n this.panels[id].layout.proportional_height = this.panels[id].layout.height / this.layout.height;\n }\n if (this.panels[id].layout.proportional_width === null) {\n this.panels[id].layout.proportional_width = 1;\n }\n if (this.panels[id].layout.interaction.x_linked) {\n x_linked_margins.left = Math.max(x_linked_margins.left, this.panels[id].layout.margin.left);\n x_linked_margins.right = Math.max(x_linked_margins.right, this.panels[id].layout.margin.right);\n }\n }\n // Sum the proportional heights and then adjust all proportionally so that the sum is exactly 1\n var total_proportional_height = this.sumProportional('height');\n if (!total_proportional_height) {\n return this;\n }\n var proportional_adjustment = 1 / total_proportional_height;\n for (id in this.panels) {\n this.panels[id].layout.proportional_height *= proportional_adjustment;\n }\n // Update origins on all panels without changing plot-level dimensions yet\n // Also apply x-linked margins to x-linked panels, updating widths as needed\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n y_offset += this.panels[panel_id].layout.height;\n if (this.panels[panel_id].layout.interaction.x_linked) {\n var delta = Math.max(x_linked_margins.left - this.panels[panel_id].layout.margin.left, 0) + Math.max(x_linked_margins.right - this.panels[panel_id].layout.margin.right, 0);\n this.panels[panel_id].layout.width += delta;\n this.panels[panel_id].layout.margin.left = x_linked_margins.left;\n this.panels[panel_id].layout.margin.right = x_linked_margins.right;\n this.panels[panel_id].layout.cliparea.origin.x = x_linked_margins.left;\n }\n }.bind(this));\n var calculated_plot_height = y_offset;\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n this.panels[panel_id].layout.proportional_origin.y = this.panels[panel_id].layout.origin.y / calculated_plot_height;\n }.bind(this));\n // Update dimensions on the plot to accommodate repositioned panels\n this.setDimensions();\n // Set dimensions on all panels using newly set plot-level dimensions and panel-level proportional dimensions\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n this.panels[panel_id].setDimensions(this.layout.width * this.panels[panel_id].layout.proportional_width, this.layout.height * this.panels[panel_id].layout.proportional_height);\n }.bind(this));\n return this;\n };\n /**\n * Prepare the first rendering of the plot. This includes initializing the individual panels, but also creates shared\n * elements such as mouse events, panel guides/boundaries, and loader/curtain.\n *\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.initialize = function () {\n // Ensure proper responsive class is present on the containing node if called for\n if (this.layout.responsive_resize) {\n d3.select(this.container).classed('lz-container-responsive', true);\n }\n // Create an element/layer for containing mouse guides\n if (this.layout.mouse_guide) {\n var mouse_guide_svg = this.svg.append('g').attr('class', 'lz-mouse_guide').attr('id', this.id + '.mouse_guide');\n var mouse_guide_vertical_svg = mouse_guide_svg.append('rect').attr('class', 'lz-mouse_guide-vertical').attr('x', -1);\n var mouse_guide_horizontal_svg = mouse_guide_svg.append('rect').attr('class', 'lz-mouse_guide-horizontal').attr('y', -1);\n this.mouse_guide = {\n svg: mouse_guide_svg,\n vertical: mouse_guide_vertical_svg,\n horizontal: mouse_guide_horizontal_svg\n };\n }\n // Add curtain and loader prototpyes to the plot\n this.curtain = LocusZoom.generateCurtain.call(this);\n this.loader = LocusZoom.generateLoader.call(this);\n // Create the panel_boundaries object with show/position/hide methods\n this.panel_boundaries = {\n parent: this,\n hide_timeout: null,\n showing: false,\n dragging: false,\n selectors: [],\n corner_selector: null,\n show: function () {\n // Generate panel boundaries\n if (!this.showing && !this.parent.curtain.showing) {\n this.showing = true;\n // Loop through all panels to create a horizontal boundary for each\n this.parent.panel_ids_by_y_index.forEach(function (panel_id, panel_idx) {\n var selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip').attr('class', 'lz-panel-boundary').attr('title', 'Resize panel');\n selector.append('span');\n var panel_resize_drag = d3.behavior.drag();\n panel_resize_drag.on('dragstart', function () {\n this.dragging = true;\n }.bind(this));\n panel_resize_drag.on('dragend', function () {\n this.dragging = false;\n }.bind(this));\n panel_resize_drag.on('drag', function () {\n // First set the dimensions on the panel we're resizing\n var this_panel = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]];\n var original_panel_height = this_panel.layout.height;\n this_panel.setDimensions(this_panel.layout.width, this_panel.layout.height + d3.event.dy);\n var panel_height_change = this_panel.layout.height - original_panel_height;\n var new_calculated_plot_height = this.parent.layout.height + panel_height_change;\n // Next loop through all panels.\n // Update proportional dimensions for all panels including the one we've resized using discrete heights.\n // Reposition panels with a greater y-index than this panel to their appropriate new origin.\n this.parent.panel_ids_by_y_index.forEach(function (loop_panel_id, loop_panel_idx) {\n var loop_panel = this.parent.panels[this.parent.panel_ids_by_y_index[loop_panel_idx]];\n loop_panel.layout.proportional_height = loop_panel.layout.height / new_calculated_plot_height;\n if (loop_panel_idx > panel_idx) {\n loop_panel.setOrigin(loop_panel.layout.origin.x, loop_panel.layout.origin.y + panel_height_change);\n loop_panel.dashboard.position();\n }\n }.bind(this));\n // Reset dimensions on the entire plot and reposition panel boundaries\n this.parent.positionPanels();\n this.position();\n }.bind(this));\n selector.call(panel_resize_drag);\n this.parent.panel_boundaries.selectors.push(selector);\n }.bind(this));\n // Create a corner boundary / resize element on the bottom-most panel that resizes the entire plot\n var corner_selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip').attr('class', 'lz-panel-corner-boundary').attr('title', 'Resize plot');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-outer');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-inner');\n var corner_drag = d3.behavior.drag();\n corner_drag.on('dragstart', function () {\n this.dragging = true;\n }.bind(this));\n corner_drag.on('dragend', function () {\n this.dragging = false;\n }.bind(this));\n corner_drag.on('drag', function () {\n this.setDimensions(this.layout.width + d3.event.dx, this.layout.height + d3.event.dy);\n }.bind(this.parent));\n corner_selector.call(corner_drag);\n this.parent.panel_boundaries.corner_selector = corner_selector;\n }\n return this.position();\n },\n position: function () {\n if (!this.showing) {\n return this;\n }\n // Position panel boundaries\n var plot_page_origin = this.parent.getPageOrigin();\n this.selectors.forEach(function (selector, panel_idx) {\n var panel_page_origin = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].getPageOrigin();\n var left = plot_page_origin.x;\n var top = panel_page_origin.y + this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].layout.height - 12;\n var width = this.parent.layout.width - 1;\n selector.style({\n top: top + 'px',\n left: left + 'px',\n width: width + 'px'\n });\n selector.select('span').style({ width: width + 'px' });\n }.bind(this));\n // Position corner selector\n var corner_padding = 10;\n var corner_size = 16;\n this.corner_selector.style({\n top: plot_page_origin.y + this.parent.layout.height - corner_padding - corner_size + 'px',\n left: plot_page_origin.x + this.parent.layout.width - corner_padding - corner_size + 'px'\n });\n return this;\n },\n hide: function () {\n if (!this.showing) {\n return this;\n }\n this.showing = false;\n // Remove panel boundaries\n this.selectors.forEach(function (selector) {\n selector.remove();\n });\n this.selectors = [];\n // Remove corner boundary\n this.corner_selector.remove();\n this.corner_selector = null;\n return this;\n }\n };\n // Show panel boundaries stipulated by the layout (basic toggle, only show on mouse over plot)\n if (this.layout.panel_boundaries) {\n d3.select(this.svg.node().parentNode).on('mouseover.' + this.id + '.panel_boundaries', function () {\n clearTimeout(this.panel_boundaries.hide_timeout);\n this.panel_boundaries.show();\n }.bind(this));\n d3.select(this.svg.node().parentNode).on('mouseout.' + this.id + '.panel_boundaries', function () {\n this.panel_boundaries.hide_timeout = setTimeout(function () {\n this.panel_boundaries.hide();\n }.bind(this), 300);\n }.bind(this));\n }\n // Create the dashboard object and immediately show it\n this.dashboard = new LocusZoom.Dashboard(this).show();\n // Initialize all panels\n for (var id in this.panels) {\n this.panels[id].initialize();\n }\n // Define plot-level mouse events\n var namespace = '.' + this.id;\n if (this.layout.mouse_guide) {\n var mouseout_mouse_guide = function () {\n this.mouse_guide.vertical.attr('x', -1);\n this.mouse_guide.horizontal.attr('y', -1);\n }.bind(this);\n var mousemove_mouse_guide = function () {\n var coords = d3.mouse(this.svg.node());\n this.mouse_guide.vertical.attr('x', coords[0]);\n this.mouse_guide.horizontal.attr('y', coords[1]);\n }.bind(this);\n this.svg.on('mouseout' + namespace + '-mouse_guide', mouseout_mouse_guide).on('touchleave' + namespace + '-mouse_guide', mouseout_mouse_guide).on('mousemove' + namespace + '-mouse_guide', mousemove_mouse_guide);\n }\n var mouseup = function () {\n this.stopDrag();\n }.bind(this);\n var mousemove = function () {\n if (this.interaction.dragging) {\n var coords = d3.mouse(this.svg.node());\n if (d3.event) {\n d3.event.preventDefault();\n }\n this.interaction.dragging.dragged_x = coords[0] - this.interaction.dragging.start_x;\n this.interaction.dragging.dragged_y = coords[1] - this.interaction.dragging.start_y;\n this.panels[this.interaction.panel_id].render();\n this.interaction.linked_panel_ids.forEach(function (panel_id) {\n this.panels[panel_id].render();\n }.bind(this));\n }\n }.bind(this);\n this.svg.on('mouseup' + namespace, mouseup).on('touchend' + namespace, mouseup).on('mousemove' + namespace, mousemove).on('touchmove' + namespace, mousemove);\n // Add an extra namespaced mouseup handler to the containing body, if there is one\n // This helps to stop interaction events gracefully when dragging outside of the plot element\n if (!d3.select('body').empty()) {\n d3.select('body').on('mouseup' + namespace, mouseup).on('touchend' + namespace, mouseup);\n }\n this.on('match_requested', function (eventData) {\n // Layers can broadcast that a specific point has been selected, and the plot will tell every other layer\n // to look for that value. Whenever a point is de-selected, it clears the match.\n var data = eventData.data;\n var to_send = data.active ? data.value : null;\n this.applyState({ lz_match_value: to_send });\n }.bind(this));\n this.initialized = true;\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n var client_rect = this.svg.node().getBoundingClientRect();\n var width = client_rect.width ? client_rect.width : this.layout.width;\n var height = client_rect.height ? client_rect.height : this.layout.height;\n this.setDimensions(width, height);\n return this;\n };\n /**\n * Refresh (or fetch) a plot's data from sources, regardless of whether position or state has changed\n * @returns {Promise}\n */\n LocusZoom.Plot.prototype.refresh = function () {\n return this.applyState();\n };\n /**\n * A user-defined callback function that can receive (and potentially act on) new plot data.\n * @callback externalDataCallback\n * @param {Object} new_data The body resulting from a data request. This represents the same information that would be passed to\n * a data layer making an equivalent request.\n */\n /**\n * A user-defined callback function that can respond to errors received during a previous operation\n * @callback externalErrorCallback\n * @param err A representation of the error that occurred\n */\n /**\n * Allow newly fetched data to be made available outside the LocusZoom plot. For example, a callback could be\n * registered to draw an HTML table of top GWAS hits, and update that table whenever the plot region changes.\n *\n * This is a convenience method for external hooks. It registers an event listener and returns parsed data,\n * using the same fields syntax and underlying methods as data layers.\n *\n * @param {String[]} fields An array of field names and transforms, in the same syntax used by a data layer.\n * Different data sources should be prefixed by the source name.\n * @param {externalDataCallback} success_callback Used defined function that is automatically called any time that\n * new data is received by the plot.\n * @param {Object} [opts] Options\n * @param {externalErrorCallback} [opts.onerror] User defined function that is automatically called if a problem\n * occurs during the data request or subsequent callback operations\n * @param {boolean} [opts.discrete=false] Normally the callback will subscribe to the combined body from the chain,\n * which may not be in a format that matches what the external callback wants to do. If discrete=true, returns the\n * uncombined record info\n * @return {function} The newly created event listener, to allow for later cleanup/removal\n */\n LocusZoom.Plot.prototype.subscribeToData = function (fields, success_callback, opts) {\n opts = opts || {};\n // Register an event listener that is notified whenever new data has been rendered\n var error_callback = opts.onerror || function (err) {\n console.log('An error occurred while acting on an external callback', err);\n };\n var self = this;\n var listener = function () {\n try {\n self.lzd.getData(self.state, fields).then(function (new_data) {\n success_callback(opts.discrete ? new_data.discrete : new_data.body);\n }).catch(error_callback);\n } catch (error) {\n // In certain cases, errors are thrown before a promise can be generated, and LZ error display seems to rely on these errors bubbling up\n error_callback(error);\n }\n };\n this.on('data_rendered', listener);\n return listener;\n };\n /**\n * Update state values and trigger a pull for fresh data on all data sources for all data layers\n * @param state_changes\n * @returns {Promise} A promise that resolves when all data fetch and update operations are complete\n */\n LocusZoom.Plot.prototype.applyState = function (state_changes) {\n state_changes = state_changes || {};\n if (typeof state_changes != 'object') {\n throw new Error('LocusZoom.applyState only accepts an object; ' + typeof state_changes + ' given');\n }\n // First make a copy of the current (old) state to work with\n var new_state = JSON.parse(JSON.stringify(this.state));\n // Apply changes by top-level property to the new state\n for (var property in state_changes) {\n new_state[property] = state_changes[property];\n }\n // Validate the new state (may do nothing, may do a lot, depends on how the user has things set up)\n new_state = LocusZoom.validateState(new_state, this.layout);\n // Apply new state to the actual state\n for (property in new_state) {\n this.state[property] = new_state[property];\n }\n // Generate requests for all panels given new state\n this.emit('data_requested');\n this.remap_promises = [];\n this.loading_data = true;\n for (var id in this.panels) {\n this.remap_promises.push(this.panels[id].reMap());\n }\n return Promise.all(this.remap_promises).catch(function (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n this.loading_data = false;\n }.bind(this)).then(function () {\n // Update dashboard / components\n this.dashboard.update();\n // Apply panel-level state values\n this.panel_ids_by_y_index.forEach(function (panel_id) {\n var panel = this.panels[panel_id];\n panel.dashboard.update();\n // Apply data-layer-level state values\n panel.data_layer_ids_by_z_index.forEach(function (data_layer_id) {\n var data_layer = this.data_layers[data_layer_id];\n var state_id = panel_id + '.' + data_layer_id;\n for (var property in this.state[state_id]) {\n if (!this.state[state_id].hasOwnProperty(property)) {\n continue;\n }\n if (Array.isArray(this.state[state_id][property])) {\n this.state[state_id][property].forEach(function (element_id) {\n try {\n this.setElementStatus(property, this.getElementById(element_id), true);\n } catch (e) {\n console.warn('Unable to apply state: ' + state_id + ', ' + property);\n console.error(e);\n }\n }.bind(data_layer));\n }\n }\n }.bind(panel));\n }.bind(this));\n // Emit events\n this.emit('layout_changed');\n this.emit('data_rendered');\n this.emit('state_changed', state_changes);\n this.loading_data = false;\n }.bind(this));\n };\n /**\n * Register interactions along the specified axis, provided that the target panel allows interaction.\n *\n * @param {LocusZoom.Panel} panel\n * @param {('x_tick'|'y1_tick'|'y2_tick')} method The direction (axis) along which dragging is being performed.\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.startDrag = function (panel, method) {\n panel = panel || null;\n method = method || null;\n var axis = null;\n switch (method) {\n case 'background':\n case 'x_tick':\n axis = 'x';\n break;\n case 'y1_tick':\n axis = 'y1';\n break;\n case 'y2_tick':\n axis = 'y2';\n break;\n }\n if (!(panel instanceof LocusZoom.Panel) || !axis || !this.canInteract()) {\n return this.stopDrag();\n }\n var coords = d3.mouse(this.svg.node());\n this.interaction = {\n panel_id: panel.id,\n linked_panel_ids: panel.getLinkedPanelIds(axis),\n dragging: {\n method: method,\n start_x: coords[0],\n start_y: coords[1],\n dragged_x: 0,\n dragged_y: 0,\n axis: axis\n }\n };\n this.svg.style('cursor', 'all-scroll');\n return this;\n };\n /**\n * Process drag interactions across the target panel and synchronize plot state across other panels in sync;\n * clear the event when complete\n * @returns {LocusZoom.Plot}\n */\n LocusZoom.Plot.prototype.stopDrag = function () {\n if (!this.interaction.dragging) {\n return this;\n }\n if (typeof this.panels[this.interaction.panel_id] != 'object') {\n this.interaction = {};\n return this;\n }\n var panel = this.panels[this.interaction.panel_id];\n // Helper function to find the appropriate axis layouts on child data layers\n // Once found, apply the extent as floor/ceiling and remove all other directives\n // This forces all associated axes to conform to the extent generated by a drag action\n var overrideAxisLayout = function (axis, axis_number, extent) {\n panel.data_layer_ids_by_z_index.forEach(function (id) {\n if (panel.data_layers[id].layout[axis + '_axis'].axis === axis_number) {\n panel.data_layers[id].layout[axis + '_axis'].floor = extent[0];\n panel.data_layers[id].layout[axis + '_axis'].ceiling = extent[1];\n delete panel.data_layers[id].layout[axis + '_axis'].lower_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].upper_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].min_extent;\n delete panel.data_layers[id].layout[axis + '_axis'].ticks;\n }\n });\n };\n switch (this.interaction.dragging.method) {\n case 'background':\n case 'x_tick':\n if (this.interaction.dragging.dragged_x !== 0) {\n overrideAxisLayout('x', 1, panel.x_extent);\n this.applyState({\n start: panel.x_extent[0],\n end: panel.x_extent[1]\n });\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n if (this.interaction.dragging.dragged_y !== 0) {\n // TODO: Hardcoded assumption of only two possible axes with single-digit #s (switch/case)\n var y_axis_number = parseInt(this.interaction.dragging.method[1]);\n overrideAxisLayout('y', y_axis_number, panel['y' + y_axis_number + '_extent']);\n }\n break;\n }\n this.interaction = {};\n this.svg.style('cursor', null);\n return this;\n };\n /* global LocusZoom */\n 'use strict';\n /**\n * A panel is an abstract class representing a subdivision of the LocusZoom stage\n * to display a distinct data representation as a collection of data layers.\n * @class\n * @param {Object} layout\n * @param {LocusZoom.Plot|null} parent\n*/\n LocusZoom.Panel = function (layout, parent) {\n if (typeof layout !== 'object') {\n throw new Error('Unable to create panel, invalid layout');\n }\n /** @member {LocusZoom.Plot|null} */\n this.parent = parent || null;\n /** @member {LocusZoom.Plot|null} */\n this.parent_plot = parent;\n // Ensure a valid ID is present. If there is no valid ID then generate one\n if (typeof layout.id !== 'string' || !layout.id.length) {\n if (!this.parent) {\n layout.id = 'p' + Math.floor(Math.random() * Math.pow(10, 8));\n } else {\n var id = null;\n var generateID = function () {\n id = 'p' + Math.floor(Math.random() * Math.pow(10, 8));\n if (id == null || typeof this.parent.panels[id] != 'undefined') {\n id = generateID();\n }\n }.bind(this);\n layout.id = id;\n }\n } else if (this.parent) {\n if (typeof this.parent.panels[layout.id] !== 'undefined') {\n throw new Error('Cannot create panel with id [' + layout.id + ']; panel with that id already exists');\n }\n }\n /** @member {String} */\n this.id = layout.id;\n /** @member {Boolean} */\n this.initialized = false;\n /**\n * The index of this panel in the parent plot's `layout.panels`\n * @member {number}\n * */\n this.layout_idx = null;\n /** @member {Object} */\n this.svg = {};\n /**\n * A JSON-serializable object used to describe the composition of the Panel\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.Panel.DefaultLayout);\n // Define state parameters specific to this panel\n if (this.parent) {\n /** @member {Object} */\n this.state = this.parent.state;\n /** @member {String} */\n this.state_id = this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n } else {\n this.state = null;\n this.state_id = null;\n }\n /** @member {Object} */\n this.data_layers = {};\n /** @member {String[]} */\n this.data_layer_ids_by_z_index = [];\n /** @protected */\n this.applyDataLayerZIndexesToDataLayerLayouts = function () {\n this.data_layer_ids_by_z_index.forEach(function (dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n }.bind(this);\n /**\n * Track data requests in progress\n * @member {Promise[]}\n * @protected\n */\n this.data_promises = [];\n /** @member {d3.scale} */\n this.x_scale = null;\n /** @member {d3.scale} */\n this.y1_scale = null;\n /** @member {d3.scale} */\n this.y2_scale = null;\n /** @member {d3.extent} */\n this.x_extent = null;\n /** @member {d3.extent} */\n this.y1_extent = null;\n /** @member {d3.extent} */\n this.y2_extent = null;\n /** @member {Number[]} */\n this.x_ticks = [];\n /** @member {Number[]} */\n this.y1_ticks = [];\n /** @member {Number[]} */\n this.y2_ticks = [];\n /**\n * A timeout ID as returned by setTimeout\n * @protected\n * @member {number}\n */\n this.zoom_timeout = null;\n /** @returns {string} */\n this.getBaseId = function () {\n return this.parent.id + '.' + this.id;\n };\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [],\n 'element_selection': [],\n 'match_requested': [] // A data layer is attempting to highlight matching points (internal use only)\n };\n /**\n * There are several events that a LocusZoom panel can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following panel-level events are currently supported:\n * - `layout_changed` - context: panel - Any aspect of the panel's layout (including dimensions or state) has changed.\n * - `data_requested` - context: panel - A request for new data from any data source used in the panel has been made.\n * - `data_rendered` - context: panel - Data from a request has been received and rendered in the panel.\n * - `element_clicked` - context: panel - A data element in any of the panel's data layers has been clicked.\n * - `element_selection` - context: panel - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `panel.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * panel itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of the event (as defined in `event_hooks`)\n * @param {function} hook\n * @returns {function} The registered event listener\n */\n this.on = function (event, hook) {\n // TODO: Dry plot and panel event code into a shared mixin\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Panel}\n */\n this.off = function (event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n *\n * There is a shorter overloaded form of this method: if the event does not have any data, the second\n * argument can be a boolean to control bubbling\n *\n * @param {string} event A known event name\n * @param {*} [eventData] Data or event description that will be passed to the event listener\n * @param {boolean} [bubble=false] Whether to bubble the event to the parent\n * @returns {LocusZoom.Panel}\n */\n this.emit = function (event, eventData, bubble) {\n bubble = bubble || false;\n // TODO: DRY this with the parent plot implementation. Ensure interfaces remain compatible.\n // TODO: Improve documentation for overloaded method signature (JSDoc may have trouble here)\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n if (typeof eventData === 'boolean' && arguments.length === 2) {\n // Overloaded method signature: emit(event, bubble)\n bubble = eventData;\n eventData = null;\n }\n var sourceID = this.getBaseId();\n var self = this;\n var eventContext = {\n sourceID: sourceID,\n data: eventData || null\n };\n this.event_hooks[event].forEach(function (hookToRun) {\n // By default, any handlers fired here will see the panel as the value of `this`. If a bound function is\n // registered as a handler, the previously bound `this` will override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n if (bubble && this.parent) {\n this.parent.emit(event, eventContext);\n }\n return this;\n };\n /**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\n this.getPageOrigin = function () {\n var plot_origin = this.parent.getPageOrigin();\n return {\n x: plot_origin.x + this.layout.origin.x,\n y: plot_origin.y + this.layout.origin.y\n };\n };\n // Initialize the layout\n this.initializeLayout();\n return this;\n };\n /**\n * Default panel layout\n * @static\n * @type {Object}\n */\n LocusZoom.Panel.DefaultLayout = {\n title: {\n text: '',\n style: {},\n x: 10,\n y: 22\n },\n y_index: null,\n width: 0,\n height: 0,\n origin: {\n x: 0,\n y: null\n },\n min_width: 1,\n min_height: 1,\n proportional_width: null,\n proportional_height: null,\n proportional_origin: {\n x: 0,\n y: null\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 0,\n left: 0\n },\n background_click: 'clear_selections',\n dashboard: { components: [] },\n cliparea: {\n height: 0,\n width: 0,\n origin: {\n x: 0,\n y: 0\n }\n },\n axes: {\n // These are the only axes supported!!\n x: {},\n y1: {},\n y2: {}\n },\n legend: null,\n interaction: {\n drag_background_to_pan: false,\n drag_x_ticks_to_scale: false,\n drag_y1_ticks_to_scale: false,\n drag_y2_ticks_to_scale: false,\n scroll_to_zoom: false,\n x_linked: false,\n y1_linked: false,\n y2_linked: false\n },\n data_layers: []\n };\n /**\n * Prepare the panel for first use by performing parameter validation, creating axes, setting default dimensions,\n * and preparing / positioning data layers as appropriate.\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.initializeLayout = function () {\n // If the layout is missing BOTH width and proportional width then set the proportional width to 1.\n // This will default the panel to taking up the full width of the plot.\n if (this.layout.width === 0 && this.layout.proportional_width === null) {\n this.layout.proportional_width = 1;\n }\n // If the layout is missing BOTH height and proportional height then set the proportional height to\n // an equal share of the plot's current height.\n if (this.layout.height === 0 && this.layout.proportional_height === null) {\n var panel_count = Object.keys(this.parent.panels).length;\n if (panel_count > 0) {\n this.layout.proportional_height = 1 / panel_count;\n } else {\n this.layout.proportional_height = 1;\n }\n }\n // Set panel dimensions, origin, and margin\n this.setDimensions();\n this.setOrigin();\n this.setMargin();\n // Set ranges\n // TODO: Define stub values in constructor\n this.x_range = [\n 0,\n this.layout.cliparea.width\n ];\n this.y1_range = [\n this.layout.cliparea.height,\n 0\n ];\n this.y2_range = [\n this.layout.cliparea.height,\n 0\n ];\n // Initialize panel axes\n [\n 'x',\n 'y1',\n 'y2'\n ].forEach(function (axis) {\n if (!Object.keys(this.layout.axes[axis]).length || this.layout.axes[axis].render === false) {\n // The default layout sets the axis to an empty object, so set its render boolean here\n this.layout.axes[axis].render = false;\n } else {\n this.layout.axes[axis].render = true;\n this.layout.axes[axis].label = this.layout.axes[axis].label || null;\n this.layout.axes[axis].label_function = this.layout.axes[axis].label_function || null;\n }\n }.bind(this));\n // Add data layers (which define x and y extents)\n this.layout.data_layers.forEach(function (data_layer_layout) {\n this.addDataLayer(data_layer_layout);\n }.bind(this));\n return this;\n };\n /**\n * Set the dimensions for the panel. If passed with no arguments will calculate optimal size based on layout\n * directives and the available area within the plot. If passed discrete width (number) and height (number) will\n * attempt to resize the panel to them, but may be limited by minimum dimensions defined on the plot or panel.\n *\n * @public\n * @param {number} [width]\n * @param {number} [height]\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.setDimensions = function (width, height) {\n if (typeof width != 'undefined' && typeof height != 'undefined') {\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n }\n } else {\n if (this.layout.proportional_width !== null) {\n this.layout.width = Math.max(this.layout.proportional_width * this.parent.layout.width, this.layout.min_width);\n }\n if (this.layout.proportional_height !== null) {\n this.layout.height = Math.max(this.layout.proportional_height * this.parent.layout.height, this.layout.min_height);\n }\n }\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n if (this.svg.clipRect) {\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n if (this.initialized) {\n this.render();\n this.curtain.update();\n this.loader.update();\n this.dashboard.update();\n if (this.legend) {\n this.legend.position();\n }\n }\n return this;\n };\n /**\n * Set panel origin on the plot, and re-render as appropriate\n *\n * @public\n * @param {number} x\n * @param {number} y\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.setOrigin = function (x, y) {\n if (!isNaN(x) && x >= 0) {\n this.layout.origin.x = Math.max(Math.round(+x), 0);\n }\n if (!isNaN(y) && y >= 0) {\n this.layout.origin.y = Math.max(Math.round(+y), 0);\n }\n if (this.initialized) {\n this.render();\n }\n return this;\n };\n /**\n * Set margins around this panel\n * @public\n * @param {number} top\n * @param {number} right\n * @param {number} bottom\n * @param {number} left\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.setMargin = function (top, right, bottom, left) {\n var extra;\n if (!isNaN(top) && top >= 0) {\n this.layout.margin.top = Math.max(Math.round(+top), 0);\n }\n if (!isNaN(right) && right >= 0) {\n this.layout.margin.right = Math.max(Math.round(+right), 0);\n }\n if (!isNaN(bottom) && bottom >= 0) {\n this.layout.margin.bottom = Math.max(Math.round(+bottom), 0);\n }\n if (!isNaN(left) && left >= 0) {\n this.layout.margin.left = Math.max(Math.round(+left), 0);\n }\n if (this.layout.margin.top + this.layout.margin.bottom > this.layout.height) {\n extra = Math.floor((this.layout.margin.top + this.layout.margin.bottom - this.layout.height) / 2);\n this.layout.margin.top -= extra;\n this.layout.margin.bottom -= extra;\n }\n if (this.layout.margin.left + this.layout.margin.right > this.layout.width) {\n extra = Math.floor((this.layout.margin.left + this.layout.margin.right - this.layout.width) / 2);\n this.layout.margin.left -= extra;\n this.layout.margin.right -= extra;\n }\n [\n 'top',\n 'right',\n 'bottom',\n 'left'\n ].forEach(function (m) {\n this.layout.margin[m] = Math.max(this.layout.margin[m], 0);\n }.bind(this));\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n this.layout.cliparea.origin.x = this.layout.margin.left;\n this.layout.cliparea.origin.y = this.layout.margin.top;\n if (this.initialized) {\n this.render();\n }\n return this;\n };\n /**\n * Set the title for the panel. If passed an object, will merge the object with the existing layout configuration, so\n * that all or only some of the title layout object's parameters can be customized. If passed null, false, or an empty\n * string, the title DOM element will be set to display: none.\n *\n * @param {string|object|null} title The title text, or an object with additional configuration\n * @param {string} title.text Text to display. Since titles are rendered as SVG text, HTML and newlines will not be rendered.\n * @param {number} title.x X-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n * @param {number} title.y Y-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n NOTE: SVG y values go from the top down, so the SVG origin of (0,0) is in the top left corner.\n * @param {object} title.style CSS styles object to be applied to the title's DOM element.\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.setTitle = function (title) {\n if (typeof this.layout.title == 'string') {\n var text = this.layout.title;\n this.layout.title = {\n text: text,\n x: 0,\n y: 0,\n style: {}\n };\n }\n if (typeof title == 'string') {\n this.layout.title.text = title;\n } else if (typeof title == 'object' && title !== null) {\n this.layout.title = LocusZoom.Layouts.merge(title, this.layout.title);\n }\n if (this.layout.title.text.length) {\n this.title.attr('display', null).attr('x', parseFloat(this.layout.title.x)).attr('y', parseFloat(this.layout.title.y)).style(this.layout.title.style).text(this.layout.title.text);\n } else {\n this.title.attr('display', 'none');\n }\n return this;\n };\n /**\n * Prepare the first rendering of the panel. This includes drawing the individual data layers, but also creates shared\n * elements such as axes, title, and loader/curtain.\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.initialize = function () {\n // Append a container group element to house the main panel group element and the clip path\n // Position with initial layout parameters\n this.svg.container = this.parent.svg.append('g').attr('id', this.getBaseId() + '.panel_container').attr('transform', 'translate(' + (this.layout.origin.x || 0) + ',' + (this.layout.origin.y || 0) + ')');\n // Append clip path to the parent svg element, size with initial layout parameters\n var clipPath = this.svg.container.append('clipPath').attr('id', this.getBaseId() + '.clip');\n this.svg.clipRect = clipPath.append('rect').attr('width', this.layout.width).attr('height', this.layout.height);\n // Append svg group for rendering all panel child elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g').attr('id', this.getBaseId() + '.panel').attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n // Add curtain and loader prototypes to the panel\n /** @member {Object} */\n this.curtain = LocusZoom.generateCurtain.call(this);\n /** @member {Object} */\n this.loader = LocusZoom.generateLoader.call(this);\n /**\n * Create the dashboard object and hang components on it as defined by panel layout\n * @member {LocusZoom.Dashboard}\n */\n this.dashboard = new LocusZoom.Dashboard(this);\n // Inner border\n this.inner_border = this.svg.group.append('rect').attr('class', 'lz-panel-background').on('click', function () {\n if (this.layout.background_click === 'clear_selections') {\n this.clearSelections();\n }\n }.bind(this));\n // Add the title\n /** @member {Element} */\n this.title = this.svg.group.append('text').attr('class', 'lz-panel-title');\n if (typeof this.layout.title != 'undefined') {\n this.setTitle();\n }\n // Initialize Axes\n this.svg.x_axis = this.svg.group.append('g').attr('id', this.getBaseId() + '.x_axis').attr('class', 'lz-x lz-axis');\n if (this.layout.axes.x.render) {\n this.svg.x_axis_label = this.svg.x_axis.append('text').attr('class', 'lz-x lz-axis lz-label').attr('text-anchor', 'middle');\n }\n this.svg.y1_axis = this.svg.group.append('g').attr('id', this.getBaseId() + '.y1_axis').attr('class', 'lz-y lz-y1 lz-axis');\n if (this.layout.axes.y1.render) {\n this.svg.y1_axis_label = this.svg.y1_axis.append('text').attr('class', 'lz-y1 lz-axis lz-label').attr('text-anchor', 'middle');\n }\n this.svg.y2_axis = this.svg.group.append('g').attr('id', this.getBaseId() + '.y2_axis').attr('class', 'lz-y lz-y2 lz-axis');\n if (this.layout.axes.y2.render) {\n this.svg.y2_axis_label = this.svg.y2_axis.append('text').attr('class', 'lz-y2 lz-axis lz-label').attr('text-anchor', 'middle');\n }\n // Initialize child Data Layers\n this.data_layer_ids_by_z_index.forEach(function (id) {\n this.data_layers[id].initialize();\n }.bind(this));\n /**\n * Legend object, as defined by panel layout and child data layer layouts\n * @member {LocusZoom.Legend}\n * */\n this.legend = null;\n if (this.layout.legend) {\n this.legend = new LocusZoom.Legend(this);\n }\n // Establish panel background drag interaction mousedown event handler (on the panel background)\n if (this.layout.interaction.drag_background_to_pan) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var mousedown = function () {\n this.parent.startDrag(this, 'background');\n }.bind(this);\n this.svg.container.select('.lz-panel-background').on('mousedown' + namespace + '.background', mousedown).on('touchstart' + namespace + '.background', mousedown);\n }\n return this;\n };\n /**\n * Refresh the sort order of all data layers (called by data layer moveUp and moveDown methods)\n */\n LocusZoom.Panel.prototype.resortDataLayers = function () {\n var sort = [];\n this.data_layer_ids_by_z_index.forEach(function (id) {\n sort.push(this.data_layers[id].layout.z_index);\n }.bind(this));\n this.svg.group.selectAll('g.lz-data_layer-container').data(sort).sort(d3.ascending);\n this.applyDataLayerZIndexesToDataLayerLayouts();\n };\n /**\n * Get an array of panel IDs that are axis-linked to this panel\n * @param {('x'|'y1'|'y2')} axis\n * @returns {Array}\n */\n LocusZoom.Panel.prototype.getLinkedPanelIds = function (axis) {\n axis = axis || null;\n var linked_panel_ids = [];\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(axis) === -1) {\n return linked_panel_ids;\n }\n if (!this.layout.interaction[axis + '_linked']) {\n return linked_panel_ids;\n }\n this.parent.panel_ids_by_y_index.forEach(function (panel_id) {\n if (panel_id !== this.id && this.parent.panels[panel_id].layout.interaction[axis + '_linked']) {\n linked_panel_ids.push(panel_id);\n }\n }.bind(this));\n return linked_panel_ids;\n };\n /**\n * Move a panel up relative to others by y-index\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.moveUp = function () {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index - 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index - 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index - 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n };\n /**\n * Move a panel down (y-axis) relative to others in the plot\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.moveDown = function () {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index + 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index + 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index + 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n };\n /**\n * Create a new data layer from a provided layout object. Should have the keys specified in `DefaultLayout`\n * Will automatically add at the top (depth/z-index) of the panel unless explicitly directed differently\n * in the layout provided.\n * @param {object} layout\n * @returns {*}\n */\n LocusZoom.Panel.prototype.addDataLayer = function (layout) {\n // Sanity checks\n if (typeof layout !== 'object' || typeof layout.id !== 'string' || !layout.id.length) {\n throw new Error('Invalid data layer layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n if (typeof this.data_layers[layout.id] !== 'undefined') {\n throw new Error('Cannot create data_layer with id [' + layout.id + ']; data layer with that id already exists in the panel');\n }\n if (typeof layout.type !== 'string') {\n throw new Error('Invalid data layer type in layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n // If the layout defines a y axis make sure the axis number is set and is 1 or 2 (default to 1)\n if (typeof layout.y_axis == 'object' && (typeof layout.y_axis.axis == 'undefined' || [\n 1,\n 2\n ].indexOf(layout.y_axis.axis) === -1)) {\n layout.y_axis.axis = 1;\n }\n // Create the Data Layer\n var data_layer = LocusZoom.DataLayers.get(layout.type, layout, this);\n // Store the Data Layer on the Panel\n this.data_layers[data_layer.id] = data_layer;\n // If a discrete z_index was set in the layout then adjust other data layer z_index values to accommodate this one\n if (data_layer.layout.z_index !== null && !isNaN(data_layer.layout.z_index) && this.data_layer_ids_by_z_index.length > 0) {\n // Negative z_index values should count backwards from the end, so convert negatives to appropriate values here\n if (data_layer.layout.z_index < 0) {\n data_layer.layout.z_index = Math.max(this.data_layer_ids_by_z_index.length + data_layer.layout.z_index, 0);\n }\n this.data_layer_ids_by_z_index.splice(data_layer.layout.z_index, 0, data_layer.id);\n this.data_layer_ids_by_z_index.forEach(function (dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n } else {\n var length = this.data_layer_ids_by_z_index.push(data_layer.id);\n this.data_layers[data_layer.id].layout.z_index = length - 1;\n }\n // Determine if this data layer was already in the layout.data_layers array.\n // If it wasn't, add it. Either way store the layout.data_layers array index on the data_layer.\n var layout_idx = null;\n this.layout.data_layers.forEach(function (data_layer_layout, idx) {\n if (data_layer_layout.id === data_layer.id) {\n layout_idx = idx;\n }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.data_layers.push(this.data_layers[data_layer.id].layout) - 1;\n }\n this.data_layers[data_layer.id].layout_idx = layout_idx;\n return this.data_layers[data_layer.id];\n };\n /**\n * Remove a data layer by id\n * @param {string} id\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.removeDataLayer = function (id) {\n if (!this.data_layers[id]) {\n throw new Error('Unable to remove data layer, ID not found: ' + id);\n }\n // Destroy all tooltips for the data layer\n this.data_layers[id].destroyAllTooltips();\n // Remove the svg container for the data layer if it exists\n if (this.data_layers[id].svg.container) {\n this.data_layers[id].svg.container.remove();\n }\n // Delete the data layer and its presence in the panel layout and state\n this.layout.data_layers.splice(this.data_layers[id].layout_idx, 1);\n delete this.state[this.data_layers[id].state_id];\n delete this.data_layers[id];\n // Remove the data_layer id from the z_index array\n this.data_layer_ids_by_z_index.splice(this.data_layer_ids_by_z_index.indexOf(id), 1);\n // Update layout_idx and layout.z_index values for all remaining data_layers\n this.applyDataLayerZIndexesToDataLayerLayouts();\n this.layout.data_layers.forEach(function (data_layer_layout, idx) {\n this.data_layers[data_layer_layout.id].layout_idx = idx;\n }.bind(this));\n return this;\n };\n /**\n * Clear all selections on all data layers\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.clearSelections = function () {\n this.data_layer_ids_by_z_index.forEach(function (id) {\n this.data_layers[id].setAllElementStatus('selected', false);\n }.bind(this));\n return this;\n };\n /**\n * When the parent plot changes state, adjust the panel accordingly. For example, this may include fetching new data\n * from the API as the viewing region changes\n * @returns {Promise}\n */\n LocusZoom.Panel.prototype.reMap = function () {\n this.emit('data_requested');\n this.data_promises = [];\n // Remove any previous error messages before attempting to load new data\n this.curtain.hide();\n // Trigger reMap on each Data Layer\n for (var id in this.data_layers) {\n try {\n this.data_promises.push(this.data_layers[id].reMap());\n } catch (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }\n }\n // When all finished trigger a render\n return Promise.all(this.data_promises).then(function () {\n this.initialized = true;\n this.render();\n this.emit('layout_changed', true);\n this.emit('data_rendered');\n }.bind(this)).catch(function (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }.bind(this));\n };\n /**\n * Iterate over data layers to generate panel axis extents\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.generateExtents = function () {\n // Reset extents\n [\n 'x',\n 'y1',\n 'y2'\n ].forEach(function (axis) {\n this[axis + '_extent'] = null;\n }.bind(this));\n // Loop through the data layers\n for (var id in this.data_layers) {\n var data_layer = this.data_layers[id];\n // If defined and not decoupled, merge the x extent of the data layer with the panel's x extent\n if (data_layer.layout.x_axis && !data_layer.layout.x_axis.decoupled) {\n this.x_extent = d3.extent((this.x_extent || []).concat(data_layer.getAxisExtent('x')));\n }\n // If defined and not decoupled, merge the y extent of the data layer with the panel's appropriate y extent\n if (data_layer.layout.y_axis && !data_layer.layout.y_axis.decoupled) {\n var y_axis = 'y' + data_layer.layout.y_axis.axis;\n this[y_axis + '_extent'] = d3.extent((this[y_axis + '_extent'] || []).concat(data_layer.getAxisExtent('y')));\n }\n }\n // Override x_extent from state if explicitly defined to do so\n if (this.layout.axes.x && this.layout.axes.x.extent === 'state') {\n this.x_extent = [\n this.state.start,\n this.state.end\n ];\n }\n return this;\n };\n /**\n * Generate an array of ticks for an axis. These ticks are generated in one of three ways (highest wins):\n * 1. An array of specific tick marks\n * 2. Query each data layer for what ticks are appropriate, and allow a panel-level tick configuration parameter\n * object to override the layer's default presentation settings\n * 3. Generate generic tick marks based on the extent of the data\n * @param {('x'|'y1'|'y2')} axis The string identifier of the axis\n * @returns {Number[]|Object[]} TODO: number format?\n * An array of numbers: interpreted as an array of axis value offsets for positioning.\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\n LocusZoom.Panel.prototype.generateTicks = function (axis) {\n // Parse an explicit 'ticks' attribute in the axis layout\n if (this.layout.axes[axis].ticks) {\n var layout = this.layout.axes[axis];\n var baseTickConfig = layout.ticks;\n if (Array.isArray(baseTickConfig)) {\n // Array of specific ticks hard-coded into a panel will override any ticks that an individual layer might specify\n return baseTickConfig;\n }\n if (typeof baseTickConfig === 'object') {\n // If the layout specifies base configuration for ticks- but without specific positions- then ask each\n // data layer to report the tick marks that it thinks it needs\n // TODO: Few layers currently need to specify custom ticks (which is ok!). But if it becomes common, consider adding mechanisms to deduplicate ticks across layers\n var self = this;\n // Pass any layer-specific customizations for how ticks are calculated. (styles are overridden separately)\n var config = { position: baseTickConfig.position };\n var combinedTicks = this.data_layer_ids_by_z_index.reduce(function (acc, data_layer_id) {\n var nextLayer = self.data_layers[data_layer_id];\n return acc.concat(nextLayer.getTicks(axis, config));\n }, []);\n return combinedTicks.map(function (item) {\n // The layer makes suggestions, but tick configuration params specified on the panel take precedence\n var itemConfig = {};\n itemConfig = LocusZoom.Layouts.merge(itemConfig, baseTickConfig);\n return LocusZoom.Layouts.merge(itemConfig, item);\n });\n }\n }\n // If no other configuration is provided, attempt to generate ticks from the extent\n if (this[axis + '_extent']) {\n return LocusZoom.prettyTicks(this[axis + '_extent'], 'both');\n }\n return [];\n };\n /**\n * Update rendering of this panel whenever an event triggers a redraw. Assumes that the panel has already been\n * prepared the first time via `initialize`\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.render = function () {\n // Position the panel container\n this.svg.container.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n // Set size on the clip rect\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n // Set and position the inner border, style if necessary\n this.inner_border.attr('x', this.layout.margin.left).attr('y', this.layout.margin.top).attr('width', this.layout.width - (this.layout.margin.left + this.layout.margin.right)).attr('height', this.layout.height - (this.layout.margin.top + this.layout.margin.bottom));\n if (this.layout.inner_border) {\n this.inner_border.style({\n 'stroke-width': 1,\n 'stroke': this.layout.inner_border\n });\n }\n // Set/update panel title if necessary\n this.setTitle();\n // Regenerate all extents\n this.generateExtents();\n // Helper function to constrain any procedurally generated vectors (e.g. ranges, extents)\n // Constraints applied here keep vectors from going to infinity or beyond a definable power of ten\n var constrain = function (value, limit_exponent) {\n var neg_min = Math.pow(-10, limit_exponent);\n var neg_max = Math.pow(-10, -limit_exponent);\n var pos_min = Math.pow(10, -limit_exponent);\n var pos_max = Math.pow(10, limit_exponent);\n if (value === Infinity) {\n value = pos_max;\n }\n if (value === -Infinity) {\n value = neg_min;\n }\n if (value === 0) {\n value = pos_min;\n }\n if (value > 0) {\n value = Math.max(Math.min(value, pos_max), pos_min);\n }\n if (value < 0) {\n value = Math.max(Math.min(value, neg_max), neg_min);\n }\n return value;\n };\n // Define default and shifted ranges for all axes\n var ranges = {};\n if (this.x_extent) {\n var base_x_range = {\n start: 0,\n end: this.layout.cliparea.width\n };\n if (this.layout.axes.x.range) {\n base_x_range.start = this.layout.axes.x.range.start || base_x_range.start;\n base_x_range.end = this.layout.axes.x.range.end || base_x_range.end;\n }\n ranges.x = [\n base_x_range.start,\n base_x_range.end\n ];\n ranges.x_shifted = [\n base_x_range.start,\n base_x_range.end\n ];\n }\n if (this.y1_extent) {\n var base_y1_range = {\n start: this.layout.cliparea.height,\n end: 0\n };\n if (this.layout.axes.y1.range) {\n base_y1_range.start = this.layout.axes.y1.range.start || base_y1_range.start;\n base_y1_range.end = this.layout.axes.y1.range.end || base_y1_range.end;\n }\n ranges.y1 = [\n base_y1_range.start,\n base_y1_range.end\n ];\n ranges.y1_shifted = [\n base_y1_range.start,\n base_y1_range.end\n ];\n }\n if (this.y2_extent) {\n var base_y2_range = {\n start: this.layout.cliparea.height,\n end: 0\n };\n if (this.layout.axes.y2.range) {\n base_y2_range.start = this.layout.axes.y2.range.start || base_y2_range.start;\n base_y2_range.end = this.layout.axes.y2.range.end || base_y2_range.end;\n }\n ranges.y2 = [\n base_y2_range.start,\n base_y2_range.end\n ];\n ranges.y2_shifted = [\n base_y2_range.start,\n base_y2_range.end\n ];\n }\n // Shift ranges based on any drag or zoom interactions currently underway\n if (this.parent.interaction.panel_id && (this.parent.interaction.panel_id === this.id || this.parent.interaction.linked_panel_ids.indexOf(this.id) !== -1)) {\n var anchor, scalar = null;\n if (this.parent.interaction.zooming && typeof this.x_scale == 'function') {\n var current_extent_size = Math.abs(this.x_extent[1] - this.x_extent[0]);\n var current_scaled_extent_size = Math.round(this.x_scale.invert(ranges.x_shifted[1])) - Math.round(this.x_scale.invert(ranges.x_shifted[0]));\n var zoom_factor = this.parent.interaction.zooming.scale;\n var potential_extent_size = Math.floor(current_scaled_extent_size * (1 / zoom_factor));\n if (zoom_factor < 1 && !isNaN(this.parent.layout.max_region_scale)) {\n zoom_factor = 1 / (Math.min(potential_extent_size, this.parent.layout.max_region_scale) / current_scaled_extent_size);\n } else if (zoom_factor > 1 && !isNaN(this.parent.layout.min_region_scale)) {\n zoom_factor = 1 / (Math.max(potential_extent_size, this.parent.layout.min_region_scale) / current_scaled_extent_size);\n }\n var new_extent_size = Math.floor(current_extent_size * zoom_factor);\n anchor = this.parent.interaction.zooming.center - this.layout.margin.left - this.layout.origin.x;\n var offset_ratio = anchor / this.layout.cliparea.width;\n var new_x_extent_start = Math.max(Math.floor(this.x_scale.invert(ranges.x_shifted[0]) - (new_extent_size - current_scaled_extent_size) * offset_ratio), 1);\n ranges.x_shifted = [\n this.x_scale(new_x_extent_start),\n this.x_scale(new_x_extent_start + new_extent_size)\n ];\n } else if (this.parent.interaction.dragging) {\n switch (this.parent.interaction.dragging.method) {\n case 'background':\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n break;\n case 'x_tick':\n if (d3.event && d3.event.shiftKey) {\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n } else {\n anchor = this.parent.interaction.dragging.start_x - this.layout.margin.left - this.layout.origin.x;\n scalar = constrain(anchor / (anchor + this.parent.interaction.dragging.dragged_x), 3);\n ranges.x_shifted[0] = 0;\n ranges.x_shifted[1] = Math.max(this.layout.cliparea.width * (1 / scalar), 1);\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n var y_shifted = 'y' + this.parent.interaction.dragging.method[1] + '_shifted';\n if (d3.event && d3.event.shiftKey) {\n ranges[y_shifted][0] = this.layout.cliparea.height + this.parent.interaction.dragging.dragged_y;\n ranges[y_shifted][1] = +this.parent.interaction.dragging.dragged_y;\n } else {\n anchor = this.layout.cliparea.height - (this.parent.interaction.dragging.start_y - this.layout.margin.top - this.layout.origin.y);\n scalar = constrain(anchor / (anchor - this.parent.interaction.dragging.dragged_y), 3);\n ranges[y_shifted][0] = this.layout.cliparea.height;\n ranges[y_shifted][1] = this.layout.cliparea.height - this.layout.cliparea.height * (1 / scalar);\n }\n }\n }\n }\n // Generate scales and ticks for all axes, then render them\n [\n 'x',\n 'y1',\n 'y2'\n ].forEach(function (axis) {\n if (!this[axis + '_extent']) {\n return;\n }\n // Base Scale\n this[axis + '_scale'] = d3.scale.linear().domain(this[axis + '_extent']).range(ranges[axis + '_shifted']);\n // Shift the extent\n this[axis + '_extent'] = [\n this[axis + '_scale'].invert(ranges[axis][0]),\n this[axis + '_scale'].invert(ranges[axis][1])\n ];\n // Finalize Scale\n this[axis + '_scale'] = d3.scale.linear().domain(this[axis + '_extent']).range(ranges[axis]);\n // Render axis (and generate ticks as needed)\n this.renderAxis(axis);\n }.bind(this));\n // Establish mousewheel zoom event handers on the panel (namespacing not passed through by d3, so not used here)\n if (this.layout.interaction.scroll_to_zoom) {\n var zoom_handler = function () {\n // Look for a shift key press while scrolling to execute.\n // If not present, gracefully raise a notification and allow conventional scrolling\n if (!d3.event.shiftKey) {\n if (this.parent.canInteract(this.id)) {\n this.loader.show('Press [SHIFT] while scrolling to zoom').hide(1000);\n }\n return;\n }\n d3.event.preventDefault();\n if (!this.parent.canInteract(this.id)) {\n return;\n }\n var coords = d3.mouse(this.svg.container.node());\n var delta = Math.max(-1, Math.min(1, d3.event.wheelDelta || -d3.event.detail || -d3.event.deltaY));\n if (delta === 0) {\n return;\n }\n this.parent.interaction = {\n panel_id: this.id,\n linked_panel_ids: this.getLinkedPanelIds('x'),\n zooming: {\n scale: delta < 1 ? 0.9 : 1.1,\n center: coords[0]\n }\n };\n this.render();\n this.parent.interaction.linked_panel_ids.forEach(function (panel_id) {\n this.parent.panels[panel_id].render();\n }.bind(this));\n if (this.zoom_timeout !== null) {\n clearTimeout(this.zoom_timeout);\n }\n this.zoom_timeout = setTimeout(function () {\n this.parent.interaction = {};\n this.parent.applyState({\n start: this.x_extent[0],\n end: this.x_extent[1]\n });\n }.bind(this), 500);\n }.bind(this);\n this.zoom_listener = d3.behavior.zoom();\n this.svg.container.call(this.zoom_listener).on('wheel.zoom', zoom_handler).on('mousewheel.zoom', zoom_handler).on('DOMMouseScroll.zoom', zoom_handler);\n }\n // Render data layers in order by z-index\n this.data_layer_ids_by_z_index.forEach(function (data_layer_id) {\n this.data_layers[data_layer_id].draw().render();\n }.bind(this));\n return this;\n };\n /**\n * Render ticks for a particular axis\n * @param {('x'|'y1'|'y2')} axis The identifier of the axes\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.renderAxis = function (axis) {\n if ([\n 'x',\n 'y1',\n 'y2'\n ].indexOf(axis) === -1) {\n throw new Error('Unable to render axis; invalid axis identifier: ' + axis);\n }\n var canRender = this.layout.axes[axis].render && typeof this[axis + '_scale'] == 'function' && !isNaN(this[axis + '_scale'](0));\n // If the axis has already been rendered then check if we can/can't render it\n // Make sure the axis element is shown/hidden to suit\n if (this[axis + '_axis']) {\n this.svg.container.select('g.lz-axis.lz-' + axis).style('display', canRender ? null : 'none');\n }\n if (!canRender) {\n return this;\n }\n // Axis-specific values to plug in where needed\n var axis_params = {\n x: {\n position: 'translate(' + this.layout.margin.left + ',' + (this.layout.height - this.layout.margin.bottom) + ')',\n orientation: 'bottom',\n label_x: this.layout.cliparea.width / 2,\n label_y: this.layout.axes[axis].label_offset || 0,\n label_rotate: null\n },\n y1: {\n position: 'translate(' + this.layout.margin.left + ',' + this.layout.margin.top + ')',\n orientation: 'left',\n label_x: -1 * (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n },\n y2: {\n position: 'translate(' + (this.layout.width - this.layout.margin.right) + ',' + this.layout.margin.top + ')',\n orientation: 'right',\n label_x: this.layout.axes[axis].label_offset || 0,\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n }\n };\n // Generate Ticks\n this[axis + '_ticks'] = this.generateTicks(axis);\n // Determine if the ticks are all numbers (d3-automated tick rendering) or not (manual tick rendering)\n var ticksAreAllNumbers = function (ticks) {\n for (var i = 0; i < ticks.length; i++) {\n if (isNaN(ticks[i])) {\n return false;\n }\n }\n return true;\n }(this[axis + '_ticks']);\n // Initialize the axis; set scale and orientation\n this[axis + '_axis'] = d3.svg.axis().scale(this[axis + '_scale']).orient(axis_params[axis].orientation).tickPadding(3);\n // Set tick values and format\n if (ticksAreAllNumbers) {\n this[axis + '_axis'].tickValues(this[axis + '_ticks']);\n if (this.layout.axes[axis].tick_format === 'region') {\n this[axis + '_axis'].tickFormat(function (d) {\n return LocusZoom.positionIntToString(d, 6);\n });\n }\n } else {\n var ticks = this[axis + '_ticks'].map(function (t) {\n return t[axis.substr(0, 1)];\n });\n this[axis + '_axis'].tickValues(ticks).tickFormat(function (t, i) {\n return this[axis + '_ticks'][i].text;\n }.bind(this));\n }\n // Position the axis in the SVG and apply the axis construct\n this.svg[axis + '_axis'].attr('transform', axis_params[axis].position).call(this[axis + '_axis']);\n // If necessary manually apply styles and transforms to ticks as specified by the layout\n if (!ticksAreAllNumbers) {\n var tick_selector = d3.selectAll('g#' + this.getBaseId().replace('.', '\\\\.') + '\\\\.' + axis + '_axis g.tick');\n var panel = this;\n tick_selector.each(function (d, i) {\n var selector = d3.select(this).select('text');\n if (panel[axis + '_ticks'][i].style) {\n selector.style(panel[axis + '_ticks'][i].style);\n }\n if (panel[axis + '_ticks'][i].transform) {\n selector.attr('transform', panel[axis + '_ticks'][i].transform);\n }\n });\n }\n // Render the axis label if necessary\n var label = this.layout.axes[axis].label || null;\n if (label !== null) {\n this.svg[axis + '_axis_label'].attr('x', axis_params[axis].label_x).attr('y', axis_params[axis].label_y).text(LocusZoom.parseFields(this.state, label));\n if (axis_params[axis].label_rotate !== null) {\n this.svg[axis + '_axis_label'].attr('transform', 'rotate(' + axis_params[axis].label_rotate + ' ' + axis_params[axis].label_x + ',' + axis_params[axis].label_y + ')');\n }\n }\n // Attach interactive handlers to ticks as needed\n [\n 'x',\n 'y1',\n 'y2'\n ].forEach(function (axis) {\n if (this.layout.interaction['drag_' + axis + '_ticks_to_scale']) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var tick_mouseover = function () {\n if (typeof d3.select(this).node().focus == 'function') {\n d3.select(this).node().focus();\n }\n var cursor = axis === 'x' ? 'ew-resize' : 'ns-resize';\n if (d3.event && d3.event.shiftKey) {\n cursor = 'move';\n }\n d3.select(this).style({\n 'font-weight': 'bold',\n 'cursor': cursor\n }).on('keydown' + namespace, tick_mouseover).on('keyup' + namespace, tick_mouseover);\n };\n this.svg.container.selectAll('.lz-axis.lz-' + axis + ' .tick text').attr('tabindex', 0) // necessary to make the tick focusable so keypress events can be captured\n.on('mouseover' + namespace, tick_mouseover).on('mouseout' + namespace, function () {\n d3.select(this).style({ 'font-weight': 'normal' });\n d3.select(this).on('keydown' + namespace, null).on('keyup' + namespace, null);\n }).on('mousedown' + namespace, function () {\n this.parent.startDrag(this, axis + '_tick');\n }.bind(this));\n }\n }.bind(this));\n return this;\n };\n /**\n * Force the height of this panel to the largest absolute height of the data in\n * all child data layers (if not null for any child data layers)\n * @param {number|null} [target_height] A target height, which will be used in situations when the expected height can be\n * pre-calculated (eg when the layers are transitioning)\n */\n LocusZoom.Panel.prototype.scaleHeightToData = function (target_height) {\n target_height = +target_height || null;\n if (target_height === null) {\n this.data_layer_ids_by_z_index.forEach(function (id) {\n var dh = this.data_layers[id].getAbsoluteDataHeight();\n if (+dh) {\n if (target_height === null) {\n target_height = +dh;\n } else {\n target_height = Math.max(target_height, +dh);\n }\n }\n }.bind(this));\n }\n if (+target_height) {\n target_height += +this.layout.margin.top + +this.layout.margin.bottom;\n this.setDimensions(this.layout.width, target_height);\n this.parent.setDimensions();\n this.parent.panel_ids_by_y_index.forEach(function (id) {\n this.parent.panels[id].layout.proportional_height = null;\n }.bind(this));\n this.parent.positionPanels();\n }\n };\n /**\n * Methods to set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n */\n LocusZoom.Panel.prototype.setElementStatusByFilters = function (status, toggle, filters, exclusive) {\n this.data_layer_ids_by_z_index.forEach(function (id) {\n this.data_layers[id].setElementStatusByFilters(status, toggle, filters, exclusive);\n }.bind(this));\n };\n /**\n * Set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n */\n LocusZoom.Panel.prototype.setAllElementStatus = function (status, toggle) {\n this.data_layer_ids_by_z_index.forEach(function (id) {\n this.data_layers[id].setAllElementStatus(status, toggle);\n }.bind(this));\n };\n // TODO: Capture documentation for dynamically generated methods\n LocusZoom.DataLayer.Statuses.verbs.forEach(function (verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.Panel.prototype[verb + 'ElementsByFilters'] = function (filters, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.Panel.prototype[antiverb + 'ElementsByFilters'] = function (filters, exclusive) {\n if (typeof exclusive == 'undefined') {\n exclusive = false;\n } else {\n exclusive = !!exclusive;\n }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.Panel.prototype[verb + 'AllElements'] = function () {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.Panel.prototype[antiverb + 'AllElements'] = function () {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n });\n /**\n * Add a \"basic\" loader to a panel\n * This method is just a shortcut for adding the most commonly used type of loading indicator, which appears when\n * data is requested, animates (e.g. shows an infinitely cycling progress bar as opposed to one that loads from\n * 0-100% based on actual load progress), and disappears when new data is loaded and rendered.\n *\n *\n * @param {Boolean} show_immediately\n * @returns {LocusZoom.Panel}\n */\n LocusZoom.Panel.prototype.addBasicLoader = function (show_immediately) {\n if (typeof show_immediately != 'undefined') {\n show_immediately = true;\n }\n if (show_immediately) {\n this.loader.show('Loading...').animate();\n }\n this.on('data_requested', function () {\n this.loader.show('Loading...').animate();\n }.bind(this));\n this.on('data_rendered', function () {\n this.loader.hide();\n }.bind(this));\n return this;\n };\n } catch (plugin_loading_error) {\n console.error('LocusZoom Plugin error: ', plugin_loading_error);\n }\n return LocusZoom;\n })); //# sourceMappingURL=locuszoom.app.js.map\n } catch (plugin_loading_error) {\n console.error('LocusZoom Plugin error: ', plugin_loading_error);\n }\n return LocusZoom;\n}));","/* global LocusZoom */\n'use strict';\n\n/**\n * A Dashboard is an HTML element used for presenting arbitrary user interface components. Dashboards are anchored\n * to either the entire Plot or to individual Panels.\n *\n * Each dashboard is an HTML-based (read: not SVG) collection of components used to display information or provide\n * user interface. Dashboards can exist on entire plots, where their visibility is permanent and vertically adjacent\n * to the plot, or on individual panels, where their visibility is tied to a behavior (e.g. a mouseover) and is as\n * an overlay.\n * @class\n */\nLocusZoom.Dashboard = function(parent) {\n // parent must be a locuszoom plot or panel\n if (!(parent instanceof LocusZoom.Plot) && !(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create dashboard, parent must be a locuszoom plot or panel');\n }\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.dashboard';\n /** @member {('plot'|'panel')} */\n this.type = (this.parent instanceof LocusZoom.Plot) ? 'plot' : 'panel';\n /** @member {LocusZoom.Plot} */\n this.parent_plot = this.type === 'plot' ? this.parent : this.parent.parent;\n\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {LocusZoom.Dashboard.Component[]} */\n this.components = [];\n /**\n * The timer identifier as returned by setTimeout\n * @member {Number}\n */\n this.hide_timeout = null;\n /**\n * Whether to hide the dashboard. Can be overridden by a child component. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n\n // TODO: Return value from constructor function?\n return this.initialize();\n};\n\n/**\n * Prepare the dashboard for first use: generate all component instances for this dashboard, based on the provided\n * layout of the parent. Connects event listeners and shows/hides as appropriate.\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.initialize = function() {\n // Parse layout to generate component instances\n if (Array.isArray(this.parent.layout.dashboard.components)) {\n this.parent.layout.dashboard.components.forEach(function(layout) {\n try {\n var component = LocusZoom.Dashboard.Components.get(layout.type, layout, this);\n this.components.push(component);\n } catch (e) {\n console.warn(e);\n }\n }.bind(this));\n }\n\n // Add mouseover event handlers to show/hide panel dashboard\n if (this.type === 'panel') {\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseover.' + this.id, function() {\n clearTimeout(this.hide_timeout);\n if (!this.selector || this.selector.style('visibility') === 'hidden') { this.show(); }\n }.bind(this));\n d3.select(this.parent.parent.svg.node().parentNode).on('mouseout.' + this.id, function() {\n clearTimeout(this.hide_timeout);\n this.hide_timeout = setTimeout(function() { this.hide(); }.bind(this), 300);\n }.bind(this));\n }\n\n return this;\n\n};\n\n/**\n * Whether to persist the dashboard. Returns true if at least one component should persist, or if the panel is engaged\n * in an active drag event.\n * @returns {boolean}\n */\nLocusZoom.Dashboard.prototype.shouldPersist = function() {\n if (this.persist) { return true; }\n var persist = false;\n // Persist if at least one component should also persist\n this.components.forEach(function(component) {\n persist = persist || component.shouldPersist();\n });\n // Persist if in a parent drag event\n persist = persist || (this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.dragging);\n return !!persist;\n};\n\n/**\n * Make the dashboard appear. If it doesn't exist yet create it, including creating/positioning all components within,\n * and make sure it is set to be visible.\n */\nLocusZoom.Dashboard.prototype.show = function() {\n if (!this.selector) {\n switch (this.type) {\n case 'plot':\n this.selector = d3.select(this.parent.svg.node().parentNode)\n .insert('div',':first-child');\n break;\n case 'panel':\n this.selector = d3.select(this.parent.parent.svg.node().parentNode)\n .insert('div', '.lz-data_layer-tooltip, .lz-dashboard-menu, .lz-curtain').classed('lz-panel-dashboard', true);\n break;\n }\n this.selector.classed('lz-dashboard', true).classed('lz-' + this.type + '-dashboard', true).attr('id', this.id);\n }\n this.components.forEach(function(component) { component.show(); });\n this.selector.style({ visibility: 'visible' });\n return this.update();\n};\n\n/**\n * Update the dashboard and rerender all child components. This can be called whenever plot state changes.\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.update = function() {\n if (!this.selector) { return this; }\n this.components.forEach(function(component) { component.update(); });\n return this.position();\n};\n\n/**\n * Position the dashboard (and child components) within the panel\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.position = function() {\n if (!this.selector) { return this; }\n // Position the dashboard itself (panel only)\n if (this.type === 'panel') {\n var page_origin = this.parent.getPageOrigin();\n var top = (page_origin.y + 3.5).toString() + 'px';\n var left = page_origin.x.toString() + 'px';\n var width = (this.parent.layout.width - 4).toString() + 'px';\n this.selector.style({ position: 'absolute', top: top, left: left, width: width });\n }\n // Recursively position components\n this.components.forEach(function(component) { component.position(); });\n return this;\n};\n\n/**\n * Hide the dashboard (make invisible but do not destroy). Will do nothing if `shouldPersist` returns true.\n *\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.hide = function() {\n if (!this.selector || this.shouldPersist()) { return this; }\n this.components.forEach(function(component) { component.hide(); });\n this.selector.style({ visibility: 'hidden' });\n return this;\n};\n\n/**\n * Completely remove dashboard and all child components. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.prototype.destroy = function(force) {\n if (typeof force == 'undefined') { force = false; }\n if (!this.selector) { return this; }\n if (this.shouldPersist() && !force) { return this; }\n this.components.forEach(function(component) { component.destroy(true); });\n this.components = [];\n this.selector.remove();\n this.selector = null;\n return this;\n};\n\n/**\n *\n * A dashboard component is an empty div rendered on a dashboard that can display custom\n * html of user interface elements. LocusZoom.Dashboard.Components is a singleton used to\n * define and manage an extendable collection of dashboard components.\n * (e.g. by LocusZoom.Dashboard.Components.add())\n * @class\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @param {('left'|'right')} [layout.position='left'] Whether to float the component left or right.\n * @param {('start'|'middle'|'end')} [layout.group_position] Buttons can optionally be gathered into a visually\n * distinctive group whose elements are closer together. If a button is identified as the start or end of a group,\n * it will be drawn with rounded corners and an extra margin of spacing from any button not part of the group.\n * For example, the region_nav_plot dashboard is a defined as a group.\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple'} [layout.color='gray'] Color scheme for the\n * component. Applies to buttons and menus.\n * @param {LocusZoom.Dashboard} parent The dashboard that contains this component\n*/\nLocusZoom.Dashboard.Component = function(layout, parent) {\n /** @member {Object} */\n this.layout = layout || {};\n if (!this.layout.color) { this.layout.color = 'gray'; }\n\n /** @member {LocusZoom.Dashboard|*} */\n this.parent = parent || null;\n /**\n * Some dashboards are attached to a panel, rather than directly to a plot\n * @member {LocusZoom.Panel|null}\n */\n this.parent_panel = null;\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n /**\n * This is a reference to either the panel or the plot, depending on what the dashboard is\n * tied to. Useful when absolutely positioning dashboard components relative to their SVG anchor.\n * @member {LocusZoom.Plot|LocusZoom.Panel}\n */\n this.parent_svg = null;\n if (this.parent instanceof LocusZoom.Dashboard) {\n // TODO: when is the immediate parent *not* a dashboard?\n if (this.parent.type === 'panel') {\n this.parent_panel = this.parent.parent;\n this.parent_plot = this.parent.parent.parent;\n this.parent_svg = this.parent_panel;\n } else {\n this.parent_plot = this.parent.parent;\n this.parent_svg = this.parent_plot;\n }\n }\n /** @member {d3.selection} */\n this.selector = null;\n /**\n * If this is an interactive component, it will contain a button or menu instance that handles the interactivity.\n * There is a 1-to-1 relationship of dashboard component to button\n * @member {null|LocusZoom.Dashboard.Component.Button}\n */\n this.button = null;\n /**\n * If any single component is marked persistent, it will bubble up to prevent automatic hide behavior on a\n * component's parent dashboard. Check via `shouldPersist`\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n if (!this.layout.position) { this.layout.position = 'left'; }\n\n // TODO: Return value in constructor\n return this;\n};\n/**\n * Perform all rendering of component, including toggling visibility to true. Will initialize and create SVG element\n * if necessary, as well as updating with new data and performing layout actions.\n */\nLocusZoom.Dashboard.Component.prototype.show = function() {\n if (!this.parent || !this.parent.selector) { return; }\n if (!this.selector) {\n var group_position = (['start','middle','end'].indexOf(this.layout.group_position) !== -1 ? ' lz-dashboard-group-' + this.layout.group_position : '');\n this.selector = this.parent.selector.append('div')\n .attr('class', 'lz-dashboard-' + this.layout.position + group_position);\n if (this.layout.style) { this.selector.style(this.layout.style); }\n if (typeof this.initialize == 'function') { this.initialize(); }\n }\n if (this.button && this.button.status === 'highlighted') { this.button.menu.show(); }\n this.selector.style({ visibility: 'visible' });\n this.update();\n return this.position();\n};\n/**\n * Update the dashboard component with any new data or plot state as appropriate. This method performs all\n * necessary rendering steps.\n */\nLocusZoom.Dashboard.Component.prototype.update = function() { /* stub */ };\n/**\n * Place the component correctly in the plot\n * @returns {LocusZoom.Dashboard.Component}\n */\nLocusZoom.Dashboard.Component.prototype.position = function() {\n if (this.button) { this.button.menu.position(); }\n return this;\n};\n/**\n * Determine whether the component should persist (will bubble up to parent dashboard)\n * @returns {boolean}\n */\nLocusZoom.Dashboard.Component.prototype.shouldPersist = function() {\n if (this.persist) { return true; }\n if (this.button && this.button.persist) { return true; }\n return false;\n};\n/**\n * Toggle visibility to hidden, unless marked as persistent\n * @returns {LocusZoom.Dashboard.Component}\n */\nLocusZoom.Dashboard.Component.prototype.hide = function() {\n if (!this.selector || this.shouldPersist()) { return this; }\n if (this.button) { this.button.menu.hide(); }\n this.selector.style({ visibility: 'hidden' });\n return this;\n};\n/**\n * Completely remove component and button. (may be overridden by persistence settings)\n * @param {Boolean} [force=false] If true, will ignore persistence settings and always destroy the dashboard\n * @returns {LocusZoom.Dashboard}\n */\nLocusZoom.Dashboard.Component.prototype.destroy = function(force) {\n if (typeof force == 'undefined') { force = false; }\n if (!this.selector) { return this; }\n if (this.shouldPersist() && !force) { return this; }\n if (this.button && this.button.menu) { this.button.menu.destroy(); }\n this.selector.remove();\n this.selector = null;\n this.button = null;\n return this;\n};\n\n/**\n * Singleton registry of all known components\n * @class\n * @static\n */\nLocusZoom.Dashboard.Components = (function() {\n /** @lends LocusZoom.Dashboard.Components */\n var obj = {};\n var components = {};\n\n /**\n * Create a new component instance by name\n * @param {String} name The string identifier of the desired component\n * @param {Object} layout The layout to use to create the component\n * @param {LocusZoom.Dashboard} parent The containing dashboard to use when creating the component\n * @returns {LocusZoom.Dashboard.Component}\n */\n obj.get = function(name, layout, parent) {\n if (!name) {\n return null;\n } else if (components[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for dashboard component [' + name + ']');\n } else {\n return new components[name](layout, parent);\n }\n } else {\n throw new Error('dashboard component [' + name + '] not found');\n }\n };\n /**\n * Add a new component constructor to the registry and ensure that it extends the correct parent class\n * @protected\n * @param name\n * @param component\n */\n obj.set = function(name, component) {\n if (component) {\n if (typeof component != 'function') {\n throw new Error('unable to set dashboard component [' + name + '], argument provided is not a function');\n } else {\n components[name] = component;\n components[name].prototype = new LocusZoom.Dashboard.Component();\n }\n } else {\n delete components[name];\n }\n };\n\n /**\n * Register a new component constructor by name\n * @param {String} name\n * @param {function} component The component constructor\n */\n obj.add = function(name, component) {\n if (components[name]) {\n throw new Error('dashboard component already exists with name: ' + name);\n } else {\n obj.set(name, component);\n }\n };\n\n /**\n * List the names of all registered components\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(components);\n };\n\n return obj;\n})();\n\n/**\n * Plots and panels may have a \"dashboard\" element suited for showing HTML components that may be interactive.\n * When components need to incorporate a generic button, or additionally a button that generates a menu, this\n * class provides much of the necessary framework.\n * @class\n * @param {LocusZoom.Dashboard.Component} parent\n */\nLocusZoom.Dashboard.Component.Button = function(parent) {\n\n if (!(parent instanceof LocusZoom.Dashboard.Component)) {\n throw new Error('Unable to create dashboard component button, invalid parent');\n }\n /** @member {LocusZoom.Dashboard.Component} */\n this.parent = parent;\n /** @member {LocusZoom.Dashboard.Panel} */\n this.parent_panel = this.parent.parent_panel;\n /** @member {LocusZoom.Dashboard.Plot} */\n this.parent_plot = this.parent.parent_plot;\n /** @member {LocusZoom.Plot|LocusZoom.Panel} */\n this.parent_svg = this.parent.parent_svg;\n\n /** @member {LocusZoom.Dashboard|null|*} */\n this.parent_dashboard = this.parent.parent;\n /** @member {d3.selection} */\n this.selector = null;\n\n /**\n * Tag to use for the button (default: a)\n * @member {String}\n */\n this.tag = 'a';\n\n /**\n * TODO This method does not appear to be used anywhere\n * @param {String} tag\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTag = function(tag) {\n if (typeof tag != 'undefined') { this.tag = tag.toString(); }\n return this;\n };\n\n /**\n * HTML for the button to show.\n * @protected\n * @member {String}\n */\n this.html = '';\n /**\n * Specify the HTML content of this button.\n * WARNING: The string provided will be inserted into the document as raw markup; XSS mitigation is the\n * responsibility of each button implementation.\n * @param {String} html\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setHtml = function(html) {\n if (typeof html != 'undefined') { this.html = html.toString(); }\n return this;\n };\n /**\n * @deprecated since 0.5.6; use setHtml instead\n */\n this.setText = this.setHtml;\n\n /**\n * Mouseover title text for the button to show\n * @protected\n * @member {String}\n */\n this.title = '';\n /**\n * Set the mouseover title text for the button (if any)\n * @param {String} title Simple text to display\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setTitle = function(title) {\n if (typeof title != 'undefined') { this.title = title.toString(); }\n return this;\n };\n\n /**\n * Color of the button\n * @member {String}\n */\n this.color = 'gray';\n\n /**\n * Set the color associated with this button\n * @param {('gray'|'red'|'orange'|'yellow'|'green'|'blue'|'purple')} color Any selection not in the preset list\n * will be replaced with gray.\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setColor = function(color) {\n if (typeof color != 'undefined') {\n if (['gray', 'red', 'orange', 'yellow', 'green', 'blue', 'purple'].indexOf(color) !== -1) { this.color = color; }\n else { this.color = 'gray'; }\n }\n return this;\n };\n\n /**\n * Hash of arbitrary button styles to apply as {name: value} entries\n * @protected\n * @member {Object}\n */\n this.style = {};\n /**\n * Set a collection of custom styles to be used by the button\n * @param {Object} style Hash of {name:value} entries\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setStyle = function(style) {\n if (typeof style != 'undefined') { this.style = style; }\n return this;\n };\n\n //\n /**\n * Method to generate a CSS class string\n * @returns {string}\n */\n this.getClass = function() {\n var group_position = (['start','middle','end'].indexOf(this.parent.layout.group_position) !== -1 ? ' lz-dashboard-button-group-' + this.parent.layout.group_position : '');\n return 'lz-dashboard-button lz-dashboard-button-' + this.color + (this.status ? '-' + this.status : '') + group_position;\n };\n\n // Permanence\n /**\n * Track internal state on whether to keep showing the button/ menu contents at the moment\n * @protected\n * @member {Boolean}\n */\n this.persist = false;\n /**\n * Configuration when defining a button: track whether this component should be allowed to keep open\n * menu/button contents in response to certain events\n * @protected\n * @member {Boolean}\n */\n this.permanent = false;\n /**\n * Allow code to change whether the button is allowed to be `permanent`\n * @param {boolean} bool\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.setPermanent = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n this.permanent = bool;\n if (this.permanent) { this.persist = true; }\n return this;\n };\n /**\n * Determine whether the button/menu contents should persist in response to a specific event\n * @returns {Boolean}\n */\n this.shouldPersist = function() {\n return this.permanent || this.persist;\n };\n\n /**\n * Button status (highlighted / disabled/ etc)\n * @protected\n * @member {String}\n */\n this.status = '';\n /**\n * Change button state\n * @param {('highlighted'|'disabled'|'')} status\n */\n this.setStatus = function(status) {\n if (typeof status != 'undefined' && ['', 'highlighted', 'disabled'].indexOf(status) !== -1) { this.status = status; }\n return this.update();\n };\n /**\n * Toggle whether the button is highlighted\n * @param {boolean} bool If provided, explicitly set highlighted state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.highlight = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n if (bool) { return this.setStatus('highlighted'); }\n else if (this.status === 'highlighted') { return this.setStatus(''); }\n return this;\n };\n /**\n * Toggle whether the button is disabled\n * @param {boolean} bool If provided, explicitly set disabled state\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.disable = function(bool) {\n if (typeof bool == 'undefined') { bool = true; } else { bool = Boolean(bool); }\n if (bool) { return this.setStatus('disabled'); }\n else if (this.status === 'disabled') { return this.setStatus(''); }\n return this;\n };\n\n // Mouse events\n /** @member {function} */\n this.onmouseover = function() {};\n this.setOnMouseover = function(onmouseover) {\n if (typeof onmouseover == 'function') { this.onmouseover = onmouseover; }\n else { this.onmouseover = function() {}; }\n return this;\n };\n /** @member {function} */\n this.onmouseout = function() {};\n this.setOnMouseout = function(onmouseout) {\n if (typeof onmouseout == 'function') { this.onmouseout = onmouseout; }\n else { this.onmouseout = function() {}; }\n return this;\n };\n /** @member {function} */\n this.onclick = function() {};\n this.setOnclick = function(onclick) {\n if (typeof onclick == 'function') { this.onclick = onclick; }\n else { this.onclick = function() {}; }\n return this;\n };\n\n // Primary behavior functions\n /**\n * Show the button, including creating DOM elements if necessary for first render\n */\n this.show = function() {\n if (!this.parent) { return; }\n if (!this.selector) {\n this.selector = this.parent.selector.append(this.tag).attr('class', this.getClass());\n }\n return this.update();\n };\n /**\n * Hook for any actions or state cleanup to be performed before rerendering\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.preUpdate = function() { return this; };\n /**\n * Update button state and contents, and fully rerender\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.update = function() {\n if (!this.selector) { return this; }\n this.preUpdate();\n this.selector\n .attr('class', this.getClass())\n .attr('title', this.title).style(this.style)\n .on('mouseover', (this.status === 'disabled') ? null : this.onmouseover)\n .on('mouseout', (this.status === 'disabled') ? null : this.onmouseout)\n .on('click', (this.status === 'disabled') ? null : this.onclick)\n .html(this.html);\n this.menu.update();\n this.postUpdate();\n return this;\n };\n /**\n * Hook for any behavior to be added/changed after the button has been re-rendered\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.postUpdate = function() { return this; };\n /**\n * Hide the button by removing it from the DOM (may be overridden by current persistence setting)\n * @returns {LocusZoom.Dashboard.Component.Button}\n */\n this.hide = function() {\n if (this.selector && !this.shouldPersist()) {\n this.selector.remove();\n this.selector = null;\n }\n return this;\n };\n\n /**\n * Button Menu Object\n * The menu is an HTML overlay that can appear below a button. It can contain arbitrary HTML and\n * has logic to be automatically positioned and sized to behave more or less like a dropdown menu.\n * @member {Object}\n */\n this.menu = {\n outer_selector: null,\n inner_selector: null,\n scroll_position: 0,\n hidden: true,\n /**\n * Show the button menu, including setting up any DOM elements needed for first rendering\n */\n show: function() {\n if (!this.menu.outer_selector) {\n this.menu.outer_selector = d3.select(this.parent_plot.svg.node().parentNode).append('div')\n .attr('class', 'lz-dashboard-menu lz-dashboard-menu-' + this.color)\n .attr('id', this.parent_svg.getBaseId() + '.dashboard.menu');\n this.menu.inner_selector = this.menu.outer_selector.append('div')\n .attr('class', 'lz-dashboard-menu-content');\n this.menu.inner_selector.on('scroll', function() {\n this.menu.scroll_position = this.menu.inner_selector.node().scrollTop;\n }.bind(this));\n }\n this.menu.outer_selector.style({ visibility: 'visible' });\n this.menu.hidden = false;\n return this.menu.update();\n }.bind(this),\n /**\n * Update the rendering of the menu\n */\n update: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.populate(); // This function is stubbed for all buttons by default and custom implemented in component definition\n if (this.menu.inner_selector) { this.menu.inner_selector.node().scrollTop = this.menu.scroll_position; }\n return this.menu.position();\n }.bind(this),\n position: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n // Unset any explicitly defined outer selector height so that menus dynamically shrink if content is removed\n this.menu.outer_selector.style({ height: null });\n var padding = 3;\n var scrollbar_padding = 20;\n var menu_height_padding = 14; // 14: 2x 6px padding, 2x 1px border\n var page_origin = this.parent_svg.getPageOrigin();\n var page_scroll_top = document.documentElement.scrollTop || document.body.scrollTop;\n var container_offset = this.parent_plot.getContainerOffset();\n var dashboard_client_rect = this.parent_dashboard.selector.node().getBoundingClientRect();\n var button_client_rect = this.selector.node().getBoundingClientRect();\n var menu_client_rect = this.menu.outer_selector.node().getBoundingClientRect();\n var total_content_height = this.menu.inner_selector.node().scrollHeight;\n var top = 0; var left = 0;\n if (this.parent_dashboard.type === 'panel') {\n top = (page_origin.y + dashboard_client_rect.height + (2 * padding));\n left = Math.max(page_origin.x + this.parent_svg.layout.width - menu_client_rect.width - padding, page_origin.x + padding);\n } else {\n top = button_client_rect.bottom + page_scroll_top + padding - container_offset.top;\n left = Math.max(button_client_rect.left + button_client_rect.width - menu_client_rect.width - container_offset.left, page_origin.x + padding);\n }\n var base_max_width = Math.max(this.parent_svg.layout.width - (2 * padding) - scrollbar_padding, scrollbar_padding);\n var container_max_width = base_max_width;\n var content_max_width = (base_max_width - (4 * padding));\n var base_max_height = Math.max(this.parent_svg.layout.height - (10 * padding) - menu_height_padding, menu_height_padding);\n var height = Math.min(total_content_height, base_max_height);\n var max_height = base_max_height;\n this.menu.outer_selector.style({\n 'top': top.toString() + 'px',\n 'left': left.toString() + 'px',\n 'max-width': container_max_width.toString() + 'px',\n 'max-height': max_height.toString() + 'px',\n 'height': height.toString() + 'px'\n });\n this.menu.inner_selector.style({ 'max-width': content_max_width.toString() + 'px' });\n this.menu.inner_selector.node().scrollTop = this.menu.scroll_position;\n return this.menu;\n }.bind(this),\n hide: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.outer_selector.style({ visibility: 'hidden' });\n this.menu.hidden = true;\n return this.menu;\n }.bind(this),\n destroy: function() {\n if (!this.menu.outer_selector) { return this.menu; }\n this.menu.inner_selector.remove();\n this.menu.outer_selector.remove();\n this.menu.inner_selector = null;\n this.menu.outer_selector = null;\n return this.menu;\n }.bind(this),\n /**\n * Internal method definition\n * By convention populate() does nothing and should be reimplemented with each dashboard button definition\n * Reimplement by way of Dashboard.Component.Button.menu.setPopulate to define the populate method and hook\n * up standard menu click-toggle behavior prototype.\n * @protected\n */\n populate: function() { /* stub */ }.bind(this),\n /**\n * Define how the menu is populated with items, and set up click and display properties as appropriate\n * @public\n */\n setPopulate: function(menu_populate_function) {\n if (typeof menu_populate_function == 'function') {\n this.menu.populate = menu_populate_function;\n this.setOnclick(function() {\n if (this.menu.hidden) {\n this.menu.show();\n this.highlight().update();\n this.persist = true;\n } else {\n this.menu.hide();\n this.highlight(false).update();\n if (!this.permanent) { this.persist = false; }\n }\n }.bind(this));\n } else {\n this.setOnclick();\n }\n return this;\n }.bind(this)\n };\n\n};\n\n/**\n * Renders arbitrary text with title formatting\n * @class LocusZoom.Dashboard.Components.title\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.title Text to render\n */\nLocusZoom.Dashboard.Components.add('title', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.show = function() {\n if (!this.div_selector) {\n this.div_selector = this.parent.selector.append('div')\n .attr('class', 'lz-dashboard-title lz-dashboard-' + this.layout.position);\n this.title_selector = this.div_selector.append('h3');\n }\n return this.update();\n };\n this.update = function() {\n var title = layout.title.toString();\n if (this.layout.subtitle) { title += ' ' + this.layout.subtitle + ''; }\n this.title_selector.html(title);\n return this;\n };\n});\n\n/**\n * Renders text to display the current dimensions of the plot. Automatically updated as plot dimensions change\n * @class LocusZoom.Dashboard.Components.dimensions\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('dimensions', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n var display_width = this.parent_plot.layout.width.toString().indexOf('.') === -1 ? this.parent_plot.layout.width : this.parent_plot.layout.width.toFixed(2);\n var display_height = this.parent_plot.layout.height.toString().indexOf('.') === -1 ? this.parent_plot.layout.height : this.parent_plot.layout.height.toFixed(2);\n this.selector.html(display_width + 'px × ' + display_height + 'px');\n if (layout.class) { this.selector.attr('class', layout.class); }\n if (layout.style) { this.selector.style(layout.style); }\n return this;\n };\n});\n\n/**\n * Display the current scale of the genome region displayed in the plot, as defined by the difference between\n * `state.end` and `state.start`.\n * @class LocusZoom.Dashboard.Components.region_scale\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('region_scale', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (!isNaN(this.parent_plot.state.start) && !isNaN(this.parent_plot.state.end)\n && this.parent_plot.state.start !== null && this.parent_plot.state.end !== null) {\n this.selector.style('display', null);\n this.selector.html(LocusZoom.positionIntToString(this.parent_plot.state.end - this.parent_plot.state.start, null, true));\n } else {\n this.selector.style('display', 'none');\n }\n if (layout.class) { this.selector.attr('class', layout.class); }\n if (layout.style) { this.selector.style(layout.style); }\n return this;\n };\n});\n\n/**\n * Button to export current plot to an SVG image\n * @class LocusZoom.Dashboard.Components.download\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Download Image\"]\n * @param {string} [layout.button_title=\"Download image of the current plot as locuszoom.svg\"]\n * @param {string} [layout.filename=\"locuszoom.svg\"] The default filename to use when saving the image\n */\nLocusZoom.Dashboard.Components.add('download', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html || 'Download Image')\n .setTitle(layout.button_title || 'Download image of the current plot as locuszoom.svg')\n .setOnMouseover(function() {\n this.button.selector\n .classed('lz-dashboard-button-gray-disabled', true)\n .html('Preparing Image');\n this.generateBase64SVG().then(function(url) {\n var old = this.button.selector.attr('href');\n if (old) { URL.revokeObjectURL(old); } // Clean up old url instance to prevent memory leaks\n this.button.selector\n .attr('href', url)\n .classed('lz-dashboard-button-gray-disabled', false)\n .classed('lz-dashboard-button-gray-highlighted', true)\n .html(layout.button_html || 'Download Image');\n }.bind(this));\n }.bind(this))\n .setOnMouseout(function() {\n this.button.selector.classed('lz-dashboard-button-gray-highlighted', false);\n }.bind(this));\n this.button.show();\n this.button.selector.attr('href-lang', 'image/svg+xml').attr('download', layout.filename || 'locuszoom.svg');\n return this;\n };\n this.css_string = '';\n for (var stylesheet in Object.keys(document.styleSheets)) {\n if ( document.styleSheets[stylesheet].href !== null\n && document.styleSheets[stylesheet].href.indexOf('locuszoom.css') !== -1) {\n // TODO: \"Download image\" button will render the image incorrectly if the stylesheet has been renamed or concatenated\n LocusZoom.createCORSPromise('GET', document.styleSheets[stylesheet].href)\n .then(function(response) {\n this.css_string = response.replace(/[\\r\\n]/g,' ').replace(/\\s+/g,' ');\n if (this.css_string.indexOf('/* ! LocusZoom HTML Styles */')) {\n this.css_string = this.css_string.substring(0, this.css_string.indexOf('/* ! LocusZoom HTML Styles */'));\n }\n }.bind(this));\n break;\n }\n }\n this.generateBase64SVG = function() {\n return new Promise(function (resolve, reject) {\n // Insert a hidden div, clone the node into that so we can modify it with d3\n var container = this.parent.selector.append('div').style('display', 'none')\n .html(this.parent_plot.svg.node().outerHTML);\n // Remove unnecessary elements\n container.selectAll('g.lz-curtain').remove();\n container.selectAll('g.lz-mouse_guide').remove();\n // Convert units on axis tick dy attributes from ems to pixels\n container.selectAll('g.tick text').each(function() {\n var dy = +(d3.select(this).attr('dy').substring(-2).slice(0,-2)) * 10;\n d3.select(this).attr('dy', dy);\n });\n // Pull the svg into a string and add the contents of the locuszoom stylesheet\n // Don't add this with d3 because it will escape the CDATA declaration incorrectly\n var initial_html = d3.select(container.select('svg').node().parentNode).html();\n var style_def = '';\n var insert_at = initial_html.indexOf('>') + 1;\n initial_html = initial_html.slice(0,insert_at) + style_def + initial_html.slice(insert_at);\n // Delete the container node\n container.remove();\n // Create an object URL based on the rendered markup\n var content = new Blob([initial_html], { type: 'image/svg+xml' });\n resolve(URL.createObjectURL(content));\n }.bind(this));\n };\n});\n\n/**\n * Button to remove panel from plot.\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.remove_panel\n * @augments LocusZoom.Dashboard.Component\n * @param {Boolean} [layout.suppress_confirm=false] If true, removes the panel without prompting user for confirmation\n */\nLocusZoom.Dashboard.Components.add('remove_panel', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('×')\n .setTitle('Remove panel')\n .setOnclick(function() {\n if (!layout.suppress_confirm && !confirm('Are you sure you want to remove this panel? This cannot be undone!')) {\n return false;\n }\n var panel = this.parent_panel;\n panel.dashboard.hide(true);\n d3.select(panel.parent.svg.node().parentNode).on('mouseover.' + panel.getBaseId() + '.dashboard', null);\n d3.select(panel.parent.svg.node().parentNode).on('mouseout.' + panel.getBaseId() + '.dashboard', null);\n return panel.parent.removePanel(panel.id);\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Button to move panel up relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_up\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('move_panel_up', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) {\n var is_at_top = (this.parent_panel.layout.y_index === 0);\n this.button.disable(is_at_top);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('▴')\n .setTitle('Move panel up')\n .setOnclick(function() {\n this.parent_panel.moveUp();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n});\n\n/**\n * Button to move panel down relative to other panels (in terms of y-index on the page)\n * NOTE: Will only work on panel dashboards.\n * @class LocusZoom.Dashboard.Components.move_panel_down\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('move_panel_down', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) {\n var is_at_bottom = (this.parent_panel.layout.y_index === this.parent_plot.panel_ids_by_y_index.length - 1);\n this.button.disable(is_at_bottom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml('▾')\n .setTitle('Move panel down')\n .setOnclick(function() {\n this.parent_panel.moveDown();\n this.update();\n }.bind(this));\n this.button.show();\n return this.update();\n };\n});\n\n/**\n * Button to shift plot region forwards or back by a `step` increment provided in the layout\n * @class LocusZoom.Dashboard.Components.shift_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=50000] The stepsize to change the region by\n * @param {string} [layout.button_html]\n * @param {string} [layout.button_title]\n */\nLocusZoom.Dashboard.Components.add('shift_region', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function() {};\n console.warn('Unable to add shift_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) { layout.step = 50000; }\n if (typeof layout.button_html !== 'string') { layout.button_html = layout.step > 0 ? '>' : '<'; }\n if (typeof layout.button_title !== 'string') {\n layout.button_title = 'Shift region by ' + (layout.step > 0 ? '+' : '-') + LocusZoom.positionIntToString(Math.abs(layout.step),null,true);\n }\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start + layout.step, 1),\n end: this.parent_plot.state.end + layout.step\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Zoom in or out on the plot, centered on the middle of the plot region, by the specified amount\n * @class LocusZoom.Dashboard.Components.zoom_region\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {number} [layout.step=0.2] The amount to zoom in by (where 1 indicates 100%)\n */\nLocusZoom.Dashboard.Components.add('zoom_region', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (isNaN(this.parent_plot.state.start) || isNaN(this.parent_plot.state.end)) {\n this.update = function() {};\n console.warn('Unable to add zoom_region dashboard component: plot state does not have region bounds');\n return;\n }\n if (isNaN(layout.step) || layout.step === 0) { layout.step = 0.2; }\n if (typeof layout.button_html != 'string') { layout.button_html = layout.step > 0 ? 'z–' : 'z+'; }\n if (typeof layout.button_title != 'string') {\n layout.button_title = 'Zoom region ' + (layout.step > 0 ? 'out' : 'in') + ' by ' + (Math.abs(layout.step) * 100).toFixed(1) + '%';\n }\n this.update = function() {\n if (this.button) {\n var can_zoom = true;\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n if (layout.step > 0 && !isNaN(this.parent_plot.layout.max_region_scale) && current_region_scale >= this.parent_plot.layout.max_region_scale) {\n can_zoom = false;\n }\n if (layout.step < 0 && !isNaN(this.parent_plot.layout.min_region_scale) && current_region_scale <= this.parent_plot.layout.min_region_scale) {\n can_zoom = false;\n }\n this.button.disable(!can_zoom);\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n var current_region_scale = this.parent_plot.state.end - this.parent_plot.state.start;\n var zoom_factor = 1 + layout.step;\n var new_region_scale = current_region_scale * zoom_factor;\n if (!isNaN(this.parent_plot.layout.max_region_scale)) {\n new_region_scale = Math.min(new_region_scale, this.parent_plot.layout.max_region_scale);\n }\n if (!isNaN(this.parent_plot.layout.min_region_scale)) {\n new_region_scale = Math.max(new_region_scale, this.parent_plot.layout.min_region_scale);\n }\n var delta = Math.floor((new_region_scale - current_region_scale) / 2);\n this.parent_plot.applyState({\n start: Math.max(this.parent_plot.state.start - delta, 1),\n end: this.parent_plot.state.end + delta\n });\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Renders button with arbitrary text that, when clicked, shows a dropdown containing arbitrary HTML\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @class LocusZoom.Dashboard.Components.menu\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n * @param {string} layout.menu_html The HTML content of the dropdown menu\n */\nLocusZoom.Dashboard.Components.add('menu', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color).setHtml(layout.button_html).setTitle(layout.button_title);\n this.button.menu.setPopulate(function() {\n this.button.menu.inner_selector.html(layout.menu_html);\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Special button/menu to allow model building by tracking individual covariants. Will track a list of covariate\n * objects and store them in the special `model.covariates` field of plot `state`.\n * @class LocusZoom.Dashboard.Components.covariates_model\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {string} layout.button_html The HTML to render inside the button\n * @param {string} layout.button_title Text to display as a tooltip when hovering over the button\n */\nLocusZoom.Dashboard.Components.add('covariates_model', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n this.initialize = function() {\n // Initialize state.model.covariates\n this.parent_plot.state.model = this.parent_plot.state.model || {};\n this.parent_plot.state.model.covariates = this.parent_plot.state.model.covariates || [];\n // Create an object at the plot level for easy access to interface methods in custom client-side JS\n /**\n * When a covariates model dashboard element is present, create (one) object at the plot level that exposes\n * component data and state for custom interactions with other plot elements.\n * @class LocusZoom.Plot.CovariatesModel\n */\n this.parent_plot.CovariatesModel = {\n /** @member {LocusZoom.Dashboard.Component.Button} */\n button: this,\n /**\n * Add an element to the model and show a representation of it in the dashboard component menu. If the\n * element is already part of the model, do nothing (to avoid adding duplicates).\n * When plot state is changed, this will automatically trigger requests for new data accordingly.\n * @param {string|object} element_reference Can be any value that can be put through JSON.stringify()\n * to create a serialized representation of itself.\n */\n add: function(element_reference) {\n var element = JSON.parse(JSON.stringify(element_reference));\n if (typeof element_reference == 'object' && typeof element.html != 'string') {\n element.html = ( (typeof element_reference.toHTML == 'function') ? element_reference.toHTML() : element_reference.toString());\n }\n // Check if the element is already in the model covariates array and return if it is.\n for (var i = 0; i < this.state.model.covariates.length; i++) {\n if (JSON.stringify(this.state.model.covariates[i]) === JSON.stringify(element)) {\n return this;\n }\n }\n this.state.model.covariates.push(element);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Remove an element from `state.model.covariates` (and from the dashboard component menu's\n * representation of the state model). When plot state is changed, this will automatically trigger\n * requests for new data accordingly.\n * @param {number} idx Array index of the element, in the `state.model.covariates array`.\n */\n removeByIdx: function(idx) {\n if (typeof this.state.model.covariates[idx] == 'undefined') {\n throw new Error('Unable to remove model covariate, invalid index: ' + idx.toString());\n }\n this.state.model.covariates.splice(idx, 1);\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Empty the `state.model.covariates` array (and dashboard component menu representation thereof) of all\n * elements. When plot state is changed, this will automatically trigger requests for new data accordingly\n */\n removeAll: function() {\n this.state.model.covariates = [];\n this.applyState();\n this.CovariatesModel.updateComponent();\n return this;\n }.bind(this.parent_plot),\n /**\n * Manually trigger the update methods on the dashboard component's button and menu elements to force\n * display of most up-to-date content. Can be used to force the dashboard to reflect changes made, eg if\n * modifying `state.model.covariates` directly instead of via `plot.CovariatesModel`\n */\n updateComponent: function() {\n this.button.update();\n this.button.menu.update();\n }.bind(this)\n };\n }.bind(this);\n\n this.update = function() {\n\n if (this.button) { return this; }\n\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.button.menu.populate();\n }.bind(this));\n\n this.button.menu.setPopulate(function() {\n var selector = this.button.menu.inner_selector;\n selector.html('');\n // General model HTML representation\n if (typeof this.parent_plot.state.model.html != 'undefined') {\n selector.append('div').html(this.parent_plot.state.model.html);\n }\n // Model covariates table\n if (!this.parent_plot.state.model.covariates.length) {\n selector.append('i').html('no covariates in model');\n } else {\n selector.append('h5').html('Model Covariates (' + this.parent_plot.state.model.covariates.length + ')');\n var table = selector.append('table');\n this.parent_plot.state.model.covariates.forEach(function(covariate, idx) {\n var html = ( (typeof covariate == 'object' && typeof covariate.html == 'string') ? covariate.html : covariate.toString() );\n var row = table.append('tr');\n row.append('td').append('button')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color)\n .style({ 'margin-left': '0em' })\n .on('click', function() {\n this.parent_plot.CovariatesModel.removeByIdx(idx);\n }.bind(this))\n .html('×');\n row.append('td').html(html);\n }.bind(this));\n selector.append('button')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color)\n .style({ 'margin-left': '4px' }).html('× Remove All Covariates')\n .on('click', function() {\n this.parent_plot.CovariatesModel.removeAll();\n }.bind(this));\n }\n }.bind(this));\n\n this.button.preUpdate = function() {\n var html = 'Model';\n if (this.parent_plot.state.model.covariates.length) {\n var cov = this.parent_plot.state.model.covariates.length > 1 ? 'covariates' : 'covariate';\n html += ' (' + this.parent_plot.state.model.covariates.length + ' ' + cov + ')';\n }\n this.button.setHtml(html).disable(false);\n }.bind(this);\n\n this.button.show();\n\n return this;\n };\n});\n\n/**\n * Button to toggle split tracks\n * @class LocusZoom.Dashboard.Components.toggle_split_tracks\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('toggle_split_tracks', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n if (!layout.data_layer_id) { layout.data_layer_id = 'intervals'; }\n if (!this.parent_panel.data_layers[layout.data_layer_id]) {\n throw new Error('Dashboard toggle split tracks component missing valid data layer ID');\n }\n this.update = function() {\n var data_layer = this.parent_panel.data_layers[layout.data_layer_id];\n var html = data_layer.layout.split_tracks ? 'Merge Tracks' : 'Split Tracks';\n if (this.button) {\n this.button.setHtml(html);\n this.button.show();\n this.parent.position();\n return this;\n } else {\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(html)\n .setTitle('Toggle whether tracks are split apart or merged together')\n .setOnclick(function() {\n data_layer.toggleSplitTracks();\n if (this.scale_timeout) { clearTimeout(this.scale_timeout); }\n var timeout = data_layer.layout.transition ? +data_layer.layout.transition.duration || 0 : 0;\n this.scale_timeout = setTimeout(function() {\n this.parent_panel.scaleHeightToData();\n this.parent_plot.positionPanels();\n }.bind(this), timeout);\n this.update();\n }.bind(this));\n return this.update();\n }\n };\n});\n\n/**\n * Button to resize panel height to fit available data (eg when showing a list of tracks)\n * @class LocusZoom.Dashboard.Components.resize_to_data\n * @augments LocusZoom.Dashboard.Component\n * @param {string} [layout.button_html=\"Resize to Data\"]\n * @param {string} [layout.button_title]\n */\nLocusZoom.Dashboard.Components.add('resize_to_data', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n if (this.button) { return this; }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html || 'Resize to Data')\n .setTitle(layout.button_title || 'Automatically resize this panel to show all data available')\n .setOnclick(function() {\n this.parent_panel.scaleHeightToData();\n this.update();\n }.bind(this));\n this.button.show();\n return this;\n };\n});\n\n/**\n * Button to toggle legend\n * @class LocusZoom.Dashboard.Components.toggle_legend\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('toggle_legend', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n this.update = function() {\n var html = this.parent_panel.legend.layout.hidden ? 'Show Legend' : 'Hide Legend';\n if (this.button) {\n this.button.setHtml(html).show();\n this.parent.position();\n return this;\n }\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setTitle('Show or hide the legend for this panel')\n .setOnclick(function() {\n this.parent_panel.legend.layout.hidden = !this.parent_panel.legend.layout.hidden;\n this.parent_panel.legend.render();\n this.update();\n }.bind(this));\n return this.update();\n };\n});\n\n/**\n * Menu for manipulating multiple data layers in a single panel: show/hide, change order, etc.\n * @class LocusZoom.Dashboard.Components.data_layers\n * @augments LocusZoom.Dashboard.Component\n */\nLocusZoom.Dashboard.Components.add('data_layers', function(layout) {\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n this.update = function() {\n\n if (typeof layout.button_html != 'string') { layout.button_html = 'Data Layers'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Manipulate Data Layers (sort, dim, show/hide, etc.)'; }\n\n if (this.button) { return this; }\n\n this.button = new LocusZoom.Dashboard.Component.Button(this)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function() {\n this.button.menu.populate();\n }.bind(this));\n\n this.button.menu.setPopulate(function() {\n this.button.menu.inner_selector.html('');\n var table = this.button.menu.inner_selector.append('table');\n this.parent_panel.data_layer_ids_by_z_index.slice().reverse().forEach(function(id, idx) {\n var data_layer = this.parent_panel.data_layers[id];\n var name = (typeof data_layer.layout.name != 'string') ? data_layer.id : data_layer.layout.name;\n var row = table.append('tr');\n // Layer name\n row.append('td').html(name);\n // Status toggle buttons\n layout.statuses.forEach(function(status_adj) {\n var status_idx = LocusZoom.DataLayer.Statuses.adjectives.indexOf(status_adj);\n var status_verb = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n var html, onclick, highlight;\n if (data_layer.global_statuses[status_adj]) {\n html = LocusZoom.DataLayer.Statuses.menu_antiverbs[status_idx];\n onclick = 'un' + status_verb + 'AllElements';\n highlight = '-highlighted';\n } else {\n html = LocusZoom.DataLayer.Statuses.verbs[status_idx];\n onclick = status_verb + 'AllElements';\n highlight = '';\n }\n row.append('td').append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-' + this.layout.color + highlight)\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer[onclick](); this.button.menu.populate(); }.bind(this))\n .html(html);\n }.bind(this));\n // Sort layer buttons\n var at_top = (idx === 0);\n var at_bottom = (idx === (this.parent_panel.data_layer_ids_by_z_index.length - 1));\n var td = row.append('td');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-start lz-dashboard-button-' + this.layout.color + (at_bottom ? '-disabled' : ''))\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer.moveDown(); this.button.menu.populate(); }.bind(this))\n .html('▾').attr('title', 'Move layer down (further back)');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-middle lz-dashboard-button-' + this.layout.color + (at_top ? '-disabled' : ''))\n .style({ 'margin-left': '0em' })\n .on('click', function() { data_layer.moveUp(); this.button.menu.populate(); }.bind(this))\n .html('▴').attr('title', 'Move layer up (further front)');\n td.append('a')\n .attr('class', 'lz-dashboard-button lz-dashboard-button-group-end lz-dashboard-button-red')\n .style({ 'margin-left': '0em' })\n .on('click', function() {\n if (confirm('Are you sure you want to remove the ' + name + ' layer? This cannot be undone!')) {\n data_layer.parent.removeDataLayer(id);\n }\n return this.button.menu.populate();\n }.bind(this))\n .html('×').attr('title', 'Remove layer');\n }.bind(this));\n return this;\n }.bind(this));\n\n this.button.show();\n\n return this;\n };\n});\n\n/**\n * Dropdown menu allowing the user to choose between different display options for a single specific data layer\n * within a panel.\n *\n * This allows controlling how points on a datalayer can be displayed- any display options supported via the layout for the target datalayer. This includes point\n * size/shape, coloring, etc.\n *\n * This button intentionally limits display options it can control to those available on common plot types.\n * Although the list of options it sets can be overridden (to control very special custom plot types), this\n * capability should be used sparingly if at all.\n *\n * @class LocusZoom.Dashboard.Components.display_options\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Display options...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Control how plot items are displayed\"] Hover text for the toolbar button\n * @param {string} layout.layer_name Specify the datalayer that this button should affect\n * @param {string} [layout.default_config_display_name] Store the default configuration for this datalayer\n * configuration, and show a button to revert to the \"default\" (listing the human-readable display name provided)\n * @param {Array} [layout.fields_whitelist='see code'] The list of presentation fields that this button can control.\n * This can be overridden if this button needs to be used on a custom layer type with special options.\n * @typedef {{display_name: string, display: Object}} DisplayOptionsButtonConfigField\n * @param {DisplayOptionsButtonConfigField[]} layout.options Specify a label and set of layout directives associated\n * with this `display` option. Display field should include all changes to datalayer presentation options.\n */\nLocusZoom.Dashboard.Components.add('display_options', function (layout) {\n if (typeof layout.button_html != 'string') { layout.button_html = 'Display options...'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Control how plot items are displayed'; }\n\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n // List of layout fields that this button is allowed to control. This ensures that we don't override any other\n // information (like plot height etc) while changing point rendering\n var allowed_fields = layout.fields_whitelist || ['color', 'fill_opacity', 'label', 'legend',\n 'point_shape', 'point_size', 'tooltip', 'tooltip_positioning'];\n\n var dataLayer = this.parent_panel.data_layers[layout.layer_name];\n if (!dataLayer) {\n throw new Error(\"Display options could not locate the specified layer_name: '\" + layout.layer_name + \"'\");\n }\n var dataLayerLayout = dataLayer.layout;\n\n // Store default configuration for the layer as a clean deep copy, so we may revert later\n var defaultConfig = {};\n allowed_fields.forEach(function(name) {\n var configSlot = dataLayerLayout[name];\n if (configSlot !== undefined) {\n defaultConfig[name] = JSON.parse(JSON.stringify(configSlot));\n }\n });\n\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n this._selected_item = 'default';\n\n // Define the button + menu that provides the real functionality for this dashboard component\n var self = this;\n this.button = new LocusZoom.Dashboard.Component.Button(self)\n .setColor(layout.color)\n .setHtml(layout.button_html)\n .setTitle(layout.button_title)\n .setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 1e4).toString();\n\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n\n var menuLayout = self.layout;\n\n var renderRow = function(display_name, display_options, row_id) { // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td')\n .append('input')\n .attr({id: radioId, type: 'radio', name: 'display-option-' + uniqueID, value: row_id})\n .style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n .property('checked', (row_id === self._selected_item))\n .on('click', function () {\n // If an option is not specified in these display options, use the original defaults\n allowed_fields.forEach(function(field_name) {\n dataLayer.layout[field_name] = display_options[field_name] || defaultConfig[field_name];\n });\n\n self._selected_item = row_id;\n self.parent_panel.render();\n var legend = self.parent_panel.legend;\n if (legend) {\n legend.render();\n }\n });\n row.append('td').append('label')\n .style('font-weight', 'normal')\n .attr('for', radioId)\n .text(display_name);\n };\n // Render the \"display options\" menu: default and special custom options\n var defaultName = menuLayout.default_config_display_name || 'Default style';\n renderRow(defaultName, defaultConfig, 'default');\n menuLayout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.display, index);\n });\n return self;\n });\n\n this.update = function () {\n this.button.show();\n return this;\n };\n});\n\n\n/**\n * Dropdown menu allowing the user to set the value of a specific `state_field` in plot.state\n * This is useful for things (like datasources) that allow dynamic configuration based on global information in state\n *\n * For example, the LDLZ2 data source can use it to change LD reference population (for all panels) after render\n *\n * @class LocusZoom.Dashboard.Components.set_state\n * @augments LocusZoom.Dashboard.Component\n * @param {object} layout\n * @param {String} [layout.button_html=\"Set option...\"] Text to display on the toolbar button\n * @param {String} [layout.button_title=\"Choose an option to customize the plot\"] Hover text for the toolbar button\n * @param {bool} [layout.show_selected=false] Whether to append the selected value to the button label\n * @param {string} [layout.state_field] The name of the field in plot.state that will be set by this button\n * @typedef {{display_name: string, value: *}} SetStateOptionsConfigField\n * @param {SetStateOptionsConfigField[]} layout.options Specify human labels and associated values for the dropdown menu\n */\nLocusZoom.Dashboard.Components.add('set_state', function (layout) {\n var self = this;\n if (typeof layout.button_html != 'string') { layout.button_html = 'Set option...'; }\n if (typeof layout.button_title != 'string') { layout.button_title = 'Choose an option to customize the plot'; }\n\n // Call parent constructor\n LocusZoom.Dashboard.Component.apply(this, arguments);\n\n if (this.parent_panel) {\n throw new Error('This widget is designed to set global options, so it can only be used at the top (plot) level');\n }\n if (!layout.state_field) {\n throw new Error('Must specify the `state_field` that this widget controls');\n }\n\n /**\n * Which item in the menu is currently selected. (track for rerendering menu)\n * @member {String}\n * @private\n */\n // The first option listed is automatically assumed to be the default, unless a value exists in plot.state\n this._selected_item = this.parent_plot.state[layout.state_field] || layout.options[0].value;\n if (!layout.options.find(function(item) { return item.value === self._selected_item; })) {\n // Check only gets run at widget creation, but generally this widget is assumed to be an exclusive list of options\n throw new Error('There is an existing state value that does not match the known values in this widget');\n }\n\n // Define the button + menu that provides the real functionality for this dashboard component\n this.button = new LocusZoom.Dashboard.Component.Button(self)\n .setColor(layout.color)\n .setHtml(layout.button_html + (layout.show_selected ? this._selected_item : ''))\n .setTitle(layout.button_title)\n .setOnclick(function () {\n self.button.menu.populate();\n });\n this.button.menu.setPopulate(function () {\n // Multiple copies of this button might be used on a single LZ page; append unique IDs where needed\n var uniqueID = Math.floor(Math.random() * 1e4).toString();\n\n self.button.menu.inner_selector.html('');\n var table = self.button.menu.inner_selector.append('table');\n\n var renderRow = function(display_name, value, row_id) { // Helper method\n var row = table.append('tr');\n var radioId = '' + uniqueID + row_id;\n row.append('td')\n .append('input')\n .attr({id: radioId, type: 'radio', name: 'set-state-' + uniqueID, value: row_id})\n .style('margin', 0) // Override css libraries (eg skeleton) that style form inputs\n .property('checked', (value === self._selected_item))\n .on('click', function () {\n var new_state = {};\n new_state[layout.state_field] = value;\n self._selected_item = value;\n self.parent_plot.applyState(new_state);\n self.button.setHtml(layout.button_html + (layout.show_selected ? self._selected_item : ''));\n });\n row.append('td').append('label')\n .style('font-weight', 'normal')\n .attr('for', radioId)\n .text(display_name);\n };\n layout.options.forEach(function (item, index) {\n renderRow(item.display_name, item.value, index);\n });\n return self;\n });\n\n this.update = function () {\n this.button.show();\n return this;\n };\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n *\n * LocusZoom has various singleton objects that are used for registering functions or classes.\n * These objects provide safe, standard methods to redefine or delete existing functions/classes\n * as well as define new custom functions/classes to be used in a plot.\n *\n * @namespace Singletons\n */\n\n\n/*\n * The Collection of \"Known\" Data Sources. This registry is used internally by the `DataSources` class\n * @class\n * @static\n */\nLocusZoom.KnownDataSources = (function() {\n /** @lends LocusZoom.KnownDataSources */\n var obj = {};\n /* @member {function[]} */\n var sources = [];\n\n var findSourceByName = function(x) {\n for(var i = 0; i < sources.length; i++) {\n if (!sources[i].SOURCE_NAME) {\n throw new Error('KnownDataSources at position ' + i + \" does not have a 'SOURCE_NAME' static property\");\n }\n if (sources[i].SOURCE_NAME === x) {\n return sources[i];\n }\n }\n return null;\n };\n\n /**\n * Identify the datasource associated with a given name\n * @param {String} name\n * @returns {function} The constructor for the data source; will usually extend `Data.Source`\n */\n obj.get = function(name) {\n return findSourceByName(name);\n };\n\n /**\n * Register a data source constructor so that it may be located by name\n * @param {function} source A constructor function for a data source; will usually extend `Data.Source`,\n * and should have a `SOURCE_NAME` property\n */\n obj.add = function(source) {\n if (!source.SOURCE_NAME) {\n console.warn('Data source added does not have a SOURCE_NAME');\n }\n sources.push(source);\n };\n\n /**\n * Create a custom source type that extends the behavior of an existing source, and registers that\n * source by the provided name\n * @param {String} parent_name The name of a previously registered data source type to use as a template\n * @param {String} source_name The new name to use when registering this data source\n * @param {Object} overrides An object of additional properties and methods to add/override behavior\n * @returns {LocusZoom.Data.Source} The newly defined class for this source\n */\n obj.extend = function(parent_name, source_name, overrides) {\n var parent = findSourceByName(parent_name);\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered data source');\n }\n if (!source_name) {\n throw new Error('Must provide a name for the new data source');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n child.SOURCE_NAME = source_name;\n sources.push(child);\n return child;\n };\n\n /** @deprecated */\n obj.push = function(source) {\n console.warn('Warning: KnownDataSources.push() is deprecated. Use .add() instead');\n obj.add(source);\n };\n\n /**\n * List the names of all registered datasources\n * @returns {String[]}\n */\n obj.list = function() {\n return sources.map(function(x) {return x.SOURCE_NAME;});\n };\n\n /**\n * Create a datasource instance\n * @param {String} name The name of the desired datasource to instantiate (must be defined in the registry)\n * @returns {LocusZoom.Data.Source}\n */\n obj.create = function(name) {\n //create new object (pass additional parameters to constructor)\n var newObj = findSourceByName(name);\n if (newObj) {\n var params = arguments;\n params[0] = null;\n return new (Function.prototype.bind.apply(newObj, params));\n } else {\n throw new Error('Unable to find data source for name: ' + name);\n }\n };\n\n /**\n * Get the array of all registered constructors\n * Generally only used for unit tests internally\n * @private\n * @returns {function[]}\n */\n obj.getAll = function() {\n return sources;\n };\n\n /**\n * Register an entire collection of data sources\n * Generally only used for unit tests internally\n * @private\n * @param {function[]} x An array of datasource constructors\n */\n obj.setAll = function(x) {\n sources = x;\n };\n\n /**\n * Unregister all known data sources\n * Generally only used for unit tests internally\n * @private\n */\n obj.clear = function() {\n sources = [];\n };\n\n return obj;\n})();\n\n/**************************\n * Transformation Functions\n *\n * Singleton for formatting or transforming a single input, for instance turning raw p values into negative log10 form\n * Transformation functions are chainable with a pipe on a field name, like so: \"pvalue|neglog10\"\n *\n * NOTE: Because these functions are chainable the FUNCTION is returned by get(), not the result of that function.\n *\n * All transformation functions must accept an object of parameters and a value to process.\n * @class\n */\nLocusZoom.TransformationFunctions = (function() {\n /** @lends LocusZoom.TransformationFunctions */\n var obj = {};\n var transformations = {};\n\n var getTrans = function(name) {\n if (!name) {\n return null;\n }\n var fun = transformations[name];\n if (fun) {\n return fun;\n } else {\n throw new Error('transformation ' + name + ' not found');\n }\n };\n\n //a single transformation with any parameters\n //(parameters not currently supported)\n var parseTrans = function(name) {\n return getTrans(name);\n };\n\n //a \"raw\" transformation string with a leading pipe\n //and one or more transformations\n var parseTransString = function(x) {\n var funs = [];\n var re = /\\|([^|]+)/g;\n var result;\n while((result = re.exec(x)) !== null) {\n funs.push(result[1]);\n }\n if (funs.length === 1) {\n return parseTrans(funs[0]);\n } else if (funs.length > 1) {\n return function(x) {\n var val = x;\n for(var i = 0; i < funs.length; i++) {\n val = parseTrans(funs[i])(val);\n }\n return val;\n };\n }\n return null;\n };\n\n /**\n * Retrieve a transformation function by name\n * @param {String} name The name of the transformation function to retrieve. May optionally be prefixed with a\n * pipe (`|`) when chaining multiple transformation functions.\n * @returns {function} The constructor for the transformation function\n */\n obj.get = function(name) {\n if (name && name.substring(0,1) === '|') {\n return parseTransString(name);\n } else {\n return parseTrans(name);\n }\n };\n /**\n * Internal logic that registers a transformation function\n * @protected\n * @param {String} name\n * @param {function} fn\n */\n obj.set = function(name, fn) {\n if (name.substring(0,1) === '|') {\n throw new Error('transformation name should not start with a pipe');\n } else {\n if (fn) {\n transformations[name] = fn;\n } else {\n delete transformations[name];\n }\n }\n };\n\n /**\n * Register a transformation function\n * @param {String} name\n * @param {function} fn A transformation function (should accept one argument with the value)\n */\n obj.add = function(name, fn) {\n if (transformations[name]) {\n throw new Error('transformation already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n /**\n * List the names of all registered transformation functions\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(transformations);\n };\n\n return obj;\n})();\n\n/**\n * Return the -log (base 10)\n * @function neglog10\n */\nLocusZoom.TransformationFunctions.add('neglog10', function(x) {\n if (isNaN(x) || x <= 0) { return null; }\n return -Math.log(x) / Math.LN10;\n});\n\n/**\n * Convert a number from logarithm to scientific notation. Useful for, eg, a datasource that returns -log(p) by default\n * @function logtoscinotation\n */\nLocusZoom.TransformationFunctions.add('logtoscinotation', function(x) {\n if (isNaN(x)) { return 'NaN'; }\n if (x === 0) { return '1'; }\n var exp = Math.ceil(x);\n var diff = exp - x;\n var base = Math.pow(10, diff);\n if (exp === 1) {\n return (base / 10).toFixed(4);\n } else if (exp === 2) {\n return (base / 100).toFixed(3);\n } else {\n return base.toFixed(2) + ' × 10^-' + exp;\n }\n});\n\n/**\n * Represent a number in scientific notation\n * @function scinotation\n * @param {Number} x\n * @returns {String}\n */\nLocusZoom.TransformationFunctions.add('scinotation', function(x) {\n if (isNaN(x)) { return 'NaN'; }\n if (x === 0) { return '0'; }\n\n var abs = Math.abs(x);\n var log;\n if (abs > 1) {\n log = Math.ceil(Math.log(abs) / Math.LN10);\n } else { // 0...1\n log = Math.floor(Math.log(abs) / Math.LN10);\n }\n if (Math.abs(log) <= 3) {\n return x.toFixed(3);\n } else {\n return x.toExponential(2).replace('+', '').replace('e', ' × 10^');\n }\n});\n\n/**\n * URL-encode the provided text, eg for constructing hyperlinks\n * @function urlencode\n * @param {String} str\n */\nLocusZoom.TransformationFunctions.add('urlencode', function(str) {\n return encodeURIComponent(str);\n});\n\n/**\n * HTML-escape user entered values for use in constructed HTML fragments\n *\n * For example, this filter can be used on tooltips with custom HTML display\n * @function htmlescape\n * @param {String} str HTML-escape the provided value\n */\nLocusZoom.TransformationFunctions.add('htmlescape', function(str) {\n if ( !str ) {\n return '';\n }\n str = str + '';\n\n return str.replace( /['\"<>&`]/g, function( s ) {\n switch ( s ) {\n case \"'\":\n return ''';\n case '\"':\n return '"';\n case '<':\n return '<';\n case '>':\n return '>';\n case '&':\n return '&';\n case '`':\n return '`';\n }\n });\n});\n\n/**\n * Singleton for accessing/storing functions that will convert arbitrary data points to values in a given scale\n * Useful for anything that needs to scale discretely with data (e.g. color, point size, etc.)\n *\n * A Scale Function can be thought of as a modifier to a layout directive that adds extra logic to how a piece of data\n * can be resolved to a value.\n *\n * All scale functions must accept an object of parameters and a value to process.\n * @class\n * @static\n */\nLocusZoom.ScaleFunctions = (function() {\n /** @lends LocusZoom.ScaleFunctions */\n var obj = {};\n var functions = {};\n\n /**\n * Find a scale function and return it. If parameters and values are passed, calls the function directly; otherwise\n * returns a callable.\n * @param {String} name\n * @param {Object} [parameters] Configuration parameters specific to the specified scale function\n * @param {*} [value] The value to operate on\n * @returns {*}\n */\n obj.get = function(name, parameters, value) {\n if (!name) {\n return null;\n } else if (functions[name]) {\n if (typeof parameters === 'undefined' && typeof value === 'undefined') {\n return functions[name];\n } else {\n return functions[name](parameters, value);\n }\n } else {\n throw new Error('scale function [' + name + '] not found');\n }\n };\n\n /**\n * @protected\n * @param {String} name The name of the function to set/unset\n * @param {Function} [fn] The function to register. If blank, removes this function name from the registry.\n */\n obj.set = function(name, fn) {\n if (fn) {\n functions[name] = fn;\n } else {\n delete functions[name];\n }\n };\n\n /**\n * Add a new scale function to the registry\n * @param {String} name The name of the scale function\n * @param {function} fn A scale function that accepts two parameters: an object of configuration and a value\n */\n obj.add = function(name, fn) {\n if (functions[name]) {\n throw new Error('scale function already exists with name: ' + name);\n } else {\n obj.set(name, fn);\n }\n };\n\n /**\n * List the names of all registered scale functions\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(functions);\n };\n\n return obj;\n})();\n\n/**\n * Basic conditional function to evaluate the value of the input field and return based on equality.\n * @param {Object} parameters\n * @param {*} parameters.field_value The value against which to test the input value.\n * @param {*} parameters.then The value to return if the input value matches the field value\n * @param {*} parameters.else The value to return if the input value does not match the field value. Optional. If not\n * defined this scale function will return null (or value of null_value parameter, if defined) when input value fails\n * to match field_value.\n * @param {*} input value\n */\nLocusZoom.ScaleFunctions.add('if', function(parameters, input) {\n if (typeof input == 'undefined' || parameters.field_value !== input) {\n if (typeof parameters.else != 'undefined') {\n return parameters.else;\n } else {\n return null;\n }\n } else {\n return parameters.then;\n }\n});\n\n/**\n * Function to sort numerical values into bins based on numerical break points. Will only operate on numbers and\n * return null (or value of null_value parameter, if defined) if provided a non-numeric input value. Parameters:\n * @function numerical_bin\n * @param {Object} parameters\n * @param {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter. If the input value is greater than or equal to break n and less than\n * or equal to break n+1 (or break n+1 doesn't exist) then returned value is the nth entry in the values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against break points. Must be of\n * equal length to breaks parameter. Each entry n represents the value to return if the input value is greater than\n * or equal to break n and less than or equal to break n+1 (or break n+1 doesn't exist).\n * @param {*} null_value\n * @param {*} input value\n * @returns\n */\nLocusZoom.ScaleFunctions.add('numerical_bin', function(parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n if (typeof input == 'undefined' || input === null || isNaN(+input)) {\n return (parameters.null_value ? parameters.null_value : null);\n }\n var threshold = breaks.reduce(function(prev, curr) {\n if (+input < prev || (+input >= prev && +input < curr)) {\n return prev;\n } else {\n return curr;\n }\n });\n return values[breaks.indexOf(threshold)];\n});\n\n/**\n * Function to sort values of any type into bins based on direct equality testing with a list of categories.\n * Will return null if provided an input value that does not match to a listed category.\n * @function categorical_bin\n * @param {Object} parameters\n * @param {Array} parameters.categories Array of values against which to evaluate the input value. Must be of equal\n * length to values parameter. If the input value is equal to category n then returned value is the nth entry in the\n * values parameter.\n * @param {Array} parameters.values Array of values to return given evaluations against categories. Must be of equal\n * length to categories parameter. Each entry n represents the value to return if the input value is equal to the nth\n * value in the categories parameter.\n * @param {*} parameters.null_value Value to return if the input value fails to match to any categories. Optional.\n */\nLocusZoom.ScaleFunctions.add('categorical_bin', function(parameters, value) {\n if (typeof value == 'undefined' || parameters.categories.indexOf(value) === -1) {\n return (parameters.null_value ? parameters.null_value : null);\n } else {\n return parameters.values[parameters.categories.indexOf(value)];\n }\n});\n\n/**\n * Function for continuous interpolation of numerical values along a gradient with arbitrarily many break points.\n * @function interpolate\n * @parameters {Object} parameters\n * @parameters {Number[]} parameters.breaks Array of numerical break points against which to evaluate the input value.\n * Must be of equal length to values parameter and contain at least two elements. Input value will be evaluated for\n * relative position between two break points n and n+1 and the returned value will be interpolated at a relative\n * position between values n and n+1.\n * @parameters {*[]} parameters.values Array of values to interpolate and return given evaluations against break\n * points. Must be of equal length to breaks parameter and contain at least two elements. Each entry n represents\n * the value to return if the input value matches the nth entry in breaks exactly. Note that this scale function\n * uses d3.interpolate to provide for effective interpolation of many different value types, including numbers,\n * colors, shapes, etc.\n * @parameters {*} parameters.null_value\n */\nLocusZoom.ScaleFunctions.add('interpolate', function(parameters, input) {\n var breaks = parameters.breaks || [];\n var values = parameters.values || [];\n var nullval = (parameters.null_value ? parameters.null_value : null);\n if (breaks.length < 2 || breaks.length !== values.length) { return nullval; }\n if (typeof input == 'undefined' || input === null || isNaN(+input)) { return nullval; }\n if (+input <= parameters.breaks[0]) {\n return values[0];\n } else if (+input >= parameters.breaks[parameters.breaks.length - 1]) {\n return values[breaks.length - 1];\n } else {\n var upper_idx = null;\n breaks.forEach(function(brk, idx) {\n if (!idx) { return; }\n if (breaks[idx - 1] <= +input && breaks[idx] >= +input) { upper_idx = idx; }\n });\n if (upper_idx === null) { return nullval; }\n var normalized_input = (+input - breaks[upper_idx - 1]) / (breaks[upper_idx] - breaks[upper_idx - 1]);\n if (!isFinite(normalized_input)) { return nullval; }\n return d3.interpolate(values[upper_idx - 1], values[upper_idx])(normalized_input);\n }\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A data layer is an abstract class representing a data set and its graphical representation within a panel\n * @public\n * @class\n * @param {Object} layout A JSON-serializable object describing the layout for this layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n*/\nLocusZoom.DataLayer = function(layout, parent) {\n /** @member {Boolean} */\n this.initialized = false;\n /** @member {Number} */\n this.layout_idx = null;\n\n /** @member {String} */\n this.id = null;\n /** @member {LocusZoom.Panel} */\n this.parent = parent || null;\n /**\n * @member {{group: d3.selection, container: d3.selection, clipRect: d3.selection}}\n */\n this.svg = {};\n\n /** @member {LocusZoom.Plot} */\n this.parent_plot = null;\n if (typeof parent != 'undefined' && parent instanceof LocusZoom.Panel) { this.parent_plot = parent.parent; }\n\n /** @member {Object} */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.DataLayer.DefaultLayout);\n if (this.layout.id) { this.id = this.layout.id; }\n\n // Ensure any axes defined in the layout have an explicit axis number (default: 1)\n if (this.layout.x_axis !== {} && typeof this.layout.x_axis.axis !== 'number') { this.layout.x_axis.axis = 1; }\n if (this.layout.y_axis !== {} && typeof this.layout.y_axis.axis !== 'number') { this.layout.y_axis.axis = 1; }\n\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original data layer state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n\n /** @member {Object} */\n this.state = {};\n /** @member {String} */\n this.state_id = null;\n\n this.setDefaultState();\n\n // Initialize parameters for storing data and tool tips\n /** @member {Array} */\n this.data = [];\n if (this.layout.tooltip) {\n /** @member {Object} */\n this.tooltips = {};\n }\n\n // Initialize flags for tracking global statuses\n this.global_statuses = {\n 'highlighted': false,\n 'selected': false,\n 'faded': false,\n 'hidden': false\n };\n\n return this;\n\n};\n\n/**\n * Instruct this datalayer to begin tracking additional fields from data sources (does not guarantee that such a field actually exists)\n *\n * Custom plots can use this to dynamically extend datalayer functionality after the plot is drawn\n *\n * (since removing core fields may break layer functionality, there is presently no hook for the inverse behavior)\n * @param fieldName\n * @param namespace\n * @param {String|String[]} transformations The name (or array of names) of transformations to apply to this field\n * @returns {String} The raw string added to the fields array\n */\nLocusZoom.DataLayer.prototype.addField = function(fieldName, namespace, transformations) {\n if (!fieldName || !namespace) {\n throw new Error('Must specify field name and namespace to use when adding field');\n }\n var fieldString = namespace + ':' + fieldName;\n if (transformations) {\n fieldString += '|';\n if (typeof transformations === 'string') {\n fieldString += transformations;\n } else if (Array.isArray(transformations)) {\n fieldString += transformations.join('|');\n } else {\n throw new Error('Must provide transformations as either a string or array of strings');\n }\n }\n var fields = this.layout.fields;\n if (fields.indexOf(fieldString) === -1) {\n fields.push(fieldString);\n }\n return fieldString;\n};\n\n/**\n * Define default state that should get tracked during the lifetime of this layer.\n *\n * In some special custom usages, it may be useful to completely reset a panel (eg \"click for\n * genome region\" links), plotting new data that invalidates any previously tracked state. This hook makes it\n * possible to reset without destroying the panel entirely. It is used by `Plot.clearPanelData`.\n */\nLocusZoom.DataLayer.prototype.setDefaultState = function() {\n // Define state parameters specific to this data layer. Within plot state, this will live under a key\n // `panel_name.layer_name`.\n if (this.parent) {\n this.state = this.parent.state;\n this.state_id = this.parent.id + '.' + this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n var layer_state = this.state[this.state_id];\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function(status) {\n layer_state[status] = layer_state[status] || [];\n });\n // Also initialize \"internal-only\" state fields\n layer_state['has_tooltip'] = layer_state['has_tooltip'] || [];\n }\n};\n\n/**\n * A basic description of keys expected in a layout. Not intended to be directly used or modified by an end user.\n * @protected\n * @type {{type: string, fields: Array, x_axis: {}, y_axis: {}}}\n */\nLocusZoom.DataLayer.DefaultLayout = {\n type: '',\n fields: [],\n x_axis: {},\n y_axis: {}\n};\n\n/**\n * Available statuses that individual elements can have. Each status is described by\n * a verb/antiverb and an adjective. Verbs and antiverbs are used to generate data layer\n * methods for updating the status on one or more elements. Adjectives are used in class\n * names and applied or removed from elements to have a visual representation of the status,\n * as well as used as keys in the state for tracking which elements are in which status(es)\n * @static\n * @type {{verbs: String[], adjectives: String[], menu_antiverbs: String[]}}\n */\nLocusZoom.DataLayer.Statuses = {\n verbs: ['highlight', 'select', 'fade', 'hide'],\n adjectives: ['highlighted', 'selected', 'faded', 'hidden'],\n menu_antiverbs: ['unhighlight', 'deselect', 'unfade', 'show']\n};\n\n/**\n * Get the fully qualified identifier for the data layer, prefixed by any parent or container elements\n *\n * @returns {string} A dot-delimited string of the format ..\n */\nLocusZoom.DataLayer.prototype.getBaseId = function() {\n return this.parent_plot.id + '.' + this.parent.id + '.' + this.id;\n};\n\n/**\n * Determine the pixel height of data-bound objects represented inside this data layer. (excluding elements such as axes)\n *\n * May be used by operations that resize the data layer to fit available data\n *\n * @public\n * @returns {number}\n */\nLocusZoom.DataLayer.prototype.getAbsoluteDataHeight = function() {\n var dataBCR = this.svg.group.node().getBoundingClientRect();\n return dataBCR.height;\n};\n\n/**\n * Whether transitions can be applied to this data layer\n * @returns {boolean}\n */\nLocusZoom.DataLayer.prototype.canTransition = function() {\n if (!this.layout.transition) { return false; }\n return !(this.parent_plot.panel_boundaries.dragging || this.parent_plot.interaction.panel_id);\n};\n\n/**\n * Fetch the fully qualified ID to be associated with a specific visual element, based on the data to which that\n * element is bound. In general this element ID will be unique, allowing it to be addressed directly via selectors.\n * @param {String|Object} element\n * @returns {String}\n */\nLocusZoom.DataLayer.prototype.getElementId = function(element) {\n var element_id = 'element';\n if (typeof element == 'string') {\n element_id = element;\n } else if (typeof element == 'object') {\n var id_field = this.layout.id_field || 'id';\n if (typeof element[id_field] == 'undefined') {\n throw new Error('Unable to generate element ID');\n }\n element_id = element[id_field].toString().replace(/\\W/g,'');\n }\n return (this.getBaseId() + '-' + element_id).replace(/([:.[\\],])/g, '_');\n};\n\n/**\n * Fetch an ID that may bind a data element to a separate visual node for displaying status\n * Examples of this might be seperate visual nodes to show select/highlight statuses, or\n * even a common/shared node to show status across many elements in a set.\n * Abstract method. It should be overridden by data layers that implement seperate status\n * nodes specifically to the use case of the data layer type.\n * @param {String|Object} element\n * @returns {String|null}\n */\nLocusZoom.DataLayer.prototype.getElementStatusNodeId = function(element) {\n return null;\n};\n\n/**\n * Returns a reference to the underlying data associated with a single visual element in the data layer, as\n * referenced by the unique identifier for the element\n\n * @param {String} id The unique identifier for the element, as defined by `getElementId`\n * @returns {Object|null} The data bound to that element\n */\nLocusZoom.DataLayer.prototype.getElementById = function(id) {\n var selector = d3.select('#' + id.replace(/([:.[\\],])/g, '\\\\$1')); // escape special characters\n if (!selector.empty() && selector.data() && selector.data().length) {\n return selector.data()[0];\n } else {\n return null;\n }\n};\n\n/**\n * Basic method to apply arbitrary methods and properties to data elements.\n * This is called on all data immediately after being fetched.\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.applyDataMethods = function() {\n var field_to_match = (this.layout.match && this.layout.match.receive);\n var broadcast_value = this.parent_plot.state.lz_match_value;\n\n this.data.forEach(function(d, i) {\n // Basic toHTML() method - return the stringified value in the id_field, if defined.\n\n // When this layer receives data, mark whether points match (via a synthetic boolean field)\n // Any field-based layout directives (color, size, shape) can then be used to control display\n if (field_to_match && broadcast_value !== null && broadcast_value !== undefined) {\n d.lz_highlight_match = (d[field_to_match] === broadcast_value);\n }\n\n this.data[i].toHTML = function() {\n var id_field = this.layout.id_field || 'id';\n var html = '';\n if (this.data[i][id_field]) { html = this.data[i][id_field].toString(); }\n return html;\n }.bind(this);\n // getDataLayer() method - return a reference to the data layer\n this.data[i].getDataLayer = function() {\n return this;\n }.bind(this);\n // deselect() method - shortcut method to deselect the element\n this.data[i].deselect = function() {\n var data_layer = this.getDataLayer();\n data_layer.unselectElement(this);\n };\n }.bind(this));\n this.applyCustomDataMethods();\n return this;\n};\n\n/**\n * Hook that allows custom datalayers to apply additional methods and properties to data elements as needed\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.applyCustomDataMethods = function() {\n return this;\n};\n\n/**\n * Initialize a data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.initialize = function() {\n\n // Append a container group element to house the main data layer group element and the clip path\n this.svg.container = this.parent.svg.group.append('g')\n .attr('class', 'lz-data_layer-container')\n .attr('id', this.getBaseId() + '.data_layer_container');\n\n // Append clip path to the container element\n this.svg.clipRect = this.svg.container.append('clipPath')\n .attr('id', this.getBaseId() + '.clip')\n .append('rect');\n\n // Append svg group for rendering all data layer elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g')\n .attr('id', this.getBaseId() + '.data_layer')\n .attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n\n return this;\n\n};\n\n/**\n * Move a data layer up relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.moveUp = function() {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index + 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n};\n\n/**\n * Move a data layer down relative to others by z-index\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.moveDown = function() {\n if (this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1]) {\n this.parent.data_layer_ids_by_z_index[this.layout.z_index] = this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1];\n this.parent.data_layer_ids_by_z_index[this.layout.z_index - 1] = this.id;\n this.parent.resortDataLayers();\n }\n return this;\n};\n\n/**\n * Apply scaling functions to an element or parameter as needed, based on its layout and the element's data\n * If the layout parameter is already a primitive type, simply return the value as given\n * @param {Array|Number|String|Object} layout\n * @param {*} data The value to be used with the filter\n * @returns {*} The transformed value\n */\nLocusZoom.DataLayer.prototype.resolveScalableParameter = function(layout, data) {\n var ret = null;\n if (Array.isArray(layout)) {\n var idx = 0;\n while (ret === null && idx < layout.length) {\n ret = this.resolveScalableParameter(layout[idx], data);\n idx++;\n }\n } else {\n switch (typeof layout) {\n case 'number':\n case 'string':\n ret = layout;\n break;\n case 'object':\n if (layout.scale_function) {\n if(layout.field) {\n var f = new LocusZoom.Data.Field(layout.field);\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, f.resolve(data));\n } else {\n ret = LocusZoom.ScaleFunctions.get(layout.scale_function, layout.parameters || {}, data);\n }\n }\n break;\n }\n }\n return ret;\n};\n\n\n/**\n * Implementation hook for fetching the min and max values of available data. Used to determine axis range, if no other\n * explicit axis settings override. Useful for data layers where the data extent depends on more than one field.\n * (eg confidence intervals in a forest plot)\n * @param data\n * @param axis_config The configuration object for the specified axis.\n * @returns {Array} [min, max] without any padding applied\n * @private\n */\nLocusZoom.DataLayer.prototype._getDataExtent = function(data, axis_config) {\n data = data || this.data;\n // By default this depends only on a single field.\n return d3.extent(data, function (d) {\n var f = new LocusZoom.Data.Field(axis_config.field);\n return +f.resolve(d);\n });\n};\n\n/**\n * Generate dimension extent function based on layout parameters\n * @param {('x'|'y')} dimension\n */\nLocusZoom.DataLayer.prototype.getAxisExtent = function(dimension) {\n\n if (['x', 'y'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier passed to LocusZoom.DataLayer.getAxisExtent()');\n }\n\n var axis_name = dimension + '_axis';\n var axis_layout = this.layout[axis_name];\n\n // If a floor AND a ceiling are explicitly defined then just return that extent and be done\n if (!isNaN(axis_layout.floor) && !isNaN(axis_layout.ceiling)) {\n return [+axis_layout.floor, +axis_layout.ceiling];\n }\n\n // If a field is defined for the axis and the data layer has data then generate the extent from the data set\n var data_extent = [];\n if (axis_layout.field && this.data) {\n if (!this.data.length) {\n // If data has been fetched (but no points in region), enforce the min_extent (with no buffers,\n // because we don't need padding around an empty screen)\n data_extent = axis_layout.min_extent || [];\n return data_extent;\n } else {\n data_extent = this._getDataExtent(this.data, axis_layout);\n\n // Apply upper/lower buffers, if applicable\n var original_extent_span = data_extent[1] - data_extent[0];\n if (!isNaN(axis_layout.lower_buffer)) {\n data_extent[0] -= original_extent_span * axis_layout.lower_buffer;\n }\n if (!isNaN(axis_layout.upper_buffer)) {\n data_extent[1] += original_extent_span * axis_layout.upper_buffer;\n }\n\n if (typeof axis_layout.min_extent == 'object') {\n // The data should span at least the range specified by min_extent, an array with [low, high]\n var range_min = axis_layout.min_extent[0];\n var range_max = axis_layout.min_extent[1];\n if (!isNaN(range_min) && !isNaN(range_max)) {\n data_extent[0] = Math.min(data_extent[0], range_min);\n }\n if (!isNaN(range_max)) {\n data_extent[1] = Math.max(data_extent[1], range_max);\n }\n }\n // If specified, floor and ceiling will override the actual data range\n return [\n isNaN(axis_layout.floor) ? data_extent[0] : axis_layout.floor,\n isNaN(axis_layout.ceiling) ? data_extent[1] : axis_layout.ceiling\n ];\n }\n }\n\n // If this is for the x axis and no extent could be generated yet but state has a defined start and end\n // then default to using the state-defined region as the extent\n if (dimension === 'x' && !isNaN(this.state.start) && !isNaN(this.state.end)) {\n return [this.state.start, this.state.end];\n }\n\n // No conditions met for generating a valid extent, return an empty array\n return [];\n\n};\n\n/**\n * Allow this data layer to tell the panel what axis ticks it thinks it will require. The panel may choose whether\n * to use some, all, or none of these when rendering, either alone or in conjunction with other data layers.\n *\n * This method is a stub and should be overridden in data layers that need to specify custom behavior.\n *\n * @param {('x'|'y1'|'y2')} dimension\n * @param {Object} [config] Additional parameters for the panel to specify how it wants ticks to be drawn. The names\n * and meanings of these parameters may vary between different data layers.\n * @returns {Object[]}\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\nLocusZoom.DataLayer.prototype.getTicks = function (dimension, config) {\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier at layer level' + dimension);\n }\n return [];\n};\n\n/**\n * Generate a tool tip for a given element\n * @param {String|Object} data Data for the element associated with the tooltip\n */\nLocusZoom.DataLayer.prototype.createTooltip = function(data) {\n if (typeof this.layout.tooltip != 'object') {\n throw new Error('DataLayer [' + this.id + '] layout does not define a tooltip');\n }\n var id = this.getElementId(data);\n if (this.tooltips[id]) {\n this.positionTooltip(id);\n return;\n }\n this.tooltips[id] = {\n data: data,\n arrow: null,\n selector: d3.select(this.parent_plot.svg.node().parentNode).append('div')\n .attr('class', 'lz-data_layer-tooltip')\n .attr('id', id + '-tooltip')\n };\n this.state[this.state_id]['has_tooltip'].push(id);\n this.updateTooltip(data);\n return this;\n};\n\n/**\n * Update a tool tip (generate its inner HTML)\n * @param {String|Object} d The element associated with the tooltip\n * @param {String} [id] An identifier to the tooltip\n */\nLocusZoom.DataLayer.prototype.updateTooltip = function(d, id) {\n if (typeof id == 'undefined') { id = this.getElementId(d); }\n // Empty the tooltip of all HTML (including its arrow!)\n this.tooltips[id].selector.html('');\n this.tooltips[id].arrow = null;\n // Set the new HTML\n if (this.layout.tooltip.html) {\n this.tooltips[id].selector.html(LocusZoom.parseFields(d, this.layout.tooltip.html));\n }\n // If the layout allows tool tips on this data layer to be closable then add the close button\n // and add padding to the tooltip to accommodate it\n if (this.layout.tooltip.closable) {\n this.tooltips[id].selector.insert('button', ':first-child')\n .attr('class', 'lz-tooltip-close-button')\n .attr('title', 'Close')\n .text('×')\n .on('click', function() {\n this.destroyTooltip(id);\n }.bind(this));\n }\n // Apply data directly to the tool tip for easier retrieval by custom UI elements inside the tool tip\n this.tooltips[id].selector.data([d]);\n // Reposition and draw a new arrow\n this.positionTooltip(id);\n return this;\n};\n\n/**\n * Destroy tool tip - remove the tool tip element from the DOM and delete the tool tip's record on the data layer\n * @param {String|Object} element_or_id The element (or id) associated with the tooltip\n * @param {boolean} [temporary=false] Whether this is temporary (not to be tracked in state). Differentiates\n * \"recreate tooltips on re-render\" (which is temporary) from \"user has closed this tooltip\" (permanent)\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.destroyTooltip = function(element_or_id, temporary) {\n var id;\n if (typeof element_or_id == 'string') {\n id = element_or_id;\n } else {\n id = this.getElementId(element_or_id);\n }\n if (this.tooltips[id]) {\n if (typeof this.tooltips[id].selector == 'object') {\n this.tooltips[id].selector.remove();\n }\n delete this.tooltips[id];\n }\n // When a tooltip is removed, also remove the reference from the state\n if (!temporary) {\n var state = this.state[this.state_id]['has_tooltip'];\n var label_mark_position = state.indexOf(id);\n state.splice(label_mark_position, 1);\n }\n return this;\n};\n\n/**\n * Loop through and destroy all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.destroyAllTooltips = function() {\n for (var id in this.tooltips) {\n this.destroyTooltip(id, true);\n }\n return this;\n};\n\n//\n/**\n * Position tool tip - naïve function to place a tool tip to the lower right of the current mouse element\n * Most data layers reimplement this method to position tool tips specifically for the data they display\n * @param {String} id The identifier of the tooltip to position\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n // Position the div itself\n this.tooltips[id].selector\n .style('left', (d3.event.pageX) + 'px')\n .style('top', (d3.event.pageY) + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!this.tooltips[id].arrow) {\n this.tooltips[id].arrow = this.tooltips[id].selector.append('div')\n .style('position', 'absolute')\n .attr('class', 'lz-data_layer-tooltip-arrow_top_left');\n }\n this.tooltips[id].arrow\n .style('left', '-1px')\n .style('top', '-1px');\n return this;\n};\n\n/**\n * Loop through and position all tool tips on this data layer\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.positionAllTooltips = function() {\n for (var id in this.tooltips) {\n this.positionTooltip(id);\n }\n return this;\n};\n\n/**\n * Show or hide a tool tip by ID depending on directives in the layout and state values relative to the ID\n * @param {String|Object} element The element associated with the tooltip\n * @param {boolean} first_time Because panels can re-render, the rules for showing a tooltip\n * depend on whether this is the first time a status change affecting display has been applied.\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.showOrHideTooltip = function(element, first_time) {\n if (typeof this.layout.tooltip != 'object') { return; }\n var id = this.getElementId(element);\n\n /**\n * Apply rules and decide whether to show or hide the tooltip\n * @param {Object} statuses All statuses that apply to an element\n * @param {String[]|object} directive A layout directive object\n * @param operator\n * @returns {null|bool}\n */\n var resolveStatus = function(statuses, directive, operator) {\n var status = null;\n if (typeof statuses != 'object' || statuses === null) { return null; }\n if (Array.isArray(directive)) {\n // This happens when the function is called on the inner part of the directive\n operator = operator || 'and';\n if (directive.length === 1) {\n status = statuses[directive[0]];\n } else {\n status = directive.reduce(function(previousValue, currentValue) {\n if (operator === 'and') {\n return statuses[previousValue] && statuses[currentValue];\n } else if (operator === 'or') {\n return statuses[previousValue] || statuses[currentValue];\n }\n return null;\n });\n }\n } else if (typeof directive == 'object') {\n var sub_status;\n for (var sub_operator in directive) {\n sub_status = resolveStatus(statuses, directive[sub_operator], sub_operator);\n if (status === null) {\n status = sub_status;\n } else if (operator === 'and') {\n status = status && sub_status;\n } else if (operator === 'or') {\n status = status || sub_status;\n }\n }\n } else {\n return false;\n }\n return status;\n };\n\n var show_directive = {};\n if (typeof this.layout.tooltip.show == 'string') {\n show_directive = { and: [ this.layout.tooltip.show ] };\n } else if (typeof this.layout.tooltip.show == 'object') {\n show_directive = this.layout.tooltip.show;\n }\n\n var hide_directive = {};\n if (typeof this.layout.tooltip.hide == 'string') {\n hide_directive = { and: [ this.layout.tooltip.hide ] };\n } else if (typeof this.layout.tooltip.hide == 'object') {\n hide_directive = this.layout.tooltip.hide;\n }\n\n // Find all the statuses that apply to just this single element\n var layer_state = this.state[this.state_id];\n var statuses = {}; // {status_name: bool}\n LocusZoom.DataLayer.Statuses.adjectives.forEach(function(status) {\n var antistatus = 'un' + status;\n statuses[status] = (layer_state[status].indexOf(id) !== -1);\n statuses[antistatus] = !statuses[status];\n });\n\n // Decide whether to show/hide the tooltip based solely on the underlying element\n var show_resolved = resolveStatus(statuses, show_directive);\n var hide_resolved = resolveStatus(statuses, hide_directive);\n\n // Most of the tooltip display logic depends on behavior layouts: was point (un)selected, (un)highlighted, etc.\n // But sometimes, a point is selected, and the user then closes the tooltip. If the panel is re-rendered for\n // some outside reason (like state change), we must track this in the create/destroy events as tooltip state.\n var has_tooltip = (layer_state['has_tooltip'].indexOf(id) !== -1);\n var tooltip_was_closed = first_time ? false : !has_tooltip;\n if (show_resolved && !tooltip_was_closed && !hide_resolved) {\n this.createTooltip(element);\n } else {\n this.destroyTooltip(element);\n }\n\n return this;\n};\n\n/**\n * Find the elements (or indices) that match any of a set of provided filters\n * @protected\n * @param {Array[]} filters A list of filter entries: [field, value] (for equivalence testing) or\n * [field, operator, value] for other operators\n * @param {('indexes'|'elements')} [return_type='indexes'] Specify whether to return either the indices of the matching\n * elements, or references to the elements themselves\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filter = function(filters, return_type) {\n if (typeof return_type == 'undefined' || ['indexes','elements'].indexOf(return_type) === -1) {\n return_type = 'indexes';\n }\n if (!Array.isArray(filters)) { return []; }\n var test = function(element, filter) {\n var operators = {\n '=': function(a,b) { return a === b; },\n // eslint-disable-next-line eqeqeq\n '!=': function(a,b) { return a != b; }, // For absence of a value, deliberately allow weak comparisons (eg undefined/null)\n '<': function(a,b) { return a < b; },\n '<=': function(a,b) { return a <= b; },\n '>': function(a,b) { return a > b; },\n '>=': function(a,b) { return a >= b; },\n '%': function(a,b) { return a % b; }\n };\n if (!Array.isArray(filter)) { return false; }\n if (filter.length === 2) {\n return element[filter[0]] === filter[1];\n } else if (filter.length === 3 && operators[filter[1]]) {\n return operators[filter[1]](element[filter[0]], filter[2]);\n } else {\n return false;\n }\n };\n var matches = [];\n this.data.forEach(function(element, idx) {\n var match = true;\n filters.forEach(function(filter) {\n if (!test(element, filter)) { match = false; }\n });\n if (match) { matches.push(return_type === 'indexes' ? idx : element); }\n });\n return matches;\n};\n\n/**\n * @param filters\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filterIndexes = function(filters) { return this.filter(filters, 'indexes'); };\n/**\n * @param filters\n * @returns {Array}\n */\nLocusZoom.DataLayer.prototype.filterElements = function(filters) { return this.filter(filters, 'elements'); };\n\nLocusZoom.DataLayer.Statuses.verbs.forEach(function(verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset a single element's status\n // TODO: Improve documentation for dynamically generated methods/properties\n LocusZoom.DataLayer.prototype[verb + 'Element'] = function(element, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n this.setElementStatus(adjective, element, true, exclusive);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'Element'] = function(element, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n this.setElementStatus(adjective, element, false, exclusive);\n return this;\n };\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.DataLayer.prototype[verb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.DataLayer.prototype[antiverb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.DataLayer.prototype[verb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.DataLayer.prototype[antiverb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n});\n\n/**\n * Toggle a status (e.g. highlighted, selected, identified) on an element\n * @param {String} status The name of a recognized status to be added/removed on an appropriate element\n * @param {String|Object} element The data bound to the element of interest\n * @param {Boolean} active True to add the status (and associated CSS styles); false to remove it\n * @param {Boolean} exclusive Whether to only allow a state for a single element at a time\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setElementStatus = function(status, element, active, exclusive) {\n if (status === 'has_tooltip') {\n // This is a special adjective that exists solely to track tooltip state. It has no CSS and never gets set\n // directly. It is invisible to the official enums.\n return this;\n }\n\n // Sanity checks\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatus()');\n }\n if (typeof element == 'undefined') {\n throw new Error('Invalid element passed to DataLayer.setElementStatus()');\n }\n if (typeof active == 'undefined') {\n active = true;\n }\n\n // Get an ID for the element or return having changed nothing\n try {\n var element_id = this.getElementId(element);\n } catch (get_element_id_error) {\n return this;\n }\n\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !active);\n }\n\n // Set/unset the proper status class on the appropriate DOM element(s)\n d3.select('#' + element_id).classed('lz-data_layer-' + this.layout.type + '-' + status, active);\n var element_status_node_id = this.getElementStatusNodeId(element);\n if (element_status_node_id !== null) {\n d3.select('#' + element_status_node_id).classed('lz-data_layer-' + this.layout.type + '-statusnode-' + status, active);\n }\n\n // Track element ID in the proper status state array\n var element_status_idx = this.state[this.state_id][status].indexOf(element_id);\n var added_status = (element_status_idx === -1); // On a re-render, existing statuses will be reapplied.\n if (active && added_status) {\n this.state[this.state_id][status].push(element_id);\n }\n if (!active && !added_status) {\n this.state[this.state_id][status].splice(element_status_idx, 1);\n }\n\n // Trigger tool tip show/hide logic\n this.showOrHideTooltip(element, added_status);\n\n // Trigger layout changed event hook\n if (added_status) {\n this.parent.emit('layout_changed', true);\n }\n\n var is_selected = (status === 'selected');\n if (is_selected && (added_status || !active)) {\n // Notify parents that an element has changed selection status (either active, or inactive)\n this.parent.emit('element_selection', { element: element, active: active }, true);\n }\n\n var value_to_broadcast = (this.layout.match && this.layout.match.send);\n if (is_selected && value_to_broadcast && (added_status || !active)) {\n this.parent.emit(\n 'match_requested',\n { value: element[value_to_broadcast], active: active },\n true\n );\n }\n return this;\n};\n\n/**\n * Toggle a status on elements in the data layer based on a set of filters\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setElementStatusByFilters = function(status, toggle, filters, exclusive) {\n\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setElementStatusByFilters()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; } else { toggle = !!toggle; }\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n if (!Array.isArray(filters)) { filters = []; }\n\n // Enforce exclusivity (force all elements to have the opposite of toggle first)\n if (exclusive) {\n this.setAllElementStatus(status, !toggle);\n }\n\n // Apply statuses\n this.filterElements(filters).forEach(function(element) {\n this.setElementStatus(status, element, toggle);\n }.bind(this));\n\n return this;\n};\n\n/**\n * Toggle a status on all elements in the data layer\n * @param {String} status\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.setAllElementStatus = function(status, toggle) {\n\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; }\n\n // Apply statuses\n if (toggle) {\n this.data.forEach(function(element) {\n this.setElementStatus(status, element, true);\n }.bind(this));\n } else {\n var status_ids = this.state[this.state_id][status].slice();\n status_ids.forEach(function(id) {\n var element = this.getElementById(id);\n if (typeof element == 'object' && element !== null) {\n this.setElementStatus(status, element, false);\n }\n }.bind(this));\n this.state[this.state_id][status] = [];\n }\n\n // Update global status flag\n this.global_statuses[status] = toggle;\n\n return this;\n};\n\n/**\n * Apply all layout-defined behaviors (DOM event handlers) to a selection of elements\n * @param {d3.selection} selection\n */\nLocusZoom.DataLayer.prototype.applyBehaviors = function(selection) {\n if (typeof this.layout.behaviors != 'object') { return; }\n Object.keys(this.layout.behaviors).forEach(function(directive) {\n var event_match = /(click|mouseover|mouseout)/.exec(directive);\n if (!event_match) { return; }\n selection.on(event_match[0] + '.' + directive, this.executeBehaviors(directive, this.layout.behaviors[directive]));\n }.bind(this));\n};\n\n/**\n * Generate a function that executes an arbitrary list of behaviors on an element during an event\n * @param {String} directive The name of the event, as described in layout.behaviors for this datalayer\n * @param {Object} behaviors An object describing the behavior to attach to this single element\n * @param {string} behaviors.action The name of the action that would trigger this behavior (eg click, mouseover, etc)\n * @param {string} behaviors.status What status to apply to the element when this behavior is triggered (highlighted,\n * selected, etc)\n * @param {string} [behaviors.exclusive] Whether triggering the event for this element should unset the relevant status\n * for all other elements. Useful for, eg, click events that exclusively highlight one thing.\n * @returns {function(this:LocusZoom.DataLayer)} Return a function that handles the event in context with the behavior\n * and the element- can be attached as an event listener\n */\nLocusZoom.DataLayer.prototype.executeBehaviors = function(directive, behaviors) {\n\n // Determine the required state of control and shift keys during the event\n var requiredKeyStates = {\n 'ctrl': (directive.indexOf('ctrl') !== -1),\n 'shift': (directive.indexOf('shift') !== -1)\n };\n\n return function(element) {\n\n // Do nothing if the required control and shift key presses (or lack thereof) doesn't match the event\n if (requiredKeyStates.ctrl !== !!d3.event.ctrlKey || requiredKeyStates.shift !== !!d3.event.shiftKey) { return; }\n\n // Loop through behaviors making each one go in succession\n behaviors.forEach(function(behavior) {\n\n // Route first by the action, if defined\n if (typeof behavior != 'object' || behavior === null) { return; }\n\n switch (behavior.action) {\n\n // Set a status (set to true regardless of current status, optionally with exclusivity)\n case 'set':\n this.setElementStatus(behavior.status, element, true, behavior.exclusive);\n break;\n\n // Unset a status (set to false regardless of current status, optionally with exclusivity)\n case 'unset':\n this.setElementStatus(behavior.status, element, false, behavior.exclusive);\n break;\n\n // Toggle a status\n case 'toggle':\n var current_status_boolean = (this.state[this.state_id][behavior.status].indexOf(this.getElementId(element)) !== -1);\n var exclusive = behavior.exclusive && !current_status_boolean;\n this.setElementStatus(behavior.status, element, !current_status_boolean, exclusive);\n break;\n\n // Link to a dynamic URL\n case 'link':\n if (typeof behavior.href == 'string') {\n var url = LocusZoom.parseFields(element, behavior.href);\n if (typeof behavior.target == 'string') {\n window.open(url, behavior.target);\n } else {\n window.location.href = url;\n }\n }\n break;\n\n // Action not defined, just return\n default:\n break;\n\n }\n\n return;\n\n }.bind(this));\n\n }.bind(this);\n\n};\n\n/**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\nLocusZoom.DataLayer.prototype.getPageOrigin = function() {\n var panel_origin = this.parent.getPageOrigin();\n return {\n x: panel_origin.x + this.parent.layout.margin.left,\n y: panel_origin.y + this.parent.layout.margin.top\n };\n};\n\n/**\n * Get a data layer's current underlying data in a standard format (e.g. JSON or CSV)\n * @param {('csv'|'tsv'|'json')} format How to export the data\n * @returns {*}\n */\nLocusZoom.DataLayer.prototype.exportData = function(format) {\n var default_format = 'json';\n format = format || default_format;\n format = (typeof format == 'string' ? format.toLowerCase() : default_format);\n if (['json','csv','tsv'].indexOf(format) === -1) { format = default_format; }\n var ret;\n switch (format) {\n case 'json':\n try {\n ret = JSON.stringify(this.data);\n } catch (e) {\n ret = null;\n console.warn('Unable to export JSON data from data layer: ' + this.getBaseId());\n console.error(e);\n }\n break;\n case 'tsv':\n case 'csv':\n try {\n var jsonified = JSON.parse(JSON.stringify(this.data));\n if (typeof jsonified != 'object') {\n ret = jsonified.toString();\n } else if (!Array.isArray(jsonified)) {\n ret = 'Object';\n } else {\n var delimiter = (format === 'tsv') ? '\\t' : ',';\n var header = this.layout.fields.map(function(header) {\n return JSON.stringify(header);\n }).join(delimiter) + '\\n';\n ret = header + jsonified.map(function(record) {\n return this.layout.fields.map(function(field) {\n if (typeof record[field] == 'undefined') {\n return JSON.stringify(null);\n } else if (typeof record[field] == 'object' && record[field] !== null) {\n return Array.isArray(record[field]) ? '\"[Array(' + record[field].length + ')]\"' : '\"[Object]\"';\n } else {\n return JSON.stringify(record[field]);\n }\n }).join(delimiter);\n }.bind(this)).join('\\n');\n }\n } catch (e) {\n ret = null;\n console.error('Unable to export CSV data from data layer: ' + this.getBaseId() + ';', e);\n }\n break;\n }\n return ret;\n};\n\n/**\n * Position the datalayer and all tooltips\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.DataLayer.prototype.draw = function() {\n this.svg.container.attr('transform', 'translate(' + this.parent.layout.cliparea.origin.x + ',' + this.parent.layout.cliparea.origin.y + ')');\n this.svg.clipRect\n .attr('width', this.parent.layout.cliparea.width)\n .attr('height', this.parent.layout.cliparea.height);\n this.positionAllTooltips();\n return this;\n};\n\n\n/**\n * Re-Map a data layer to reflect changes in the state of a plot (such as viewing region/ chromosome range)\n * @return {Promise}\n */\nLocusZoom.DataLayer.prototype.reMap = function() {\n this.destroyAllTooltips(); // hack - only non-visible tooltips should be destroyed\n // and then recreated if returning to visibility\n\n // Fetch new data. Datalayers are only given access to the final consolidated data from the chain (not headers or raw payloads)\n var promise = this.parent_plot.lzd.getData(this.state, this.layout.fields);\n promise.then(function(new_data) {\n this.data = new_data.body;\n this.applyDataMethods();\n this.initialized = true;\n }.bind(this));\n\n return promise;\n};\n\n\n/**\n * The central registry of known data layer definitions (which may be stored in separate files due to length)\n * @namespace\n */\nLocusZoom.DataLayers = (function() {\n var obj = {};\n var datalayers = {};\n /**\n * @name LocusZoom.DataLayers.get\n * @param {String} name The name of the datalayer\n * @param {Object} layout The configuration object for this data layer\n * @param {LocusZoom.DataLayer|LocusZoom.Panel} parent Where this layout is used\n * @returns {LocusZoom.DataLayer}\n */\n obj.get = function(name, layout, parent) {\n if (!name) {\n return null;\n } else if (datalayers[name]) {\n if (typeof layout != 'object') {\n throw new Error('invalid layout argument for data layer [' + name + ']');\n } else {\n return new datalayers[name](layout, parent);\n }\n } else {\n throw new Error('data layer [' + name + '] not found');\n }\n };\n\n /**\n * @name LocusZoom.DataLayers.set\n * @protected\n * @param {String} name\n * @param {Function} datalayer Constructor for the datalayer\n */\n obj.set = function(name, datalayer) {\n if (datalayer) {\n if (typeof datalayer != 'function') {\n throw new Error('unable to set data layer [' + name + '], argument provided is not a function');\n } else {\n datalayers[name] = datalayer;\n datalayers[name].prototype = new LocusZoom.DataLayer();\n }\n } else {\n delete datalayers[name];\n }\n };\n\n /**\n * Add a new type of datalayer to the registry of known layer types\n * @name LocusZoom.DataLayers.add\n * @param {String} name The name of the data layer to register\n * @param {Function} datalayer\n */\n obj.add = function(name, datalayer) {\n if (datalayers[name]) {\n throw new Error('data layer already exists with name: ' + name);\n } else {\n obj.set(name, datalayer);\n }\n };\n\n /**\n * Register a new datalayer that inherits and extends basic behaviors from a known datalayer\n * @param {String} parent_name The name of the parent data layer whose behavior is to be extended\n * @param {String} name The name of the new datalayer to register\n * @param {Object} [overrides] Object of properties and methods to combine with the prototype of the parent datalayer\n * @returns {Function} The constructor for the new child class\n */\n obj.extend = function(parent_name, name, overrides) {\n // TODO: Consider exposing additional constructor argument, if there is a use case for very granular extension\n overrides = overrides || {};\n\n var parent = datalayers[parent_name];\n if (!parent) {\n throw new Error('Attempted to subclass an unknown or unregistered datalayer type');\n }\n if (typeof overrides !== 'object') {\n throw new Error('Must specify an object of properties and methods');\n }\n var child = LocusZoom.subclass(parent, overrides);\n // Bypass .set() because we want a layer of inheritance below `DataLayer`\n datalayers[name] = child;\n return child;\n };\n\n /**\n * List the names of all known datalayers\n * @name LocusZoom.DataLayers.list\n * @returns {String[]}\n */\n obj.list = function() {\n return Object.keys(datalayers);\n };\n\n return obj;\n})();\n","/* global LocusZoom */\n'use strict';\n\nvar LZ_SIG_THRESHOLD_LOGP = 7.301; // -log10(.05/1e6)\n\n/**\n * Manage known layouts for all parts of the LocusZoom plot\n *\n * This registry allows for layouts to be reused and customized many times on a page, using a common base pattern.\n * It handles the work of ensuring that each new instance of the layout has no shared state with other copies.\n *\n * @class\n */\nLocusZoom.Layouts = (function () {\n var obj = {};\n var layouts = {\n 'plot': {},\n 'panel': {},\n 'data_layer': {},\n 'dashboard': {},\n 'dashboard_components': {},\n 'tooltip': {}\n };\n\n /**\n * Generate a layout configuration object\n * @param {('plot'|'panel'|'data_layer'|'dashboard'|'tooltip')} type The type of layout to retrieve\n * @param {string} name Identifier of the predefined layout within the specified type\n * @param {object} [modifications] Custom properties that override default settings for this layout\n * @returns {object} A JSON-serializable object representation\n */\n obj.get = function (type, name, modifications) {\n if (typeof type != 'string' || typeof name != 'string') {\n throw new Error('invalid arguments passed to LocusZoom.Layouts.get, requires string (layout type) and string (layout name)');\n } else if (layouts[type][name]) {\n // Get the base layout\n var layout = LocusZoom.Layouts.merge(modifications || {}, layouts[type][name]);\n // If \"unnamespaced\" is true then strike that from the layout and return the layout without namespacing\n if (layout.unnamespaced) {\n delete layout.unnamespaced;\n return JSON.parse(JSON.stringify(layout));\n }\n // Determine the default namespace for namespaced values\n var default_namespace = '';\n if (typeof layout.namespace == 'string') {\n default_namespace = layout.namespace;\n } else if (typeof layout.namespace == 'object' && Object.keys(layout.namespace).length) {\n if (typeof layout.namespace.default != 'undefined') {\n default_namespace = layout.namespace.default;\n } else {\n default_namespace = layout.namespace[Object.keys(layout.namespace)[0]].toString();\n }\n }\n default_namespace += default_namespace.length ? ':' : '';\n // Apply namespaces to layout, recursively\n var applyNamespaces = function (element, namespace) {\n if (namespace) {\n if (typeof namespace == 'string') {\n namespace = { default: namespace };\n }\n } else {\n namespace = { default: '' };\n }\n if (typeof element == 'string') {\n var re = /\\{\\{namespace(\\[[A-Za-z_0-9]+\\]|)\\}\\}/g;\n var match, base, key, resolved_namespace;\n var replace = [];\n while ((match = re.exec(element)) !== null) {\n base = match[0];\n key = match[1].length ? match[1].replace(/(\\[|\\])/g, '') : null;\n resolved_namespace = default_namespace;\n if (namespace != null && typeof namespace == 'object' && typeof namespace[key] != 'undefined') {\n resolved_namespace = namespace[key] + (namespace[key].length ? ':' : '');\n }\n replace.push({ base: base, namespace: resolved_namespace });\n }\n for (var r in replace) {\n element = element.replace(replace[r].base, replace[r].namespace);\n }\n } else if (typeof element == 'object' && element != null) {\n if (typeof element.namespace != 'undefined') {\n var merge_namespace = (typeof element.namespace == 'string') ? { default: element.namespace } : element.namespace;\n namespace = LocusZoom.Layouts.merge(namespace, merge_namespace);\n }\n var namespaced_element, namespaced_property;\n for (var property in element) {\n if (property === 'namespace') {\n continue;\n }\n namespaced_element = applyNamespaces(element[property], namespace);\n namespaced_property = applyNamespaces(property, namespace);\n if (property !== namespaced_property) {\n delete element[property];\n }\n element[namespaced_property] = namespaced_element;\n }\n }\n return element;\n };\n layout = applyNamespaces(layout, layout.namespace);\n // Return the layout as valid JSON only\n return JSON.parse(JSON.stringify(layout));\n } else {\n throw new Error('layout type [' + type + '] name [' + name + '] not found');\n }\n };\n\n /** @private */\n obj.set = function (type, name, layout) {\n if (typeof type != 'string' || typeof name != 'string' || typeof layout != 'object') {\n throw new Error('unable to set new layout; bad arguments passed to set()');\n }\n if (!layouts[type]) {\n layouts[type] = {};\n }\n if (layout) {\n return (layouts[type][name] = JSON.parse(JSON.stringify(layout)));\n } else {\n delete layouts[type][name];\n return null;\n }\n };\n\n /**\n * Register a new layout definition by name.\n *\n * @param {string} type The type of layout to add. Usually, this will be one of the predefined LocusZoom types,\n * but if you pass a different name, this method will automatically create the new `type` bucket\n * @param {string} name The identifier of the newly added layout\n * @param {object} [layout] A JSON-serializable object containing configuration properties for this layout\n * @returns The JSON representation of the newly created layout\n */\n obj.add = function (type, name, layout) {\n return obj.set(type, name, layout);\n };\n\n /**\n * List all registered layouts\n * @param [type] Optionally narrow the list to only layouts of a specific type; else return all known layouts\n * @returns {*}\n */\n obj.list = function (type) {\n if (!layouts[type]) {\n var list = {};\n Object.keys(layouts).forEach(function (type) {\n list[type] = Object.keys(layouts[type]);\n });\n return list;\n } else {\n return Object.keys(layouts[type]);\n }\n };\n\n /**\n * A helper method used for merging two objects. If a key is present in both, takes the value from the first object\n * Values from `default_layout` will be cleanly copied over, ensuring no references or shared state.\n *\n * Frequently used for preparing custom layouts. Both objects should be JSON-serializable.\n *\n * @param {object} custom_layout An object containing configuration parameters that override or add to defaults\n * @param {object} default_layout An object containing default settings.\n * @returns {object} The custom layout is modified in place and also returned from this method.\n */\n obj.merge = function (custom_layout, default_layout) {\n if (typeof custom_layout !== 'object' || typeof default_layout !== 'object') {\n throw new Error('LocusZoom.Layouts.merge only accepts two layout objects; ' + (typeof custom_layout) + ', ' + (typeof default_layout) + ' given');\n }\n for (var property in default_layout) {\n if (!default_layout.hasOwnProperty(property)) {\n continue;\n }\n // Get types for comparison. Treat nulls in the custom layout as undefined for simplicity.\n // (javascript treats nulls as \"object\" when we just want to overwrite them as if they're undefined)\n // Also separate arrays from objects as a discrete type.\n var custom_type = custom_layout[property] === null ? 'undefined' : typeof custom_layout[property];\n var default_type = typeof default_layout[property];\n if (custom_type === 'object' && Array.isArray(custom_layout[property])) {\n custom_type = 'array';\n }\n if (default_type === 'object' && Array.isArray(default_layout[property])) {\n default_type = 'array';\n }\n // Unsupported property types: throw an exception\n if (custom_type === 'function' || default_type === 'function') {\n throw new Error('LocusZoom.Layouts.merge encountered an unsupported property type');\n }\n // Undefined custom value: pull the default value\n if (custom_type === 'undefined') {\n custom_layout[property] = JSON.parse(JSON.stringify(default_layout[property]));\n continue;\n }\n // Both values are objects: merge recursively\n if (custom_type === 'object' && default_type === 'object') {\n custom_layout[property] = LocusZoom.Layouts.merge(custom_layout[property], default_layout[property]);\n continue;\n }\n }\n return custom_layout;\n };\n\n return obj;\n})();\n\n\n/**\n * Tooltip Layouts\n * @namespace LocusZoom.Layouts.tooltips\n */\n\nLocusZoom.Layouts.add('tooltip', 'standard_association', {\n namespace: { 'assoc': 'assoc' },\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[assoc]}}variant|htmlescape}}
'\n + 'P Value: {{{{namespace[assoc]}}log_pvalue|logtoscinotation|htmlescape}}
'\n + 'Ref. Allele: {{{{namespace[assoc]}}ref_allele|htmlescape}}
'\n + 'Make LD Reference
'\n});\n\nLocusZoom.Layouts.add('tooltip', 'covariates_model_association', function () {\n var covariates_model_association = LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true });\n covariates_model_association.html += 'Condition on Variant
';\n return covariates_model_association;\n}());\n\nLocusZoom.Layouts.add('tooltip', 'standard_genes', {\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '

{{gene_name|htmlescape}}

'\n + 'Gene ID: {{gene_id|htmlescape}}
'\n + 'Transcript ID: {{transcript_id|htmlescape}}
'\n + '{{#if pLI}}'\n + ''\n + ''\n + ''\n + ''\n + '
ConstraintExpected variantsObserved variantsConst. Metric
Synonymous{{exp_syn}}{{obs_syn}}z = {{syn_z}}
o/e = {{oe_syn}} ({{oe_syn_lower}} - {{oe_syn_upper}})
Missense{{exp_mis}}{{obs_mis}}z = {{mis_z}}
o/e = {{oe_mis}} ({{oe_mis_lower}} - {{oe_mis_upper}})
pLoF{{exp_lof}}{{obs_lof}}pLI = {{pLI}}
o/e = {{oe_lof}} ({{oe_lof_lower}} - {{oe_lof_upper}})

{{/if}}'\n + 'More data on gnomAD'\n});\n\nLocusZoom.Layouts.add('tooltip', 'standard_intervals', {\n namespace: { 'intervals': 'intervals' },\n closable: false,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[intervals]}}state_name|htmlescape}}
{{{{namespace[intervals]}}start|htmlescape}}-{{{{namespace[intervals]}}end|htmlescape}}'\n});\n\nLocusZoom.Layouts.add('tooltip', 'catalog_variant', {\n namespace: { 'assoc': 'assoc', 'catalog': 'catalog' },\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: '{{{{namespace[catalog]}}variant|htmlescape}}
'\n + 'Catalog entries: {{n_catalog_matches|htmlescape}}
'\n + 'Top Trait: {{{{namespace[catalog]}}trait|htmlescape}}
'\n + 'Top P Value: {{{{namespace[catalog]}}log_pvalue|logtoscinotation}}
'\n // User note: if a different catalog is used, the tooltip will need to be replaced with a different link URL\n + 'More: GWAS catalog / dbSNP'\n});\n\n/**\n * Data Layer Layouts: represent specific information from a data source\n * @namespace Layouts.data_layer\n */\n\nLocusZoom.Layouts.add('data_layer', 'significance', {\n id: 'significance',\n type: 'orthogonal_line',\n orientation: 'horizontal',\n offset: LZ_SIG_THRESHOLD_LOGP\n});\n\nLocusZoom.Layouts.add('data_layer', 'recomb_rate', {\n namespace: { 'recomb': 'recomb' },\n id: 'recombrate',\n type: 'line',\n fields: ['{{namespace[recomb]}}position', '{{namespace[recomb]}}recomb_rate'],\n z_index: 1,\n style: {\n 'stroke': '#0000FF',\n 'stroke-width': '1.5px'\n },\n x_axis: {\n field: '{{namespace[recomb]}}position'\n },\n y_axis: {\n axis: 2,\n field: '{{namespace[recomb]}}recomb_rate',\n floor: 0,\n ceiling: 100\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'association_pvalues', {\n namespace: { 'assoc': 'assoc', 'ld': 'ld' },\n id: 'associationpvalues',\n type: 'scatter',\n point_shape: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 'diamond',\n else: 'circle'\n }\n },\n point_size: {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: 80,\n else: 40\n }\n },\n color: [\n {\n scale_function: 'if',\n field: '{{namespace[ld]}}isrefvar',\n parameters: {\n field_value: 1,\n then: '#9632b8'\n }\n },\n {\n scale_function: 'numerical_bin',\n field: '{{namespace[ld]}}state',\n parameters: {\n breaks: [0, 0.2, 0.4, 0.6, 0.8],\n values: ['#357ebd', '#46b8da', '#5cb85c', '#eea236', '#d43f3a']\n }\n },\n '#B8B8B8'\n ],\n legend: [\n { shape: 'diamond', color: '#9632b8', size: 40, label: 'LD Ref Var', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#d43f3a', size: 40, label: '1.0 > r² ≥ 0.8', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#eea236', size: 40, label: '0.8 > r² ≥ 0.6', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#5cb85c', size: 40, label: '0.6 > r² ≥ 0.4', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#46b8da', size: 40, label: '0.4 > r² ≥ 0.2', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#357ebd', size: 40, label: '0.2 > r² ≥ 0.0', class: 'lz-data_layer-scatter' },\n { shape: 'circle', color: '#B8B8B8', size: 40, label: 'no r² data', class: 'lz-data_layer-scatter' }\n ],\n label: null,\n fields: ['{{namespace[assoc]}}variant', '{{namespace[assoc]}}position', '{{namespace[assoc]}}log_pvalue', '{{namespace[assoc]}}log_pvalue|logtoscinotation', '{{namespace[assoc]}}ref_allele', '{{namespace[ld]}}state', '{{namespace[ld]}}isrefvar'],\n id_field: '{{namespace[assoc]}}variant',\n z_index: 2,\n x_axis: {\n field: '{{namespace[assoc]}}position'\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[assoc]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.10,\n min_extent: [0, 10]\n },\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_association', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'association_pvalues_catalog', function () {\n // Slightly modify an existing layout\n var l = LocusZoom.Layouts.get('data_layer', 'association_pvalues', {\n unnamespaced: true,\n id: 'associationpvaluescatalog',\n fill_opacity: 0.7\n });\n l.tooltip.html += '{{#if {{namespace[catalog]}}rsid}}
See hits in GWAS catalog{{/if}}';\n l.namespace.catalog = 'catalog';\n l.fields.push('{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait', '{{namespace[catalog]}}log_pvalue');\n return l;\n}());\n\nLocusZoom.Layouts.add('data_layer', 'phewas_pvalues', {\n namespace: { 'phewas': 'phewas' },\n id: 'phewaspvalues',\n type: 'category_scatter',\n point_shape: 'circle',\n point_size: 70,\n tooltip_positioning: 'vertical',\n id_field: '{{namespace[phewas]}}id',\n fields: ['{{namespace[phewas]}}id', '{{namespace[phewas]}}log_pvalue', '{{namespace[phewas]}}trait_group', '{{namespace[phewas]}}trait_label'],\n x_axis: {\n field: '{{namespace[phewas]}}x', // Synthetic/derived field added by `category_scatter` layer\n category_field: '{{namespace[phewas]}}trait_group',\n lower_buffer: 0.025,\n upper_buffer: 0.025\n },\n y_axis: {\n axis: 1,\n field: '{{namespace[phewas]}}log_pvalue',\n floor: 0,\n upper_buffer: 0.15\n },\n color: [{\n field: '{{namespace[phewas]}}trait_group',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [],\n values: [],\n null_value: '#B8B8B8'\n }\n }],\n fill_opacity: 0.7,\n tooltip: {\n closable: true,\n show: { or: ['highlighted', 'selected'] },\n hide: { and: ['unhighlighted', 'unselected'] },\n html: [\n 'Trait: {{{{namespace[phewas]}}trait_label|htmlescape}}
',\n 'Trait Category: {{{{namespace[phewas]}}trait_group|htmlescape}}
',\n 'P-value: {{{{namespace[phewas]}}log_pvalue|logtoscinotation|htmlescape}}
'\n ].join('')\n },\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n label: {\n text: '{{{{namespace[phewas]}}trait_label|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n {\n field: '{{namespace[phewas]}}log_pvalue',\n operator: '>=',\n value: 20\n }\n ],\n style: {\n 'font-size': '14px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'genes', {\n namespace: { 'gene': 'gene', 'constraint': 'constraint' },\n id: 'genes',\n type: 'genes',\n fields: ['{{namespace[gene]}}all', '{{namespace[constraint]}}all'],\n id_field: 'gene_id',\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_genes', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'genome_legend', {\n namespace: { 'genome': 'genome' },\n id: 'genome_legend',\n type: 'genome_legend',\n fields: ['{{namespace[genome]}}chr', '{{namespace[genome]}}base_pairs'],\n x_axis: {\n floor: 0,\n ceiling: 2881033286\n }\n});\n\nLocusZoom.Layouts.add('data_layer', 'intervals', {\n namespace: { 'intervals': 'intervals' },\n id: 'intervals',\n type: 'intervals',\n fields: ['{{namespace[intervals]}}start', '{{namespace[intervals]}}end', '{{namespace[intervals]}}state_id', '{{namespace[intervals]}}state_name'],\n id_field: '{{namespace[intervals]}}start',\n start_field: '{{namespace[intervals]}}start',\n end_field: '{{namespace[intervals]}}end',\n track_split_field: '{{namespace[intervals]}}state_id',\n split_tracks: true,\n always_hide_legend: false,\n color: {\n field: '{{namespace[intervals]}}state_id',\n scale_function: 'categorical_bin',\n parameters: {\n categories: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],\n values: ['rgb(212,63,58)', 'rgb(250,120,105)', 'rgb(252,168,139)', 'rgb(240,189,66)', 'rgb(250,224,105)', 'rgb(240,238,84)', 'rgb(244,252,23)', 'rgb(23,232,252)', 'rgb(32,191,17)', 'rgb(23,166,77)', 'rgb(32,191,17)', 'rgb(162,133,166)', 'rgb(212,212,212)'],\n null_value: '#B8B8B8'\n }\n },\n legend: [\n { shape: 'rect', color: 'rgb(212,63,58)', width: 9, label: 'Active Promoter', '{{namespace[intervals]}}state_id': 1 },\n { shape: 'rect', color: 'rgb(250,120,105)', width: 9, label: 'Weak Promoter', '{{namespace[intervals]}}state_id': 2 },\n { shape: 'rect', color: 'rgb(252,168,139)', width: 9, label: 'Poised Promoter', '{{namespace[intervals]}}state_id': 3 },\n { shape: 'rect', color: 'rgb(240,189,66)', width: 9, label: 'Strong enhancer', '{{namespace[intervals]}}state_id': 4 },\n { shape: 'rect', color: 'rgb(250,224,105)', width: 9, label: 'Strong enhancer', '{{namespace[intervals]}}state_id': 5 },\n { shape: 'rect', color: 'rgb(240,238,84)', width: 9, label: 'Weak enhancer', '{{namespace[intervals]}}state_id': 6 },\n { shape: 'rect', color: 'rgb(244,252,23)', width: 9, label: 'Weak enhancer', '{{namespace[intervals]}}state_id': 7 },\n { shape: 'rect', color: 'rgb(23,232,252)', width: 9, label: 'Insulator', '{{namespace[intervals]}}state_id': 8 },\n { shape: 'rect', color: 'rgb(32,191,17)', width: 9, label: 'Transcriptional transition', '{{namespace[intervals]}}state_id': 9 },\n { shape: 'rect', color: 'rgb(23,166,77)', width: 9, label: 'Transcriptional elongation', '{{namespace[intervals]}}state_id': 10 },\n { shape: 'rect', color: 'rgb(136,240,129)', width: 9, label: 'Weak transcribed', '{{namespace[intervals]}}state_id': 11 },\n { shape: 'rect', color: 'rgb(162,133,166)', width: 9, label: 'Polycomb-repressed', '{{namespace[intervals]}}state_id': 12 },\n { shape: 'rect', color: 'rgb(212,212,212)', width: 9, label: 'Heterochromatin / low signal', '{{namespace[intervals]}}state_id': 13 }\n ],\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'standard_intervals', { unnamespaced: true })\n});\n\nLocusZoom.Layouts.add('data_layer', 'annotation_catalog', {\n // Identify GWAS hits that are present in the GWAS catalog\n namespace: { 'assoc': 'assoc', 'catalog': 'catalog' },\n id: 'annotation_catalog',\n type: 'annotation_track',\n id_field: '{{namespace[catalog]}}variant',\n x_axis: {\n field: '{{namespace[assoc]}}position'\n },\n color: '#0000CC',\n fields: [\n '{{namespace[assoc]}}variant', '{{namespace[assoc]}}chromosome', '{{namespace[assoc]}}position',\n '{{namespace[catalog]}}variant', '{{namespace[catalog]}}rsid', '{{namespace[catalog]}}trait',\n '{{namespace[catalog]}}log_pvalue', '{{namespace[catalog]}}pos'\n ],\n filters: [\n // Specify which points to show on the track. Any selection must satisfy ALL filters\n ['{{namespace[catalog]}}rsid', '!=', null],\n ['{{namespace[catalog]}}log_pvalue', '>', LZ_SIG_THRESHOLD_LOGP]\n ],\n behaviors: {\n onmouseover: [\n { action: 'set', status: 'highlighted' }\n ],\n onmouseout: [\n { action: 'unset', status: 'highlighted' }\n ],\n onclick: [\n { action: 'toggle', status: 'selected', exclusive: true }\n ],\n onshiftclick: [\n { action: 'toggle', status: 'selected' }\n ]\n },\n tooltip: LocusZoom.Layouts.get('tooltip', 'catalog_variant', { unnamespaced: true }),\n tooltip_positioning: 'top'\n});\n\n/**\n * Individual dashboard buttons\n * @namespace Layouts.dashboard_components\n */\nLocusZoom.Layouts.add('dashboard_components', 'ldlz2_pop_selector', {\n // **Note**: this widget is aimed at the LDLZ2 datasource, and the UM 1000G LDServer. Older LZ usages\n // (on the original LD data source) will not work with these population names.\n type: 'set_state',\n position: 'right',\n color: 'blue',\n button_html: 'LD Population: ',\n show_selected: true,\n button_title: 'Select LD Population: ',\n state_field: 'ld_pop',\n // This list below is hardcoded to work with the UMich LDServer, default 1000G populations\n // It can be customized to work with other LD servers that specify population differently\n // https://portaldev.sph.umich.edu/ld/genome_builds/GRCh37/references/1000G/populations\n options: [\n { display_name: 'ALL (default)', value: 'ALL' },\n { display_name: 'AFR', value: 'AFR' },\n { display_name: 'AMR', value: 'AMR' },\n { display_name: 'EAS', value: 'EAS' },\n { display_name: 'EUR', value: 'EUR' },\n { display_name: 'SAS', value: 'SAS' }\n ]\n});\n\n/**\n * Dashboard Layouts: Collections of toolbar buttons etc\n * @namespace Layouts.dashboard\n */\nLocusZoom.Layouts.add('dashboard', 'standard_panel', {\n components: [\n {\n type: 'remove_panel',\n position: 'right',\n color: 'red',\n group_position: 'end'\n },\n {\n type: 'move_panel_up',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'move_panel_down',\n position: 'right',\n group_position: 'start',\n style: { 'margin-left': '0.75em' }\n }\n ]\n});\n\nLocusZoom.Layouts.add('dashboard', 'standard_plot', {\n components: [\n {\n type: 'title',\n title: 'LocusZoom',\n subtitle: 'v' + LocusZoom.version + '',\n position: 'left'\n },\n {\n type: 'download',\n position: 'right'\n }\n ]\n});\n\nLocusZoom.Layouts.add('dashboard', 'covariates_model_plot', function () {\n var covariates_model_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n covariates_model_plot_dashboard.components.push({\n type: 'covariates_model',\n button_html: 'Model',\n button_title: 'Show and edit covariates currently in model',\n position: 'left'\n });\n return covariates_model_plot_dashboard;\n}());\n\nLocusZoom.Layouts.add('dashboard', 'region_nav_plot', function () {\n var region_nav_plot_dashboard = LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true });\n region_nav_plot_dashboard.components.push(\n {\n type: 'shift_region',\n step: 500000,\n button_html: '>>',\n position: 'right',\n group_position: 'end'\n }, {\n type: 'shift_region',\n step: 50000,\n button_html: '>',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'zoom_region',\n step: 0.2,\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'zoom_region',\n step: -0.2,\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'shift_region',\n step: -50000,\n button_html: '<',\n position: 'right',\n group_position: 'middle'\n },\n {\n type: 'shift_region',\n step: -500000,\n button_html: '<<',\n position: 'right',\n group_position: 'start'\n }\n );\n return region_nav_plot_dashboard;\n}());\n\n/**\n * Panel Layouts\n * @namespace Layouts.panel\n */\n\nLocusZoom.Layouts.add('panel', 'association', {\n id: 'association',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 200,\n proportional_width: 1,\n margin: { top: 35, right: 50, bottom: 40, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_legend',\n position: 'right'\n });\n return l;\n })(),\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n },\n y2: {\n label: 'Recombination Rate (cM/Mb)',\n label_offset: 40\n }\n },\n legend: {\n orientation: 'vertical',\n origin: { x: 55, y: 40 },\n hidden: true\n },\n interaction: {\n drag_background_to_pan: true,\n drag_x_ticks_to_scale: true,\n drag_y1_ticks_to_scale: true,\n drag_y2_ticks_to_scale: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'association_catalog', function () {\n var l = LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n id: 'associationcatalog',\n namespace: { 'assoc': 'assoc', 'ld': 'ld', 'catalog': 'catalog' } // Required to resolve display options\n });\n l.dashboard.components.push({\n type: 'display_options',\n position: 'right',\n color: 'blue',\n // Below: special config specific to this widget\n button_html: 'Display options...',\n button_title: 'Control how plot items are displayed',\n\n layer_name: 'associationpvaluescatalog',\n default_config_display_name: 'No catalog labels (default)', // display name for the default plot color option (allow user to revert to plot defaults)\n\n options: [\n {\n // First dropdown menu item\n display_name: 'Label catalog traits', // Human readable representation of field name\n display: { // Specify layout directives that control display of the plot for this option\n label: {\n text: '{{{{namespace[catalog]}}trait|htmlescape}}',\n spacing: 6,\n lines: {\n style: {\n 'stroke-width': '2px',\n 'stroke': '#333333',\n 'stroke-dasharray': '2px 2px'\n }\n },\n filters: [\n // Only label points if they are significant for some trait in the catalog, AND in high LD\n // with the top hit of interest\n {\n field: '{{namespace[catalog]}}trait',\n operator: '!=',\n value: null\n },\n {\n field: '{{namespace[catalog]}}log_pvalue',\n operator: '>',\n value: LZ_SIG_THRESHOLD_LOGP\n },\n {\n field: '{{namespace[ld]}}state',\n operator: '>',\n value: 0.4\n },\n ],\n style: {\n 'font-size': '10px',\n 'font-weight': 'bold',\n 'fill': '#333333'\n }\n }\n }\n }\n ]\n });\n l.data_layers = [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'recomb_rate', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'association_pvalues_catalog', { unnamespaced: true })\n ];\n return l;\n}());\n\nLocusZoom.Layouts.add('panel', 'genes', {\n id: 'genes',\n width: 800,\n height: 225,\n min_width: 400,\n min_height: 112.5,\n proportional_width: 1,\n margin: { top: 20, right: 50, bottom: 20, left: 50 },\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'resize_to_data',\n position: 'right',\n button_html: 'Show all genes',\n });\n return l;\n })(),\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'genes', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'phewas', {\n id: 'phewas',\n width: 800,\n height: 300,\n min_width: 800,\n min_height: 300,\n proportional_width: 1,\n margin: { top: 20, right: 50, bottom: 120, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n axes: {\n x: {\n ticks: { // Object based config (shared defaults; allow layers to specify ticks)\n style: {\n 'font-weight': 'bold',\n 'font-size': '11px',\n 'text-anchor': 'start'\n },\n transform: 'rotate(50)',\n position: 'left' // Special param recognized by `category_scatter` layers\n }\n },\n y1: {\n label: '-log10 p-value',\n label_offset: 28\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'significance', { unnamespaced: true }),\n LocusZoom.Layouts.get('data_layer', 'phewas_pvalues', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'genome_legend', {\n id: 'genome_legend',\n width: 800,\n height: 50,\n origin: { x: 0, y: 300 },\n min_width: 800,\n min_height: 50,\n proportional_width: 1,\n margin: { top: 0, right: 50, bottom: 35, left: 50 },\n axes: {\n x: {\n label: 'Genomic Position (number denotes chromosome)',\n label_offset: 35,\n ticks: [\n {\n x: 124625310,\n text: '1',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 370850307,\n text: '2',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 591461209,\n text: '3',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 786049562,\n text: '4',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 972084330,\n text: '5',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1148099493,\n text: '6',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1313226358,\n text: '7',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1465977701,\n text: '8',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1609766427,\n text: '9',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1748140516,\n text: '10',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 1883411148,\n text: '11',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2017840353,\n text: '12',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2142351240,\n text: '13',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2253610949,\n text: '14',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2358551415,\n text: '15',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2454994487,\n text: '16',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2540769469,\n text: '17',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2620405698,\n text: '18',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2689008813,\n text: '19',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2750086065,\n text: '20',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2805663772,\n text: '21',\n style: {\n 'fill': 'rgb(120, 120, 186)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n },\n {\n x: 2855381003,\n text: '22',\n style: {\n 'fill': 'rgb(0, 0, 66)',\n 'text-anchor': 'center',\n 'font-size': '13px',\n 'font-weight': 'bold'\n },\n transform: 'translate(0, 2)'\n }\n ]\n }\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'genome_legend', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'intervals', {\n id: 'intervals',\n width: 1000,\n height: 50,\n min_width: 500,\n min_height: 50,\n margin: { top: 25, right: 150, bottom: 5, left: 50 },\n dashboard: (function () {\n var l = LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true });\n l.components.push({\n type: 'toggle_split_tracks',\n data_layer_id: 'intervals',\n position: 'right'\n });\n return l;\n })(),\n axes: {},\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n legend: {\n hidden: true,\n orientation: 'horizontal',\n origin: { x: 50, y: 0 },\n pad_from_bottom: 5\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'intervals', { unnamespaced: true })\n ]\n});\n\nLocusZoom.Layouts.add('panel', 'annotation_catalog', {\n id: 'annotationcatalog',\n width: 800,\n height: 50,\n min_height: 50,\n proportional_width: 1,\n margin: { top: 25, right: 50, bottom: 0, left: 50 },\n inner_border: 'rgb(210, 210, 210)',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_panel', { unnamespaced: true }),\n interaction: {\n drag_background_to_pan: true,\n scroll_to_zoom: true,\n x_linked: true\n },\n data_layers: [\n LocusZoom.Layouts.get('data_layer', 'annotation_catalog', { unnamespaced: true })\n ]\n});\n\n/**\n * Plot Layouts\n * @namespace Layouts.plot\n */\n\nLocusZoom.Layouts.add('plot', 'standard_association', {\n state: {},\n width: 800,\n height: 450,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', { unnamespaced: true, proportional_height: 0.5 }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true, proportional_height: 0.5 })\n ]\n});\n\nLocusZoom.Layouts.add('plot', 'association_catalog', {\n state: {},\n width: 800,\n height: 500,\n responsive_resize: 'width_only',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'annotation_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'association_catalog', { unnamespaced: true }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true })\n ]\n});\n\n// Shortcut to \"StandardLayout\" for backward compatibility\nLocusZoom.StandardLayout = LocusZoom.Layouts.get('plot', 'standard_association');\n\nLocusZoom.Layouts.add('plot', 'standard_phewas', {\n width: 800,\n height: 600,\n min_width: 800,\n min_height: 600,\n responsive_resize: 'both',\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'phewas', { unnamespaced: true, proportional_height: 0.45 }),\n LocusZoom.Layouts.get('panel', 'genome_legend', { unnamespaced: true, proportional_height: 0.1 }),\n LocusZoom.Layouts.get('panel', 'genes', {\n unnamespaced: true, proportional_height: 0.45,\n margin: { bottom: 40 },\n axes: {\n x: {\n label: 'Chromosome {{chr}} (Mb)',\n label_offset: 32,\n tick_format: 'region',\n extent: 'state'\n }\n }\n })\n ],\n mouse_guide: false\n});\n\nLocusZoom.Layouts.add('plot', 'interval_association', {\n state: {},\n width: 800,\n height: 550,\n responsive_resize: 'both',\n min_region_scale: 20000,\n max_region_scale: 1000000,\n dashboard: LocusZoom.Layouts.get('dashboard', 'standard_plot', { unnamespaced: true }),\n panels: [\n LocusZoom.Layouts.get('panel', 'association', {\n unnamespaced: true,\n width: 800,\n proportional_height: (225 / 570)\n }),\n LocusZoom.Layouts.get('panel', 'intervals', { unnamespaced: true, proportional_height: (120 / 570) }),\n LocusZoom.Layouts.get('panel', 'genes', { unnamespaced: true, width: 800, proportional_height: (225 / 570) })\n ]\n});\n","/**\n * @namespace\n */\nvar LocusZoom = {\n version: '0.10.1'\n};\n\n/**\n * Populate a single element with a LocusZoom plot.\n * selector can be a string for a DOM Query or a d3 selector.\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot} The newly created plot instance\n */\nLocusZoom.populate = function(selector, datasource, layout) {\n if (typeof selector == 'undefined') {\n throw new Error('LocusZoom.populate selector not defined');\n }\n // Empty the selector of any existing content\n d3.select(selector).html('');\n var plot;\n d3.select(selector).call(function() {\n // Require each containing element have an ID. If one isn't present, create one.\n if (typeof this.node().id == 'undefined') {\n var iterator = 0;\n while (!d3.select('#lz-' + iterator).empty()) { iterator++; }\n this.attr('id', '#lz-' + iterator);\n }\n // Create the plot\n plot = new LocusZoom.Plot(this.node().id, datasource, layout);\n plot.container = this.node();\n // Detect data-region and fill in state values if present\n if (typeof this.node().dataset !== 'undefined' && typeof this.node().dataset.region !== 'undefined') {\n var parsed_state = LocusZoom.parsePositionQuery(this.node().dataset.region);\n Object.keys(parsed_state).forEach(function(key) {\n plot.state[key] = parsed_state[key];\n });\n }\n // Add an SVG to the div and set its dimensions\n plot.svg = d3.select('div#' + plot.id)\n .append('svg')\n .attr('version', '1.1')\n .attr('xmlns', 'http://www.w3.org/2000/svg')\n .attr('id', plot.id + '_svg').attr('class', 'lz-locuszoom')\n .style(plot.layout.style);\n plot.setDimensions();\n plot.positionPanels();\n // Initialize the plot\n plot.initialize();\n // If the plot has defined data sources then trigger its first mapping based on state values\n if (typeof datasource == 'object' && Object.keys(datasource).length) {\n plot.refresh();\n }\n });\n return plot;\n};\n\n/**\n * Populate arbitrarily many elements each with a LocusZoom plot\n * using a common datasource and layout\n * @param {String} selector CSS selector for the container element where the plot will be mounted. Any pre-existing\n * content in the container will be completely replaced.\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n * @returns {LocusZoom.Plot[]}\n */\nLocusZoom.populateAll = function(selector, datasource, layout) {\n var plots = [];\n d3.selectAll(selector).each(function(d,i) {\n plots[i] = LocusZoom.populate(this, datasource, layout);\n });\n return plots;\n};\n\n/**\n * Convert an integer chromosome position to an SI string representation (e.g. 23423456 => \"23.42\" (Mb))\n * @param {Number} pos Position\n * @param {Number} [exp] Exponent to use for the returned string, eg 6=> MB. If not specified, will attempt to guess\n * the most appropriate SI prefix based on the number provided.\n * @param {Boolean} [suffix=false] Whether or not to append a suffix (e.g. \"Mb\") to the end of the returned string\n * @returns {string}\n */\nLocusZoom.positionIntToString = function(pos, exp, suffix) {\n var exp_symbols = { 0: '', 3: 'K', 6: 'M', 9: 'G' };\n suffix = suffix || false;\n if (isNaN(exp) || exp === null) {\n var log = Math.log(pos) / Math.LN10;\n exp = Math.min(Math.max(log - (log % 3), 0), 9);\n }\n var places_exp = exp - Math.floor((Math.log(pos) / Math.LN10).toFixed(exp + 3));\n var min_exp = Math.min(Math.max(exp, 0), 2);\n var places = Math.min(Math.max(places_exp, min_exp), 12);\n var ret = '' + (pos / Math.pow(10, exp)).toFixed(places);\n if (suffix && typeof exp_symbols[exp] !== 'undefined') {\n ret += ' ' + exp_symbols[exp] + 'b';\n }\n return ret;\n};\n\n/**\n * Convert an SI string chromosome position to an integer representation (e.g. \"5.8 Mb\" => 58000000)\n * @param {String} p The chromosome position\n * @returns {Number}\n */\nLocusZoom.positionStringToInt = function(p) {\n var val = p.toUpperCase();\n val = val.replace(/,/g, '');\n var suffixre = /([KMG])[B]*$/;\n var suffix = suffixre.exec(val);\n var mult = 1;\n if (suffix) {\n if (suffix[1] === 'M') {\n mult = 1e6;\n } else if (suffix[1] === 'G') {\n mult = 1e9;\n } else {\n mult = 1e3; //K\n }\n val = val.replace(suffixre,'');\n }\n val = Number(val) * mult;\n return val;\n};\n\n/**\n * Parse region queries into their constituent parts\n * TODO: handle genes (or send off to API)\n * @param {String} x A chromosome position query. May be any of the forms `chr:start-end`, `chr:center+offset`,\n * or `chr:pos`\n * @returns {{chr:*, start: *, end:*} | {chr:*, position:*}}\n */\nLocusZoom.parsePositionQuery = function(x) {\n var chrposoff = /^(\\w+):([\\d,.]+[kmgbKMGB]*)([-+])([\\d,.]+[kmgbKMGB]*)$/;\n var chrpos = /^(\\w+):([\\d,.]+[kmgbKMGB]*)$/;\n var match = chrposoff.exec(x);\n if (match) {\n if (match[3] === '+') {\n var center = LocusZoom.positionStringToInt(match[2]);\n var offset = LocusZoom.positionStringToInt(match[4]);\n return {\n chr:match[1],\n start: center - offset,\n end: center + offset\n };\n } else {\n return {\n chr: match[1],\n start: LocusZoom.positionStringToInt(match[2]),\n end: LocusZoom.positionStringToInt(match[4])\n };\n }\n }\n match = chrpos.exec(x);\n if (match) {\n return {\n chr:match[1],\n position: LocusZoom.positionStringToInt(match[2])\n };\n }\n return null;\n};\n\n/**\n * Generate a \"pretty\" set of ticks (multiples of 1, 2, or 5 on the same order of magnitude for the range)\n * Based on R's \"pretty\" function: https://github.com/wch/r-source/blob/b156e3a711967f58131e23c1b1dc1ea90e2f0c43/src/appl/pretty.c\n * @param {Number[]} range A two-item array specifying [low, high] values for the axis range\n * @param {('low'|'high'|'both'|'neither')} [clip_range='neither'] What to do if first and last generated ticks extend\n * beyond the range. Set this to \"low\", \"high\", \"both\", or \"neither\" to clip the first (low) or last (high) tick to\n * be inside the range or allow them to extend beyond.\n * e.g. \"low\" will clip the first (low) tick if it extends beyond the low end of the range but allow the\n * last (high) tick to extend beyond the range. \"both\" clips both ends, \"neither\" allows both to extend beyond.\n * @param {Number} [target_tick_count=5] The approximate number of ticks you would like to be returned; may not be exact\n * @returns {Number[]}\n */\nLocusZoom.prettyTicks = function(range, clip_range, target_tick_count) {\n if (typeof target_tick_count == 'undefined' || isNaN(parseInt(target_tick_count))) {\n target_tick_count = 5;\n }\n target_tick_count = parseInt(target_tick_count);\n\n var min_n = target_tick_count / 3;\n var shrink_sml = 0.75;\n var high_u_bias = 1.5;\n var u5_bias = 0.5 + 1.5 * high_u_bias;\n\n var d = Math.abs(range[0] - range[1]);\n var c = d / target_tick_count;\n if ((Math.log(d) / Math.LN10) < -2) {\n c = (Math.max(Math.abs(d)) * shrink_sml) / min_n;\n }\n\n var base = Math.pow(10, Math.floor(Math.log(c) / Math.LN10));\n var base_toFixed = 0;\n if (base < 1 && base !== 0) {\n base_toFixed = Math.abs(Math.round(Math.log(base) / Math.LN10));\n }\n\n var unit = base;\n if ( ((2 * base) - c) < (high_u_bias * (c - unit)) ) {\n unit = 2 * base;\n if ( ((5 * base) - c) < (u5_bias * (c - unit)) ) {\n unit = 5 * base;\n if ( ((10 * base) - c) < (high_u_bias * (c - unit)) ) {\n unit = 10 * base;\n }\n }\n }\n\n var ticks = [];\n var i = parseFloat( (Math.floor(range[0] / unit) * unit).toFixed(base_toFixed) );\n while (i < range[1]) {\n ticks.push(i);\n i += unit;\n if (base_toFixed > 0) {\n i = parseFloat(i.toFixed(base_toFixed));\n }\n }\n ticks.push(i);\n\n if (typeof clip_range == 'undefined' || ['low', 'high', 'both', 'neither'].indexOf(clip_range) === -1) {\n clip_range = 'neither';\n }\n if (clip_range === 'low' || clip_range === 'both') {\n if (ticks[0] < range[0]) { ticks = ticks.slice(1); }\n }\n if (clip_range === 'high' || clip_range === 'both') {\n if (ticks[ticks.length - 1] > range[1]) { ticks.pop(); }\n }\n\n return ticks;\n};\n\n/**\n * Make an AJAX request and return a promise.\n * From http://www.html5rocks.com/en/tutorials/cors/\n * and with promises from https://gist.github.com/kriskowal/593076\n *\n * @param {String} method The HTTP verb\n * @param {String} url\n * @param {String} [body] The request body to send to the server\n * @param {Object} [headers] Object of custom request headers\n * @param {Number} [timeout] If provided, wait this long (in ms) before timing out\n * @returns {Promise}\n */\nLocusZoom.createCORSPromise = function (method, url, body, headers, timeout) {\n return new Promise(function (resolve, reject) {\n var xhr = new XMLHttpRequest();\n if ('withCredentials' in xhr) {\n // Check if the XMLHttpRequest object has a \"withCredentials\" property.\n // \"withCredentials\" only exists on XMLHTTPRequest2 objects.\n xhr.open(method, url, true);\n } else if (typeof XDomainRequest != 'undefined') {\n // Otherwise, check if XDomainRequest.\n // XDomainRequest only exists in IE, and is IE's way of making CORS requests.\n xhr = new XDomainRequest();\n xhr.open(method, url);\n } else {\n // Otherwise, CORS is not supported by the browser.\n xhr = null;\n }\n if (xhr) {\n xhr.onreadystatechange = function() {\n if (xhr.readyState === 4) {\n if (xhr.status === 200 || xhr.status === 0 ) {\n resolve(xhr.response);\n } else {\n reject('HTTP ' + xhr.status + ' for ' + url);\n }\n }\n };\n timeout && setTimeout(reject, timeout);\n body = typeof body !== 'undefined' ? body : '';\n if (typeof headers !== 'undefined') {\n for (var header in headers) {\n xhr.setRequestHeader(header, headers[header]);\n }\n }\n // Send the request\n xhr.send(body);\n }\n });\n};\n\n/**\n * Validate a (presumed complete) plot state object against internal rules for consistency, and ensure the plot fits\n * within any constraints imposed by the layout.\n * @param {Object} new_state\n * @param {Number} new_state.start\n * @param {Number} new_state.end\n * @param {Object} layout\n * @returns {*|{}}\n */\nLocusZoom.validateState = function(new_state, layout) {\n\n new_state = new_state || {};\n layout = layout || {};\n\n // If a \"chr\", \"start\", and \"end\" are present then resolve start and end\n // to numeric values that are not decimal, negative, or flipped\n var validated_region = false;\n if (typeof new_state.chr != 'undefined' && typeof new_state.start != 'undefined' && typeof new_state.end != 'undefined') {\n // Determine a numeric scale and midpoint for the attempted region,\n var attempted_midpoint = null; var attempted_scale;\n new_state.start = Math.max(parseInt(new_state.start), 1);\n new_state.end = Math.max(parseInt(new_state.end), 1);\n if (isNaN(new_state.start) && isNaN(new_state.end)) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_midpoint = 0.5;\n attempted_scale = 0;\n } else if (isNaN(new_state.start) || isNaN(new_state.end)) {\n attempted_midpoint = new_state.start || new_state.end;\n attempted_scale = 0;\n new_state.start = (isNaN(new_state.start) ? new_state.end : new_state.start);\n new_state.end = (isNaN(new_state.end) ? new_state.start : new_state.end);\n } else {\n attempted_midpoint = Math.round((new_state.start + new_state.end) / 2);\n attempted_scale = new_state.end - new_state.start;\n if (attempted_scale < 0) {\n var temp = new_state.start;\n new_state.end = new_state.start;\n new_state.start = temp;\n attempted_scale = new_state.end - new_state.start;\n }\n if (attempted_midpoint < 0) {\n new_state.start = 1;\n new_state.end = 1;\n attempted_scale = 0;\n }\n }\n validated_region = true;\n }\n\n // Constrain w/r/t layout-defined minimum region scale\n if (!isNaN(layout.min_region_scale) && validated_region && attempted_scale < layout.min_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.min_region_scale / 2), 1);\n new_state.end = new_state.start + layout.min_region_scale;\n }\n\n // Constrain w/r/t layout-defined maximum region scale\n if (!isNaN(layout.max_region_scale) && validated_region && attempted_scale > layout.max_region_scale) {\n new_state.start = Math.max(attempted_midpoint - Math.floor(layout.max_region_scale / 2), 1);\n new_state.end = new_state.start + layout.max_region_scale;\n }\n\n return new_state;\n};\n\n//\n/**\n * Replace placeholders in an html string with field values defined in a data object\n * Only works on scalar values! Will ignore non-scalars.\n *\n * NOTE: Trusts content exactly as given. XSS prevention is the responsibility of the implementer.\n * @param {Object} data\n * @param {String} html A placeholder string in which to substitute fields. Supports several template options:\n * `{{field_name}}` is a variable placeholder for the value of `field_name` from the provided data\n * `{{#if field_name}} Conditional text {{/if}}` will insert the contents of the tag only if the value exists.\n * Since this is only an existence check, **variables with a value of 0 will be evaluated as true**.\n * This can be used with namespaced values, `{{#if assoc:field}}`; any dynamic namespacing will be applied when the\n * layout is first retrieved.\n * @returns {string}\n */\nLocusZoom.parseFields = function (data, html) {\n if (typeof data != 'object') {\n throw new Error('LocusZoom.parseFields invalid arguments: data is not an object');\n }\n if (typeof html != 'string') {\n throw new Error('LocusZoom.parseFields invalid arguments: html is not a string');\n }\n // `tokens` is like [token,...]\n // `token` is like {text: '...'} or {variable: 'foo|bar'} or {condition: 'foo|bar'} or {close: 'if'}\n var tokens = [];\n var regex = /\\{\\{(?:(#if )?([A-Za-z0-9_:|]+)|(\\/if))\\}\\}/;\n while (html.length > 0) {\n var m = regex.exec(html);\n if (!m) { tokens.push({text: html}); html = ''; }\n else if (m.index !== 0) { tokens.push({text: html.slice(0, m.index)}); html = html.slice(m.index); }\n else if (m[1] === '#if ') { tokens.push({condition: m[2]}); html = html.slice(m[0].length); }\n else if (m[2]) { tokens.push({variable: m[2]}); html = html.slice(m[0].length); }\n else if (m[3] === '/if') { tokens.push({close: 'if'}); html = html.slice(m[0].length); }\n else {\n console.error('Error tokenizing tooltip when remaining template is ' + JSON.stringify(html) +\n ' and previous tokens are ' + JSON.stringify(tokens) +\n ' and current regex match is ' + JSON.stringify([m[1], m[2], m[3]]));\n html = html.slice(m[0].length);\n }\n }\n var astify = function() {\n var token = tokens.shift();\n if (typeof token.text !== 'undefined' || token.variable) {\n return token;\n } else if (token.condition) {\n token.then = [];\n while(tokens.length > 0) {\n if (tokens[0].close === 'if') { tokens.shift(); break; }\n token.then.push(astify());\n }\n return token;\n } else {\n console.error('Error making tooltip AST due to unknown token ' + JSON.stringify(token));\n return { text: '' };\n }\n };\n // `ast` is like [thing,...]\n // `thing` is like {text: \"...\"} or {variable:\"foo|bar\"} or {condition: \"foo|bar\", then:[thing,...]}\n var ast = [];\n while (tokens.length > 0) {\n ast.push(astify());\n }\n\n var resolve = function(variable) {\n if (!resolve.cache.hasOwnProperty(variable)) {\n resolve.cache[variable] = (new LocusZoom.Data.Field(variable)).resolve(data);\n }\n return resolve.cache[variable];\n };\n resolve.cache = {};\n var render_node = function(node) {\n if (typeof node.text !== 'undefined') {\n return node.text;\n } else if (node.variable) {\n try {\n var value = resolve(node.variable);\n if (['string','number','boolean'].indexOf(typeof value) !== -1) { return value; }\n if (value === null) { return ''; }\n } catch (error) { console.error('Error while processing variable ' + JSON.stringify(node.variable)); }\n return '{{' + node.variable + '}}';\n } else if (node.condition) {\n try {\n var condition = resolve(node.condition);\n if (condition || condition === 0) {\n return node.then.map(render_node).join('');\n }\n } catch (error) { console.error('Error while processing condition ' + JSON.stringify(node.variable)); }\n return '';\n } else { console.error('Error rendering tooltip due to unknown AST node ' + JSON.stringify(node)); }\n };\n return ast.map(render_node).join('');\n};\n\n/**\n * Shortcut method for getting the data bound to a tool tip.\n * @param {Element} node\n * @returns {*} The first element of data bound to the tooltip\n */\nLocusZoom.getToolTipData = function(node) {\n if (typeof node != 'object' || typeof node.parentNode == 'undefined') {\n throw new Error('Invalid node object');\n }\n // If this node is a locuszoom tool tip then return its data\n var selector = d3.select(node);\n if (selector.classed('lz-data_layer-tooltip') && typeof selector.data()[0] != 'undefined') {\n return selector.data()[0];\n } else {\n return LocusZoom.getToolTipData(node.parentNode);\n }\n};\n\n/**\n * Shortcut method for getting a reference to the data layer that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.DataLayer}\n */\nLocusZoom.getToolTipDataLayer = function(node) {\n var data = LocusZoom.getToolTipData(node);\n if (data.getDataLayer) { return data.getDataLayer(); }\n return null;\n};\n\n/**\n * Shortcut method for getting a reference to the panel that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.getToolTipPanel = function(node) {\n var data_layer = LocusZoom.getToolTipDataLayer(node);\n if (data_layer) { return data_layer.parent; }\n return null;\n};\n\n/**\n * Shortcut method for getting a reference to the plot that generated a tool tip.\n * @param {Element} node The element associated with the tooltip, or any element contained inside the tooltip\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.getToolTipPlot = function(node) {\n var panel = LocusZoom.getToolTipPanel(node);\n if (panel) { return panel.parent; }\n return null;\n};\n\n/**\n * Generate a curtain object for a plot, panel, or any other subdivision of a layout\n * The panel curtain, like the plot curtain is an HTML overlay that obscures the entire panel. It can be styled\n * arbitrarily and display arbitrary messages. It is useful for reporting error messages visually to an end user\n * when the error renders the panel unusable.\n * TODO: Improve type doc here\n * @returns {object}\n */\nLocusZoom.generateCurtain = function() {\n var curtain = {\n showing: false,\n selector: null,\n content_selector: null,\n hide_delay: null,\n\n /**\n * Generate the curtain. Any content (string) argument passed will be displayed in the curtain as raw HTML.\n * CSS (object) can be passed which will apply styles to the curtain and its content.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n show: function(content, css) {\n if (!this.curtain.showing) {\n this.curtain.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div')\n .attr('class', 'lz-curtain').attr('id', this.id + '.curtain');\n this.curtain.content_selector = this.curtain.selector.append('div').attr('class', 'lz-curtain-content');\n this.curtain.selector.append('div').attr('class', 'lz-curtain-dismiss').html('Dismiss')\n .on('click', function() {\n this.curtain.hide();\n }.bind(this));\n this.curtain.showing = true;\n }\n return this.curtain.update(content, css);\n }.bind(this),\n\n /**\n * Update the content and css of the curtain that's currently being shown. This method also adjusts the size\n * and positioning of the curtain to ensure it still covers the entire panel with no overlap.\n * @param {string} content Content to be displayed on the curtain (as raw HTML)\n * @param {object} css Apply the specified styles to the curtain and its contents\n */\n update: function(content, css) {\n if (!this.curtain.showing) { return this.curtain; }\n clearTimeout(this.curtain.hide_delay);\n // Apply CSS if provided\n if (typeof css == 'object') {\n this.curtain.selector.style(css);\n }\n // Update size and position\n var page_origin = this.getPageOrigin();\n this.curtain.selector.style({\n top: page_origin.y + 'px',\n left: page_origin.x + 'px',\n width: this.layout.width + 'px',\n height: this.layout.height + 'px'\n });\n this.curtain.content_selector.style({\n 'max-width': (this.layout.width - 40) + 'px',\n 'max-height': (this.layout.height - 40) + 'px'\n });\n // Apply content if provided\n if (typeof content == 'string') {\n this.curtain.content_selector.html(content);\n }\n return this.curtain;\n }.bind(this),\n\n /**\n * Remove the curtain\n * @param {number} delay Time to wait (in ms)\n */\n hide: function(delay) {\n if (!this.curtain.showing) { return this.curtain; }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.curtain.hide_delay);\n this.curtain.hide_delay = setTimeout(this.curtain.hide, delay);\n return this.curtain;\n }\n // Remove curtain\n this.curtain.selector.remove();\n this.curtain.selector = null;\n this.curtain.content_selector = null;\n this.curtain.showing = false;\n return this.curtain;\n }.bind(this)\n };\n return curtain;\n};\n\n/**\n * Generate a loader object for a plot, panel, or any other subdivision of a layout\n *\n * The panel loader is a small HTML overlay that appears in the lower left corner of the panel. It cannot be styled\n * arbitrarily, but can show a custom message and show a minimalist loading bar that can be updated to specific\n * completion percentages or be animated.\n * TODO Improve type documentation\n * @returns {object}\n */\nLocusZoom.generateLoader = function() {\n var loader = {\n showing: false,\n selector: null,\n content_selector: null,\n progress_selector: null,\n cancel_selector: null,\n\n /**\n * Show a loading indicator\n * @param {string} [content='Loading...'] Loading message (displayed as raw HTML)\n */\n show: function(content) {\n // Generate loader\n if (!this.loader.showing) {\n this.loader.selector = d3.select(this.parent_plot.svg.node().parentNode).insert('div')\n .attr('class', 'lz-loader').attr('id', this.id + '.loader');\n this.loader.content_selector = this.loader.selector.append('div')\n .attr('class', 'lz-loader-content');\n this.loader.progress_selector = this.loader.selector\n .append('div').attr('class', 'lz-loader-progress-container')\n .append('div').attr('class', 'lz-loader-progress');\n /* TODO: figure out how to make this cancel button work\n this.loader.cancel_selector = this.loader.selector.append(\"div\")\n .attr(\"class\", \"lz-loader-cancel\").html(\"Cancel\")\n .on(\"click\", function(){\n this.loader.hide();\n }.bind(this));\n */\n this.loader.showing = true;\n if (typeof content == 'undefined') { content = 'Loading...'; }\n }\n return this.loader.update(content);\n }.bind(this),\n\n /**\n * Update the currently displayed loader and ensure the new content is positioned correctly.\n * @param {string} content The text to display (as raw HTML). If not a string, will be ignored.\n * @param {number} [percent] A number from 1-100. If a value is specified, it will stop all animations\n * in progress.\n */\n update: function(content, percent) {\n if (!this.loader.showing) { return this.loader; }\n clearTimeout(this.loader.hide_delay);\n // Apply content if provided\n if (typeof content == 'string') {\n this.loader.content_selector.html(content);\n }\n // Update size and position\n var padding = 6; // is there a better place to store/define this?\n var page_origin = this.getPageOrigin();\n var loader_boundrect = this.loader.selector.node().getBoundingClientRect();\n this.loader.selector.style({\n top: (page_origin.y + this.layout.height - loader_boundrect.height - padding) + 'px',\n left: (page_origin.x + padding) + 'px'\n });\n /* Uncomment this code when a functional cancel button can be shown\n var cancel_boundrect = this.loader.cancel_selector.node().getBoundingClientRect();\n this.loader.content_selector.style({\n \"padding-right\": (cancel_boundrect.width + padding) + \"px\"\n });\n */\n // Apply percent if provided\n if (typeof percent == 'number') {\n this.loader.progress_selector.style({\n width: (Math.min(Math.max(percent, 1), 100)) + '%'\n });\n }\n return this.loader;\n }.bind(this),\n\n /**\n * Adds a class to the loading bar that makes it loop infinitely in a loading animation. Useful when exact\n * percent progress is not available.\n */\n animate: function() {\n this.loader.progress_selector.classed('lz-loader-progress-animated', true);\n return this.loader;\n }.bind(this),\n\n /**\n * Sets the loading bar in the loader to percentage width equal to the percent (number) value passed. Percents\n * will automatically be limited to a range of 1 to 100. Will stop all animations in progress.\n */\n setPercentCompleted: function(percent) {\n this.loader.progress_selector.classed('lz-loader-progress-animated', false);\n return this.loader.update(null, percent);\n }.bind(this),\n\n /**\n * Remove the loader\n * @param {number} delay Time to wait (in ms)\n */\n hide: function(delay) {\n if (!this.loader.showing) { return this.loader; }\n // If a delay was passed then defer to a timeout\n if (typeof delay == 'number') {\n clearTimeout(this.loader.hide_delay);\n this.loader.hide_delay = setTimeout(this.loader.hide, delay);\n return this.loader;\n }\n // Remove loader\n this.loader.selector.remove();\n this.loader.selector = null;\n this.loader.content_selector = null;\n this.loader.progress_selector = null;\n this.loader.cancel_selector = null;\n this.loader.showing = false;\n return this.loader;\n }.bind(this)\n };\n return loader;\n};\n\n/**\n * Create a new subclass following classical inheritance patterns. Some registry singletons use this internally to\n * enable code reuse and customization of known LZ core functionality.\n *\n * @param {Function} parent A parent class constructor that will be extended by the child class\n * @param {Object} extra An object of additional properties and methods to add/override behavior for the child class.\n * The special \"constructor\" property can be used to specify a custom constructor, or it will call parent by default.\n * Implementer must manage super calls when overriding the constructor.\n * @returns {Function} The constructor for the new child class\n */\nLocusZoom.subclass = function(parent, extra) {\n if (typeof parent !== 'function' ) {\n throw new Error('Parent must be a callable constructor');\n }\n\n extra = extra || {};\n var Sub = extra.hasOwnProperty('constructor') ? extra.constructor : function() {\n parent.apply(this, arguments);\n };\n\n Sub.prototype = Object.create(parent.prototype);\n Object.keys(extra).forEach(function(k) {\n Sub.prototype[k] = extra[k];\n });\n return Sub;\n};\n\n\n/**\n * LocusZoom optional extensions will live under this namespace.\n *\n * Extension code is not part of the core LocusZoom app.js bundle.\n * @namespace\n * @public\n */\nLocusZoom.ext = {};\n","/* global LocusZoom */\n'use strict';\n\nfunction validateBuildSource(class_name, build, source) {\n // Build OR Source, not both\n if ((build && source) || !(build || source)) {\n throw new Error(class_name + ' must provide a parameter specifying either \"build\" or \"source\". It should not specify both.');\n }\n // If the build isn't recognized, our APIs can't transparently select a source to match\n if (build && ['GRCh37', 'GRCh38'].indexOf(build) === -1) {\n throw new Error(class_name + ' must specify a valid genome build number');\n }\n}\n\n/**\n * LocusZoom functionality used for data parsing and retrieval\n * @namespace\n * @public\n */\nLocusZoom.Data = LocusZoom.Data || {};\n\n/**\n * Create and coordinate an ensemble of (namespaced) data source instances\n * @public\n * @class\n */\nLocusZoom.DataSources = function() {\n /** @member {Object.} */\n this.sources = {};\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.addSource = function(ns, x) {\n console.warn('Warning: .addSource() is deprecated. Use .add() instead');\n return this.add(ns, x);\n};\n\n/**\n * Add a (namespaced) datasource to the plot\n * @public\n * @param {String} ns A namespace used for fields from this data source\n * @param {LocusZoom.Data.Source|Array|null} x An instantiated datasource, or an array of arguments that can be used to\n * create a known datasource type.\n */\nLocusZoom.DataSources.prototype.add = function(ns, x) {\n // FIXME: Some existing sites create sources with arbitrary names. This leads to subtle breakage\n // of namespaced fields in layouts. To avoid breaking existing usages outright, issue a deprecation warning.\n if (ns.match(/[^A-Za-z0-9_]/)) {\n console.warn(\"Deprecation warning: source name '\" + ns + \"' should contain only alphanumeric characters or underscores. Use of other characters may break layouts, and will be disallowed in the future.\");\n }\n return this.set(ns, x);\n};\n\n/** @protected */\nLocusZoom.DataSources.prototype.set = function(ns, x) {\n if (Array.isArray(x)) {\n // If passed array of source name and options, make the source\n var dsobj = LocusZoom.KnownDataSources.create.apply(null, x);\n // Each datasource in the chain should be aware of its assigned namespace\n dsobj.source_id = ns;\n this.sources[ns] = dsobj;\n } else {\n // If passed the already-created source object\n if (x !== null) {\n x.source_id = ns;\n this.sources[ns] = x;\n } else {\n delete this.sources[ns];\n }\n }\n return this;\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.getSource = function(ns) {\n console.warn('Warning: .getSource() is deprecated. Use .get() instead');\n return this.get(ns);\n};\n\n/**\n * Return the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n * @returns {LocusZoom.Data.Source}\n */\nLocusZoom.DataSources.prototype.get = function(ns) {\n return this.sources[ns];\n};\n\n/** @deprecated */\nLocusZoom.DataSources.prototype.removeSource = function(ns) {\n console.warn('Warning: .removeSource() is deprecated. Use .remove() instead');\n return this.remove(ns);\n};\n\n/**\n * Remove the datasource associated with a given namespace\n * @public\n * @param {String} ns Namespace\n */\nLocusZoom.DataSources.prototype.remove = function(ns) {\n return this.set(ns, null);\n};\n\n/**\n * Populate a list of datasources specified as a JSON object\n * @public\n * @param {String|Object} x An object or JSON representation containing {ns: configArray} entries\n * @returns {LocusZoom.DataSources}\n */\nLocusZoom.DataSources.prototype.fromJSON = function(x) {\n if (typeof x === 'string') {\n x = JSON.parse(x);\n }\n var ds = this;\n Object.keys(x).forEach(function(ns) {\n ds.set(ns, x[ns]);\n });\n return ds;\n};\n\n/**\n * Return the names of all currently recognized datasources\n * @public\n * @returns {Array}\n */\nLocusZoom.DataSources.prototype.keys = function() {\n return Object.keys(this.sources);\n};\n\n/**\n * Datasources can be instantiated from a JSON object instead of code. This represents existing sources in that format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n * @public\n */\nLocusZoom.DataSources.prototype.toJSON = function() {\n return this.sources;\n};\n\n/**\n * Represents an addressable unit of data from a namespaced datasource, subject to specified value transformations.\n *\n * When used by a data layer, fields will automatically be re-fetched from the appropriate data source whenever the\n * state of a plot fetches, eg pan or zoom operations that would affect what data is displayed.\n *\n * @public\n * @class\n * @param {String} field A string representing the namespace of the datasource, the name of the desired field to fetch\n * from that datasource, and arbitrarily many transformations to apply to the value. The namespace and\n * transformation(s) are optional and information is delimited according to the general syntax\n * `[namespace:]name[|transformation][|transformation]`. For example, `association:pvalue|neglog10`\n */\nLocusZoom.Data.Field = function(field) {\n\n var parts = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/.exec(field);\n /** @member {String} */\n this.full_name = field;\n /** @member {String} */\n this.namespace = parts[1] || null;\n /** @member {String} */\n this.name = parts[2] || null;\n /** @member {Array} */\n this.transformations = [];\n\n if (typeof parts[3] == 'string' && parts[3].length > 1) {\n this.transformations = parts[3].substring(1).split('|');\n this.transformations.forEach(function(transform, i) {\n this.transformations[i] = LocusZoom.TransformationFunctions.get(transform);\n }.bind(this));\n }\n\n this.applyTransformations = function(val) {\n this.transformations.forEach(function(transform) {\n val = transform(val);\n });\n return val;\n };\n\n // Resolve the field for a given data element.\n // First look for a full match with transformations already applied by the data requester.\n // Otherwise prefer a namespace match and fall back to just a name match, applying transformations on the fly.\n this.resolve = function(d) {\n if (typeof d[this.full_name] == 'undefined') {\n var val = null;\n if (typeof (d[this.namespace + ':' + this.name]) != 'undefined') { val = d[this.namespace + ':' + this.name]; }\n else if (typeof d[this.name] != 'undefined') { val = d[this.name]; }\n d[this.full_name] = this.applyTransformations(val);\n }\n return d[this.full_name];\n };\n\n};\n\n/**\n * The Requester manages fetching of data across multiple data sources. It is used internally by LocusZoom data layers.\n * It passes state information and ensures that data is formatted in the manner expected by the plot.\n *\n * It is also responsible for constructing a \"chain\" of dependent requests, by requesting each datasource\n * sequentially in the order specified in the datalayer `fields` array. Data sources are only chained within a\n * data layer, and only if that layer requests more than one kind of data source.\n * @param {LocusZoom.DataSources} sources An object of {ns: LocusZoom.Data.Source} instances\n * @class\n */\nLocusZoom.Data.Requester = function(sources) {\n\n function split_requests(fields) {\n // Given a fields array, return an object specifying what datasource names the data layer should make requests\n // to, and how to handle the returned data\n var requests = {};\n // Regular expression finds namespace:field|trans\n var re = /^(?:([^:]+):)?([^:|]*)(\\|.+)*$/;\n fields.forEach(function(raw) {\n var parts = re.exec(raw);\n var ns = parts[1] || 'base';\n var field = parts[2];\n var trans = LocusZoom.TransformationFunctions.get(parts[3]);\n if (typeof requests[ns] == 'undefined') {\n requests[ns] = {outnames:[], fields:[], trans:[]};\n }\n requests[ns].outnames.push(raw);\n requests[ns].fields.push(field);\n requests[ns].trans.push(trans);\n });\n return requests;\n }\n\n /**\n * Fetch data, and create a chain that only connects two data sources if they depend on each other\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields The list of data fields specified in the `layout` for a specific data layer\n * @returns {Promise}\n */\n this.getData = function(state, fields) {\n var requests = split_requests(fields);\n // Create an array of functions that, when called, will trigger the request to the specified datasource\n var request_handles = Object.keys(requests).map(function(key) {\n if (!sources.get(key)) {\n throw new Error('Datasource for namespace ' + key + ' not found');\n }\n return sources.get(key).getData(state, requests[key].fields,\n requests[key].outnames, requests[key].trans);\n });\n //assume the fields are requested in dependent order\n //TODO: better manage dependencies\n var ret = Promise.resolve({header:{}, body: [], discrete: {}});\n for(var i = 0; i < request_handles.length; i++) {\n // If a single datalayer uses multiple sources, perform the next request when the previous one completes\n ret = ret.then(request_handles[i]);\n }\n return ret;\n };\n};\n\n/**\n * Base class for LocusZoom data sources\n * This can be extended with .extend() to create custom data sources\n * @class\n * @public\n */\nLocusZoom.Data.Source = function() {\n /**\n * Whether this source should enable caching\n * @member {Boolean}\n */\n this.enableCache = true;\n /**\n * Whether this data source type is dependent on previous requests- for example, the LD source cannot annotate\n * association data if no data was found for that region.\n * @member {boolean}\n */\n this.dependentSource = false;\n};\n\n/**\n * A default constructor that can be used when creating new data sources\n * @param {String|Object} init Basic configuration- either a url, or a config object\n * @param {String} [init.url] The datasource URL\n * @param {String} [init.params] Initial config params for the datasource\n */\nLocusZoom.Data.Source.prototype.parseInit = function(init) {\n if (typeof init === 'string') {\n /** @member {String} */\n this.url = init;\n /** @member {String} */\n this.params = {};\n } else {\n this.url = init.url;\n this.params = init.params || {};\n }\n if (!this.url) {\n throw new Error('Source not initialized with required URL');\n }\n\n};\n\n/**\n * A unique identifier that indicates whether cached data is valid for this request\n * @protected\n * @param state\n * @param chain\n * @param fields\n * @returns {String|undefined}\n */\nLocusZoom.Data.Source.prototype.getCacheKey = function(state, chain, fields) {\n return this.getURL && this.getURL(state, chain, fields);\n};\n\n/**\n * Stub: build the URL for any requests made by this source.\n */\nLocusZoom.Data.Source.prototype.getURL = function(state, chain, fields) { return this.url; };\n\n/**\n * Perform a network request to fetch data for this source\n * @protected\n * @param {Object} state The state of the parent plot\n * @param chain\n * @param fields\n * @returns {Promise}\n */\nLocusZoom.Data.Source.prototype.fetchRequest = function(state, chain, fields) {\n var url = this.getURL(state, chain, fields);\n return LocusZoom.createCORSPromise('GET', url);\n};\n\n/**\n * Gets the data for just this source, typically via a network request (caching where possible)\n * @protected\n */\nLocusZoom.Data.Source.prototype.getRequest = function(state, chain, fields) {\n var req;\n var cacheKey = this.getCacheKey(state, chain, fields);\n if (this.enableCache && typeof(cacheKey) !== 'undefined' && cacheKey === this._cachedKey) {\n req = Promise.resolve(this._cachedResponse); // Resolve to the value of the current promise\n } else {\n req = this.fetchRequest(state, chain, fields);\n if (this.enableCache) {\n this._cachedKey = cacheKey;\n this._cachedResponse = req;\n }\n }\n return req;\n};\n\n/**\n * Fetch the data from the specified data source, and apply transformations requested by an external consumer.\n * This is the public-facing datasource method that will most commonly be called by external code.\n *\n * @public\n * @param {Object} state The current \"state\" of the plot, such as chromosome and start/end positions\n * @param {String[]} fields Array of field names that the plot has requested from this data source. (without the \"namespace\" prefix)\n * @param {String[]} outnames Array describing how the output data should refer to this field. This represents the\n * originally requested field name, including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {function} A callable operation that can be used as part of the data chain\n */\nLocusZoom.Data.Source.prototype.getData = function(state, fields, outnames, trans) {\n if (this.preGetData) {\n var pre = this.preGetData(state, fields, outnames, trans);\n if(this.pre) {\n state = pre.state || state;\n fields = pre.fields || fields;\n outnames = pre.outnames || outnames;\n trans = pre.trans || trans;\n }\n }\n\n var self = this;\n return function (chain) {\n if (self.dependentSource && chain && chain.body && !chain.body.length) {\n // A \"dependent\" source should not attempt to fire a request if there is no data for it to act on.\n // Therefore, it should simply return the previous data chain.\n return Promise.resolve(chain);\n }\n\n return self.getRequest(state, chain, fields).then(function(resp) {\n return self.parseResponse(resp, chain, fields, outnames, trans);\n });\n };\n};\n\n/**\n * Ensure the server response is in a canonical form, an array of one object per record. [ {field: oneval} ].\n * If the server response contains columns, reformats the response from {column1: [], column2: []} to the above.\n *\n * Does not apply namespacing, transformations, or field extraction.\n *\n * May be overridden by data sources that inherently return more complex payloads, or that exist to annotate other\n * sources (eg, if the payload provides extra data rather than a series of records).\n *\n * @param {Object[]|Object} data The original parsed server response\n * @protected\n */\nLocusZoom.Data.Source.prototype.normalizeResponse = function (data) {\n if (Array.isArray(data)) {\n // Already in the desired form\n return data;\n }\n\n // Otherwise, assume the server response is an object representing columns of data.\n // Each array should have the same length (verify), and a given array index corresponds to a single row.\n var keys = Object.keys(data);\n var N = data[keys[0]].length;\n var sameLength = keys.every(function(key) {\n var item = data[key];\n return item.length === N;\n });\n if (!sameLength) {\n throw new Error(this.constructor.SOURCE_NAME + ' expects a response in which all arrays of data are the same length');\n }\n\n // Go down the rows, and create an object for each record\n var records = [];\n var fields = Object.keys(data);\n for(var i = 0; i < N; i++) {\n var record = {};\n for(var j = 0; j < fields.length; j++) {\n record[fields[j]] = data[fields[j]][i];\n }\n records.push(record);\n }\n return records;\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.prepareData = function (records) {\n console.warn('Warning: .prepareData() is deprecated. Use .annotateData() instead');\n return this.annotateData(records);\n};\n\n/**\n * Hook to post-process the data returned by this source with new, additional behavior.\n * (eg cleaning up API values or performing complex calculations on the returned data)\n *\n * @param {Object[]} records The parsed data from the source (eg standardized api response)\n * @param {Object} chain The data chain object. For example, chain.headers may provide useful annotation metadata\n * @returns {Object[]|Promise} The modified set of records\n */\nLocusZoom.Data.Source.prototype.annotateData = function(records, chain) {\n // Default behavior: no transformations\n return records;\n};\n\n/**\n * Clean up the server records for use by datalayers: extract only certain fields, with the specified names.\n * Apply per-field transformations as appropriate.\n *\n * This hook can be overridden, eg to create a source that always returns all records and ignores the \"fields\" array.\n * This is particularly common for sources at the end of a chain- many \"dependent\" sources do not allow\n * cherry-picking individual fields, in which case by **convention** the fields array specifies \"last_source_name:all\"\n *\n * @param {Object[]} data One record object per element\n * @param {String[]} fields The names of fields to extract (as named in the source data). Eg \"afield\"\n * @param {String[]} outnames How to represent the source fields in the output. Eg \"namespace:afield|atransform\"\n * @param {function[]} trans An array of transformation functions (if any). One function per data element, or null.\n * @protected\n */\nLocusZoom.Data.Source.prototype.extractFields = function (data, fields, outnames, trans) {\n //intended for an array of objects\n // [ {\"id\":1, \"val\":5}, {\"id\":2, \"val\":10}]\n // Since a number of sources exist that do not obey this format, we will provide a convenient pass-through\n if (!Array.isArray(data)) {\n return data;\n }\n\n if (!data.length) {\n // Sometimes there are regions that just don't have data- this should not trigger a missing field error message!\n return data;\n }\n\n var fieldFound = [];\n for (var k = 0; k < fields.length; k++) {\n fieldFound[k] = 0;\n }\n\n var records = data.map(function (item) {\n var output_record = {};\n for (var j = 0; j < fields.length; j++) {\n var val = item[fields[j]];\n if (typeof val != 'undefined') {\n fieldFound[j] = 1;\n }\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n output_record[outnames[j]] = val;\n }\n return output_record;\n });\n fieldFound.forEach(function(v, i) {\n if (!v) {throw new Error('field ' + fields[i] + ' not found in response for ' + outnames[i]);}\n });\n return records;\n};\n\n/**\n * Combine records from this source with others in the chain to yield final chain body.\n * Handles merging this data with other sources (if applicable).\n *\n * @param {Object[]} data The data That would be returned from this source alone\n * @param {Object} chain The data chain built up during previous requests\n * @param {String[]} fields\n * @param {String[]} outnames\n * @return {Promise|Object[]} The new chain body\n * @protected\n */\nLocusZoom.Data.Source.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n return data;\n};\n\n/**\n * Coordinates the work of parsing a response and returning records. This is broken into 4 steps, which may be\n * overridden separately for fine-grained control. Each step can return either raw data or a promise.\n *\n * @public\n * @param {String|Object} resp The raw data associated with the response\n * @param {Object} chain The combined parsed response data from this and all other requests made in the chain\n * @param {String[]} fields Array of requested field names (as they would appear in the response payload)\n * @param {String[]} outnames Array of field names as they will be represented in the data returned by this source,\n * including the namespace. This must be an array with the same length as `fields`\n * @param {Function[]} trans The collection of transformation functions to be run on selected fields.\n * This must be an array with the same length as `fields`\n * @returns {Promise|{header: ({}|*), discrete: {}, body: []}} A promise that resolves to an object containing\n * request metadata (headers), the consolidated data for plotting (body), and the individual responses that would be\n * returned by each source in the chain in isolation (discrete)\n */\nLocusZoom.Data.Source.prototype.parseResponse = function(resp, chain, fields, outnames, trans) {\n var source_id = this.source_id || this.constructor.SOURCE_NAME;\n if (!chain.discrete) {\n chain.discrete = {};\n }\n\n if (!resp) {\n // FIXME: Hack. Certain browser issues (such as mixed content warnings) are reported as a successful promise\n // resolution, even though the request was aborted. This is difficult to reliably detect, and is most likely\n // to occur for annotation sources (such as from ExAC). If empty response is received, skip parsing and log.\n // FIXME: Throw an error after pending, eg https://github.com/konradjk/exac_browser/issues/345\n console.error(\"No usable response was returned for source: '\" + source_id + \"'. Parsing will be skipped.\");\n return Promise.resolve(chain);\n }\n\n var json = typeof resp == 'string' ? JSON.parse(resp) : resp;\n\n var self = this;\n // Perform the 4 steps of parsing the payload and return a combined chain object\n return Promise.resolve(self.normalizeResponse(json.data || json))\n .then(function(standardized) {\n // Perform calculations on the data from just this source\n return Promise.resolve(self.annotateData(standardized, chain));\n }).then(function (data) {\n return Promise.resolve(self.extractFields(data, fields, outnames, trans));\n }).then(function (one_source_body) {\n // Store a copy of the data that would be returned by parsing this source in isolation (and taking the\n // fields array into account). This is useful when we want to re-use the source output in many ways.\n chain.discrete[source_id] = one_source_body;\n return Promise.resolve(self.combineChainBody(one_source_body, chain, fields, outnames, trans));\n }).then(function (new_body) {\n return { header: chain.header || {}, discrete: chain.discrete, body: new_body };\n });\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseArraysToObjects = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseArraysToObjects() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseObjectsToObjects = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseObjectsToObjects() is deprecated. Use .extractFields() instead');\n return this.extractFields(data, fields, outnames, trans);\n};\n\n/** @deprecated */\nLocusZoom.Data.Source.prototype.parseData = function(data, fields, outnames, trans) {\n console.warn('Warning: .parseData() is no longer used. A stub is provided for legacy use');\n var standard = this.normalizeResponse(data);\n return this.extractFields(standard, fields, outnames, trans);\n};\n\n/**\n * Method to define new custom datasources based on a provided constructor. (does not allow registering any additional methods)\n * @public\n * @param {Function} constructorFun Constructor function that is used to create the specified class\n * @param {String} [uniqueName] The name by which the class should be listed in `KnownDataSources`\n * @param {String|Function} [base=LocusZoomData.Source] The name or constructor of a base class to use\n * @returns {*|Function}\n */\nLocusZoom.Data.Source.extend = function(constructorFun, uniqueName, base) {\n if (base) {\n if (Array.isArray(base)) {\n base = LocusZoom.KnownDataSources.create.apply(null, base);\n } else if (typeof base === 'string') {\n base = LocusZoom.KnownDataSources.get(base).prototype;\n } else if (typeof base === 'function') {\n base = base.prototype;\n }\n } else {\n base = new LocusZoom.Data.Source();\n }\n constructorFun = constructorFun || function() {};\n constructorFun.prototype = base;\n constructorFun.prototype.constructor = constructorFun;\n if (uniqueName) {\n /** @member {String} LocusZoom.Data.Source.SOURCENAME */\n constructorFun.SOURCE_NAME = uniqueName;\n LocusZoom.KnownDataSources.add(constructorFun);\n }\n return constructorFun;\n};\n\n/**\n * Datasources can be instantiated from a JSON object instead of code. This represents an existing source in that data format.\n * For example, this can be helpful when sharing plots, or to share settings with others when debugging\n *\n * Custom sources with their own parameters may need to re-implement this method\n *\n * @public\n * @returns {Object}\n */\nLocusZoom.Data.Source.prototype.toJSON = function() {\n return [Object.getPrototypeOf(this).constructor.SOURCE_NAME,\n {url:this.url, params:this.params}];\n};\n\n/**\n * Data Source for Association Data, as fetched from the LocusZoom API server (or compatible)\n * @class\n * @public\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.AssociationSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'AssociationLZ');\n\nLocusZoom.Data.AssociationSource.prototype.preGetData = function(state, fields, outnames, trans) {\n var id_field = this.params.id_field || 'id';\n [id_field, 'position'].forEach(function(x) {\n if (fields.indexOf(x) === -1) {\n fields.unshift(x);\n outnames.unshift(x);\n trans.unshift(null);\n }\n });\n return {fields: fields, outnames:outnames, trans:trans};\n};\n\nLocusZoom.Data.AssociationSource.prototype.getURL = function(state, chain, fields) {\n var analysis = chain.header.analysis || this.params.source || this.params.analysis; // Old usages called this param \"analysis\"\n if (typeof analysis == 'undefined') {\n throw new Error('Association source must specify an analysis ID to plot');\n }\n return this.url + 'results/?filter=analysis in ' + analysis +\n \" and chromosome in '\" + state.chr + \"'\" +\n ' and position ge ' + state.start +\n ' and position le ' + state.end;\n};\n\nLocusZoom.Data.AssociationSource.prototype.normalizeResponse = function (data) {\n // Some association sources do not sort their data in a predictable order, which makes it hard to reliably\n // align with other sources (such as LD). For performance reasons, sorting is an opt-in argument.\n // TODO: Consider more fine grained sorting control in the future\n data = LocusZoom.Data.Source.prototype.normalizeResponse.call(this, data);\n if (this.params && this.params.sort && data.length && data[0]['position']) {\n data.sort(function (a, b) { return a['position'] - b['position']; });\n }\n return data;\n};\n\n/**\n * Data Source for LD Data, as fetched from the LocusZoom API server (or compatible)\n * This source is designed to connect its results to association data, and therefore depends on association data having\n * been loaded by a previous request in the data chain.\n *\n * This source is deprecated in favor of a new, standalone LD server. For new usages, see LDLZ2.\n *\n * @class\n * @deprecated\n * @public\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.LDSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n this.dependentSource = true;\n}, 'LDLZ');\n\nLocusZoom.Data.LDSource.prototype.preGetData = function(state, fields) {\n if (fields.length > 1) {\n if (fields.length !== 2 || fields.indexOf('isrefvar') === -1) {\n throw new Error('LD does not know how to get all fields: ' + fields.join(', '));\n }\n }\n};\n\nLocusZoom.Data.LDSource.prototype.findMergeFields = function(chain) {\n // Find the fields (as provided by a previous step in the chain, like an association source) that will be needed to\n // combine LD data with existing information\n\n // Since LD information may be shared across multiple assoc sources with different namespaces,\n // we use regex to find columns to join on, rather than requiring exact matches\n var exactMatch = function(arr) {return function() {\n var regexes = arguments;\n for(var i = 0; i < regexes.length; i++) {\n var regex = regexes[i];\n var m = arr.filter(function(x) {return x.match(regex);});\n if (m.length) {\n return m[0];\n }\n }\n return null;\n };};\n var dataFields = {\n id: this.params.id_field,\n position: this.params.position_field,\n pvalue: this.params.pvalue_field,\n _names_:null\n };\n if (chain && chain.body && chain.body.length > 0) {\n var names = Object.keys(chain.body[0]);\n var nameMatch = exactMatch(names);\n // Internally, fields are generally prefixed with the name of the source they come from.\n // If the user provides an id_field (like `variant`), it should work across data sources( `assoc1:variant`,\n // assoc2:variant), but not match fragments of other field names (assoc1:variant_thing)\n // Note: these lookups hard-code a couple of common fields that will work based on known APIs in the wild\n var id_match = dataFields.id && nameMatch(new RegExp(dataFields.id + '\\\\b'));\n dataFields.id = id_match || nameMatch(/\\bvariant\\b/) || nameMatch(/\\bid\\b/);\n dataFields.position = dataFields.position || nameMatch(/\\bposition\\b/i, /\\bpos\\b/i);\n dataFields.pvalue = dataFields.pvalue || nameMatch(/\\bpvalue\\b/i, /\\blog_pvalue\\b/i);\n dataFields._names_ = names;\n }\n return dataFields;\n};\n\nLocusZoom.Data.LDSource.prototype.findRequestedFields = function(fields, outnames) {\n // Assumption: all usages of this source will only ever ask for \"isrefvar\" or \"state\". This maps to output names.\n var obj = {};\n for(var i = 0; i < fields.length; i++) {\n if(fields[i] === 'isrefvar') {\n obj.isrefvarin = fields[i];\n obj.isrefvarout = outnames && outnames[i];\n } else {\n obj.ldin = fields[i];\n obj.ldout = outnames && outnames[i];\n }\n }\n return obj;\n};\n\nLocusZoom.Data.LDSource.prototype.normalizeResponse = function (data) { return data; };\n\n\n/**\n * Get the LD reference variant, which by default will be the most significant hit in the assoc results\n * This will be used in making the original query to the LD server for pairwise LD information\n * @returns {*|string} The marker id (expected to be in `chr:pos_ref/alt` format) of the reference variant\n */\nLocusZoom.Data.LDSource.prototype.getRefvar = function (state, chain, fields) {\n var findExtremeValue = function(records, pval_field) {\n // Finds the most significant hit (smallest pvalue, or largest -log10p). Will try to auto-detect the appropriate comparison.\n pval_field = pval_field || 'log_pvalue'; // The official LZ API returns log_pvalue\n var is_log = /log/.test(pval_field);\n var cmp;\n if (is_log) {\n cmp = function(a, b) { return a > b; };\n } else {\n cmp = function(a, b) { return a < b; };\n }\n var extremeVal = records[0][pval_field], extremeIdx = 0;\n for(var i = 1; i < records.length; i++) {\n if (cmp(records[i][pval_field], extremeVal)) {\n extremeVal = records[i][pval_field];\n extremeIdx = i;\n }\n }\n return extremeIdx;\n };\n\n var reqFields = this.findRequestedFields(fields);\n var refVar = reqFields.ldin;\n if (refVar === 'state') {\n refVar = state.ldrefvar || chain.header.ldrefvar || 'best';\n }\n if (refVar === 'best') {\n if (!chain.body) {\n throw new Error('No association data found to find best pvalue');\n }\n var keys = this.findMergeFields(chain);\n if (!keys.pvalue || !keys.id) {\n var columns = '';\n if (!keys.id) { columns += (columns.length ? ', ' : '') + 'id'; }\n if (!keys.pvalue) { columns += (columns.length ? ', ' : '') + 'pvalue'; }\n throw new Error('Unable to find necessary column(s) for merge: ' + columns + ' (available: ' + keys._names_ + ')');\n }\n refVar = chain.body[findExtremeValue(chain.body, keys.pvalue)][keys.id];\n }\n return refVar;\n};\n\nLocusZoom.Data.LDSource.prototype.getURL = function(state, chain, fields) {\n var refSource = state.ldrefsource || chain.header.ldrefsource || 1;\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n return this.url + 'results/?filter=reference eq ' + refSource +\n \" and chromosome2 eq '\" + state.chr + \"'\" +\n ' and position2 ge ' + state.start +\n ' and position2 le ' + state.end +\n \" and variant1 eq '\" + refVar + \"'\" +\n '&fields=chr,pos,rsquare';\n};\n\nLocusZoom.Data.LDSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n var keys = this.findMergeFields(chain);\n var reqFields = this.findRequestedFields(fields, outnames);\n if (!keys.position) {\n throw new Error('Unable to find position field for merge: ' + keys._names_);\n }\n var leftJoin = function(left, right, lfield, rfield) {\n var i = 0, j = 0;\n while (i < left.length && j < right.position2.length) {\n if (left[i][keys.position] === right.position2[j]) {\n left[i][lfield] = right[rfield][j];\n i++;\n j++;\n } else if (left[i][keys.position] < right.position2[j]) {\n i++;\n } else {\n j++;\n }\n }\n };\n var tagRefVariant = function(data, refvar, idfield, outrefname, outldname) {\n for(var i = 0; i < data.length; i++) {\n if (data[i][idfield] && data[i][idfield] === refvar) {\n data[i][outrefname] = 1;\n data[i][outldname] = 1; // For label/filter purposes, implicitly mark the ref var as LD=1 to itself\n } else {\n data[i][outrefname] = 0;\n }\n }\n };\n\n // LD servers vary slightly. Some report corr as \"rsquare\", others as \"correlation\"\n var corrField = data.rsquare ? 'rsquare' : 'correlation';\n leftJoin(chain.body, data, reqFields.ldout, corrField);\n if(reqFields.isrefvarin && chain.header.ldrefvar) {\n tagRefVariant(chain.body, chain.header.ldrefvar, keys.id, reqFields.isrefvarout, reqFields.ldout);\n }\n return chain.body;\n};\n\n/**\n * Fetch LD directly from the standalone Portal LD server\n *\n * @class\n * @public\n * @augments LocusZoom.Data.LDSource\n */\nLocusZoom.Data.LDSource2 = LocusZoom.KnownDataSources.extend('LDLZ', 'LDLZ2', {\n getURL: function(state, chain, fields) {\n // Accept the following params in this.params:\n // - method (r, rsquare, cov)\n // - source (aka panel)\n // - population (ALL, AFR, EUR, etc)\n // - build\n // The LD source/pop can be overridden from plot.state for dynamic layouts\n var build = state.genome_build || this.params.build || 'GRCh37';\n var source = state.ld_source || this.params.source || '1000G';\n var population = state.ld_pop || this.params.population || 'ALL'; // LDServer panels will always have an ALL\n var method = this.params.method || 'rsquare';\n\n validateBuildSource(this.constructor.SOURCE_NAME, build, null); // LD doesn't need to validate `source` option\n\n var refVar = this.getRefvar(state, chain, fields);\n chain.header.ldrefvar = refVar;\n\n return [\n this.url, 'genome_builds/', build, '/references/', source, '/populations/', population, '/variants',\n '?correlation=', method,\n '&variant=', encodeURIComponent(refVar),\n '&chrom=', encodeURIComponent(state.chr),\n '&start=', encodeURIComponent(state.start),\n '&stop=', encodeURIComponent(state.end)\n ].join('');\n },\n fetchRequest: function(state, chain, fields) {\n // The API is paginated, but we need all of the data to render a plot. Depaginate and combine where appropriate.\n var url = this.getURL(state, chain, fields);\n var combined = { data: {} };\n var chainRequests = function (url) {\n return LocusZoom.createCORSPromise('GET', url)\n .then(function(payload) {\n payload = JSON.parse(payload);\n Object.keys(payload.data).forEach(function (key) {\n combined.data[key] = (combined.data[key] || []).concat(payload.data[key]);\n });\n if (payload.next) {\n return chainRequests(payload.next);\n }\n return combined;\n });\n };\n\n return chainRequests(url);\n }\n});\n\n/**\n * Data source for GWAS catalogs of known variants\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object|String} init Configuration (URL or object)\n * @param {Object} [init.params] Optional configuration parameters\n * @param {Number} [init.params.source=2] The ID of the chosen catalog. Defaults to EBI GWAS catalog, GRCh37\n * @param {('strict'|'loose')} [init.params.match_type='strict'] Whether to match on exact variant, or just position.\n */\nLocusZoom.Data.GwasCatalog = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n this.dependentSource = true;\n}, 'GwasCatalogLZ');\n\nLocusZoom.Data.GwasCatalog.prototype.getURL = function(state, chain, fields) {\n // This is intended to be aligned with another source- we will assume they are always ordered by position, asc\n // (regardless of the actual match field)\n var build_option = state.genome_build || this.params.build;\n validateBuildSource(this.constructor.SOURCE_NAME, build_option, null); // Source can override build- not mutually exclusive\n\n // Most of our annotations will respect genome build before any other option.\n // But there can be more than one GWAS catalog for the same build, so an explicit config option will always take\n // precedence.\n var default_source = (build_option === 'GRCh38') ? 1 : 2; // EBI GWAS catalog\n var source = this.params.source || default_source;\n return this.url + '?format=objects&sort=pos&filter=id eq ' + source +\n \" and chrom eq '\" + state.chr + \"'\" +\n ' and pos ge ' + state.start +\n ' and pos le ' + state.end;\n};\n\nLocusZoom.Data.GwasCatalog.prototype.findMergeFields = function (records) {\n // Data from previous sources is already namespaced. Find the alignment field by matching.\n var knownFields = Object.keys(records);\n // Note: All API endoints involved only give results for 1 chromosome at a time; match is implied\n var posMatch = knownFields.find(function (item) { return item.match(/\\b(position|pos)\\b/i); });\n\n if (!posMatch) {\n throw new Error('Could not find data to align with GWAS catalog results');\n }\n return { 'pos': posMatch };\n};\n\n// Skip the \"individual field extraction\" step; extraction will be handled when building chain body instead\nLocusZoom.Data.GwasCatalog.prototype.extractFields = function (data, fields, outnames, trans) { return data; };\n\nLocusZoom.Data.GwasCatalog.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data.length) {\n return chain.body;\n }\n\n var decider = 'log_pvalue'; // TODO: Better reuse options in the future\n var decider_out = outnames[fields.indexOf(decider)];\n\n function leftJoin(left, right, fields, outnames, trans) { // Add `fields` from `right` to `left`\n // Add a synthetic, un-namespaced field to all matching records\n var n_matches = left['n_catalog_matches'] || 0;\n left['n_catalog_matches'] = n_matches + 1;\n if (decider && left[decider_out] && left[decider_out] > right[decider]) {\n // There may be more than one GWAS catalog entry for the same SNP. This source is intended for a 1:1\n // annotation scenario, so for now it only joins the catalog entry that has the best -log10 pvalue\n return;\n }\n\n for (var j = 0; j < fields.length; j++) {\n var fn = fields[j];\n var outn = outnames[j];\n\n var val = right[fn];\n if (trans && trans[j]) {\n val = trans[j](val);\n }\n left[outn] = val;\n }\n }\n\n var chainNames = this.findMergeFields(chain.body[0]);\n var catNames = this.findMergeFields(data[0]);\n\n var i = 0, j = 0;\n while (i < chain.body.length && j < data.length) {\n var left = chain.body[i];\n var right = data[j];\n\n if (left[chainNames.pos] === right[catNames.pos]) {\n // There may be multiple catalog entries for each matching SNP; evaluate match one at a time\n leftJoin(left, right, fields, outnames, trans);\n j += 1;\n } else if (left[chainNames.pos] < right[catNames.pos]) {\n i += 1;\n } else {\n j += 1;\n }\n }\n return chain.body;\n};\n\n\n/**\n * Data Source for Gene Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.GeneSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'GeneLZ');\n\nLocusZoom.Data.GeneSource.prototype.getURL = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n\n if (build) { // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = (build === 'GRCh38') ? 1 : 3;\n }\n return this.url + '?filter=source in ' + source +\n \" and chrom eq '\" + state.chr + \"'\" +\n ' and start le ' + state.end +\n ' and end ge ' + state.start;\n};\n\n// Genes have a very complex internal data format. Bypass any record parsing, and provide the data layer with the\n// exact information returned by the API. (ignoring the fields array in the layout)\nLocusZoom.Data.GeneSource.prototype.normalizeResponse = function (data) { return data; };\nLocusZoom.Data.GeneSource.prototype.extractFields = function (data, fields, outnames, trans) { return data; };\n\n/**\n * Data Source for Gene Constraint Data, as fetched from the gnomAD server (or compatible)\n *\n * In the past, this source used ExAC, which has been completely decommissioned. Since the old source referenced a\n * server that no longer exists, this was redefined in 0.11.0 in a backwards-incompatible manner.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n*/\nLocusZoom.Data.GeneConstraintSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'GeneConstraintLZ');\n\nLocusZoom.Data.GeneConstraintSource.prototype.getURL = function() {\n return this.url;\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.normalizeResponse = function (data) { return data; };\n\nLocusZoom.Data.GeneConstraintSource.prototype.getCacheKey = function(state, chain, fields) {\n return this.url + JSON.stringify(state);\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.fetchRequest = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n if (!build) {\n throw new Error(['Data source', this.constructor.SOURCE_NAME, 'requires that you specify a genome_build'].join(' '));\n }\n\n var query = chain.body.map(function (gene) {\n var gene_name = gene.gene_name;\n // GraphQL alias names must match a specific set of allowed characters: https://stackoverflow.com/a/45757065/1422268\n var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_');\n // Each gene is a separate graphQL query, grouped into one request using aliases\n return alias + ': gene(gene_symbol: \"' + gene_name + '\", reference_genome: ' + build + ') { gnomad_constraint { exp_syn obs_syn syn_z oe_syn oe_syn_lower oe_syn_upper exp_mis obs_mis mis_z oe_mis oe_mis_lower oe_mis_upper exp_lof obs_lof pLI oe_lof oe_lof_lower oe_lof_upper } } ';\n });\n\n if (!query.length) {\n // If there are no genes, skip the network request\n return Promise.resolve({ data: null });\n }\n\n query = '{' + query.join(' ') + ' }'; // GraphQL isn't quite JSON; items are separated by spaces but not commas\n var url = this.getURL(state, chain, fields);\n // See: https://graphql.org/learn/serving-over-http/\n var body = JSON.stringify({ query: query });\n var headers = { 'Content-Type': 'application/json' };\n return LocusZoom.createCORSPromise('POST', url, body, headers);\n};\n\nLocusZoom.Data.GeneConstraintSource.prototype.combineChainBody = function (data, chain, fields, outnames, trans) {\n if (!data) {\n return chain;\n }\n\n chain.body.forEach(function(gene) {\n // Find payload keys that match gene names in this response\n var alias = gene.gene_name.replace(/[^A-Za-z0-9_]/g, '_'); // aliases are modified gene names\n var constraint = data[alias] && data[alias]['gnomad_constraint']; // gnomad API has two ways of specifying missing data for a requested gene\n if (constraint) {\n // Add all fields from constraint data- do not override fields present in the gene source\n Object.keys(constraint).forEach(function (key) {\n var val = constraint[key];\n if (typeof gene[key] === 'undefined') {\n if (typeof val == 'number' && val.toString().indexOf('.') !== -1) {\n val = parseFloat(val.toFixed(2));\n }\n gene[key] = val; // These two sources are both designed to bypass namespacing\n }\n });\n }\n });\n return chain.body;\n};\n\n/**\n * Data Source for Recombination Rate Data, as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.RecombinationRateSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'RecombLZ');\n\nLocusZoom.Data.RecombinationRateSource.prototype.getURL = function(state, chain, fields) {\n var build = state.genome_build || this.params.build;\n var source = this.params.source;\n validateBuildSource(this.constructor.SOURCE_NAME, build, source);\n\n if (build) { // If build specified, choose a known Portal API dataset IDs (build 37/38)\n source = (build === 'GRCh38') ? 16 : 15;\n }\n return this.url + '?filter=id in ' + source +\n \" and chromosome eq '\" + state.chr + \"'\" +\n ' and position le ' + state.end +\n ' and position ge ' + state.start;\n};\n\n/**\n * Data Source for Interval Annotation Data (e.g. BED Tracks), as fetched from the LocusZoom API server (or compatible)\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.IntervalSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'IntervalLZ');\n\nLocusZoom.Data.IntervalSource.prototype.getURL = function(state, chain, fields) {\n var source = chain.header.bedtracksource || this.params.source;\n return this.url + '?filter=id in ' + source +\n \" and chromosome eq '\" + state.chr + \"'\" +\n ' and start le ' + state.end +\n ' and end ge ' + state.start;\n};\n\n/**\n * Data Source for static blobs of JSON Data. This does not perform additional parsing, and therefore it is the\n * responsibility of the user to pass information in a format that can be read and understood by the chosen plot.\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n */\nLocusZoom.Data.StaticSource = LocusZoom.Data.Source.extend(function(data) {\n /** @member {Object} */\n this._data = data;\n},'StaticJSON');\n\nLocusZoom.Data.StaticSource.prototype.getRequest = function(state, chain, fields) {\n return Promise.resolve(this._data);\n};\n\nLocusZoom.Data.StaticSource.prototype.toJSON = function() {\n return [Object.getPrototypeOf(this).constructor.SOURCE_NAME, this._data];\n};\n\n/**\n * Data source for PheWAS data\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {String[]} init.params.build This datasource expects to be provided the name of the genome build that will\n * be used to provide pheWAS results for this position. Note positions may not translate between builds.\n */\nLocusZoom.Data.PheWASSource = LocusZoom.Data.Source.extend(function(init) {\n this.parseInit(init);\n}, 'PheWASLZ');\nLocusZoom.Data.PheWASSource.prototype.getURL = function(state, chain, fields) {\n var build = (state.genome_build ? [state.genome_build] : null) || this.params.build;\n if (!build || !Array.isArray(build) || !build.length) {\n throw new Error(['Data source', this.constructor.SOURCE_NAME, 'requires that you specify array of one or more desired genome build names'].join(' '));\n }\n var url = [\n this.url,\n \"?filter=variant eq '\", encodeURIComponent(state.variant), \"'&format=objects&\",\n build.map(function(item) {return 'build=' + encodeURIComponent(item);}).join('&')\n ];\n return url.join('');\n};\n\n/**\n * Base class for \"connectors\"- this is meant to be subclassed, rather than used directly.\n *\n * A connector is a source that makes no server requests and caches no data of its own. Instead, it decides how to\n * combine data from other sources in the chain. Connectors are useful when we want to request (or calculate) some\n * useful piece of information once, but apply it to many different kinds of record types.\n *\n * Typically, a subclass will implement the field merging logic in `combineChainBody`.\n *\n * @public\n * @class\n * @augments LocusZoom.Data.Source\n * @param {Object} init Configuration for this source\n * @param {Object} init.sources Specify how the hard-coded logic should find the data it relies on in the chain,\n * as {internal_name: chain_source_id} pairs. This allows writing a reusable connector that does not need to make\n * assumptions about what namespaces a source is using.\n * @type {*|Function}\n */\nLocusZoom.Data.ConnectorSource = LocusZoom.Data.Source.extend(function(init) {\n if (!init || !init.sources) {\n throw new Error('Connectors must specify the data they require as init.sources = {internal_name: chain_source_id}} pairs');\n }\n\n /**\n * Tells the connector how to find the data it relies on\n *\n * For example, a connector that applies burden test information to the genes layer might specify:\n * {gene_ns: \"gene\", aggregation_ns: \"aggregation\"}\n *\n * @member {Object}\n */\n this._source_name_mapping = init.sources;\n\n // Validate that this source has been told how to find the required information\n var specified_ids = Object.keys(init.sources);\n var self = this;\n this.REQUIRED_SOURCES.forEach(function (k) {\n if (specified_ids.indexOf(k) === -1) {\n throw new Error('Configuration for ' + self.constructor.SOURCE_NAME + ' must specify a source ID corresponding to ' + k);\n }\n });\n this.parseInit(init);\n}, 'ConnectorSource');\n\n/** @property {String[]} Specifies the sources that must be provided in the original config object */\nLocusZoom.Data.ConnectorSource.prototype.REQUIRED_SOURCES = [];\n\nLocusZoom.Data.ConnectorSource.prototype.parseInit = function(init) {}; // Stub\n\nLocusZoom.Data.ConnectorSource.prototype.getRequest = function(state, chain, fields) {\n // Connectors do not request their own data by definition, but they *do* depend on other sources having been loaded\n // first. This method performs basic validation, and preserves the accumulated body from the chain so far.\n var self = this;\n Object.keys(this._source_name_mapping).forEach(function(ns) {\n var chain_source_id = self._source_name_mapping[ns];\n if (chain.discrete && !chain.discrete[chain_source_id]) {\n throw new Error(self.constructor.SOURCE_NAME + ' cannot be used before loading required data for: ' + chain_source_id);\n }\n });\n return Promise.resolve(chain.body || []);\n};\n\nLocusZoom.Data.ConnectorSource.prototype.parseResponse = function(data, chain, fields, outnames, trans) {\n // A connector source does not update chain.discrete, but it may use it. It bypasses data formatting\n // and field selection (both are assumed to have been done already, by the previous sources this draws from)\n\n // Because of how the chain works, connectors are not very good at applying new transformations or namespacing.\n // Typically connectors are called with `connector_name:all` in the fields array.\n return Promise.resolve(this.combineChainBody(data, chain, fields, outnames, trans))\n .then(function(new_body) {\n return {header: chain.header || {}, discrete: chain.discrete || {}, body: new_body};\n });\n};\n\nLocusZoom.Data.ConnectorSource.prototype.combineChainBody = function(records, chain) {\n // Stub method: specifies how to combine the data\n throw new Error('This method must be implemented in a subclass');\n};\n","'use strict';\n\n/**\n * Create a single continuous 2D track that provides information about each datapoint\n *\n * For example, this can be used to color by membership in a group, alongside information in other panels\n *\n * @class LocusZoom.DataLayers.annotation_track\n * @augments LocusZoom.DataLayer\n * @param {Object} layout\n * @param {Object|String} [layout.color]\n * @param {Array[]} An array of filter entries specifying which points to draw annotations for.\n * See `LocusZoom.DataLayer.filter` for details\n */\nLocusZoom.DataLayers.add('annotation_track', function(layout) {\n // In the future we may add additional options for controlling marker size/ shape, based on user feedback\n this.DefaultLayout = {\n color: '#000000',\n filters: [],\n tooltip_positioning: 'middle', // Allowed values: top, middle, bottom\n hit_area_width: 8,\n };\n\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n if (!Array.isArray(layout.filters)) {\n throw new Error('Annotation track must specify array of filters for selecting points to annotate');\n }\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n this.render = function() {\n var self = this;\n // Only render points that currently satisfy all provided filter conditions.\n var trackData = this.filter(this.layout.filters, 'elements');\n\n // Put the containing visible lines before the one containing hit areas, so that the hit areas will be on top.\n var visible_lines_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-visible_lines');\n if (visible_lines_group.size() === 0) {\n visible_lines_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-visible_lines');\n }\n var selection = visible_lines_group.selectAll('rect.lz-data_layer-' + self.layout.type)\n .data(trackData, function (d) { return d[self.layout.id_field]; });\n\n // Draw rectangles (visual and tooltip positioning)\n selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function (d) { return self.getElementId(d); });\n\n var width = 1;\n selection\n .attr('x', function (d) {return self.parent['x_scale'](d[self.layout.x_axis.field]) - width / 2; })\n .attr('width', width)\n .attr('height', self.parent.layout.height)\n .attr('fill', function(d) { return self.resolveScalableParameter(self.layout.color, d); });\n\n // Remove unused elements\n selection.exit()\n .remove();\n\n var hit_areas_group = this.svg.group.select('g.lz-data_layer-' + self.layout.type + '-hit_areas');\n if (hit_areas_group.size() === 0) {\n hit_areas_group = this.svg.group.append('g').attr('class', 'lz-data_layer-' + self.layout.type + '-hit_areas');\n }\n var hit_areas_selection = hit_areas_group.selectAll('rect.lz-data_layer-' + self.layout.type)\n .data(trackData, function (d) { return d[self.layout.id_field]; });\n\n // Add new elements as needed\n hit_areas_selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function (d) { return self.getElementId(d); });\n\n // Update the set of elements to reflect new data\n\n var _getX = function (d, i) { // Helper for position calcs below\n var x_center = self.parent['x_scale'](d[self.layout.x_axis.field]);\n var x_left = x_center - self.layout.hit_area_width / 2;\n if (i >= 1) {\n // This assumes that the data are in sorted order.\n var left_node = trackData[i - 1];\n var left_node_x_center = self.parent['x_scale'](left_node[self.layout.x_axis.field]);\n x_left = Math.max(x_left, (x_center + left_node_x_center) / 2);\n }\n return [x_left, x_center];\n };\n hit_areas_selection\n .attr('height', self.parent.layout.height)\n .attr('opacity', 0)\n .attr('x', function (d, i) {\n var crds = _getX(d,i);\n return crds[0];\n }).attr('width', function (d, i) {\n var crds = _getX(d,i);\n return (crds[1] - crds[0]) + self.layout.hit_area_width / 2;\n });\n\n // Remove unused elements\n hit_areas_selection.exit().remove();\n\n // Set up tooltips and mouse interaction\n this.applyBehaviors(hit_areas_selection);\n };\n\n // Reimplement the positionTooltip() method to be annotation-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var offset = stroke_width / 2;\n var page_origin = this.getPageOrigin();\n\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_center = data_layer_height / 2;\n\n // Tooltip should be horizontally centered above the point to be annotated. (or below if space is limited)\n var offset_right = Math.max((tooltip_box.width / 2) - x_center, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - (tooltip_box.width / 2) - offset_left + offset_right;\n arrow_left = (tooltip_box.width / 2) - (arrow_width) + offset_left - offset_right - offset;\n\n var top_offset = 0;\n switch(this.layout.tooltip_positioning) {\n case 'top':\n arrow_type = 'down';\n break;\n case 'bottom':\n top_offset = data_layer_height;\n arrow_type = 'up';\n break;\n case 'middle':\n default:\n var position = d3.mouse(this.svg.container.node());\n // Position the tooltip so that it does not overlap the mouse pointer\n top_offset = y_center;\n if (position[1] > (data_layer_height / 2)) {\n arrow_type = 'down';\n } else {\n arrow_type = 'up';\n }\n }\n\n if (arrow_type === 'up') {\n top = page_origin.y + top_offset + stroke_width + arrow_width;\n arrow_top = 0 - stroke_width - arrow_width;\n } else if (arrow_type === 'down') {\n top = page_origin.y + top_offset - (tooltip_box.height + stroke_width + arrow_width);\n arrow_top = tooltip_box.height - stroke_width;\n }\n\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n return this;\n});\n","'use strict';\n\n/**\n * Forest Data Layer\n * Implements a standard forest plot. In order to space out points, any layout using this must specify axis ticks\n * and extent in advance.\n *\n * If you are using dynamically fetched data, consider using `category_forest` instead.\n *\n * @class LocusZoom.DataLayers.forest\n */\nLocusZoom.DataLayers.add('forest', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'square',\n color: '#888888',\n fill_opacity: 1,\n y_axis: {\n axis: 2\n },\n id_field: 'id',\n confidence_intervals: {\n start_field: 'ci_start',\n end_field: 'ci_end'\n },\n show_no_significance_line: true\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Reimplement the positionTooltip() method to be forest-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n var offset = Math.sqrt(point_size / Math.PI);\n var left, arrow_type, arrow_left;\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var top, arrow_top;\n if (y_center - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + y_center - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (y_center + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + y_center - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Implement the main render function\n this.render = function() {\n\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n // Generate confidence interval paths if fields are defined\n if (this.layout.confidence_intervals\n && this.layout.fields.indexOf(this.layout.confidence_intervals.start_field) !== -1\n && this.layout.fields.indexOf(this.layout.confidence_intervals.end_field) !== -1) {\n // Generate a selection for all forest plot confidence intervals\n var ci_selection = this.svg.group\n .selectAll('rect.lz-data_layer-forest.lz-data_layer-forest-ci')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n // Create confidence interval rect elements\n ci_selection.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-forest lz-data_layer-forest-ci')\n .attr('id', function(d) { return this.getElementId(d) + '_ci'; }.bind(this))\n .attr('transform', 'translate(0,' + (isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height) + ')');\n // Apply position and size parameters using transition if necessary\n var ci_transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n var ci_width = function(d) {\n return this.parent[x_scale](d[this.layout.confidence_intervals.end_field])\n - this.parent[x_scale](d[this.layout.confidence_intervals.start_field]);\n }.bind(this);\n var ci_height = 1;\n if (this.canTransition()) {\n ci_selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', ci_transform)\n .attr('width', ci_width).attr('height', ci_height);\n } else {\n ci_selection\n .attr('transform', ci_transform)\n .attr('width', ci_width).attr('height', ci_height);\n }\n // Remove old elements as needed\n ci_selection.exit().remove();\n }\n\n // Generate a selection for all forest plot points\n var points_selection = this.svg.group\n .selectAll('path.lz-data_layer-forest.lz-data_layer-forest-point')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n points_selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-forest lz-data_layer-forest-point')\n .attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .attr('transform', 'translate(0,' + initial_y + ')');\n\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n\n var fill = function(d) { return this.resolveScalableParameter(this.layout.color, d); }.bind(this);\n var fill_opacity = function(d) { return this.resolveScalableParameter(this.layout.fill_opacity, d); }.bind(this);\n\n var shape = d3.svg.symbol()\n .size(function(d) { return this.resolveScalableParameter(this.layout.point_size, d); }.bind(this))\n .type(function(d) { return this.resolveScalableParameter(this.layout.point_shape, d); }.bind(this));\n\n // Apply position and color, using a transition if necessary\n if (this.canTransition()) {\n points_selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n } else {\n points_selection\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n }\n\n // Remove old elements as needed\n points_selection.exit().remove();\n\n // Apply default event emitters to selection\n points_selection.on('click.event_emitter', function(element_data) {\n this.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n\n // Apply behaviors to points\n this.applyBehaviors(points_selection);\n };\n return this;\n\n});\n\n/**\n * A y-aligned forest plot in which the y-axis represents item labels, which are dynamically chosen when data is loaded.\n * Each item is assumed to include both data and confidence intervals.\n * This allows generating forest plots without defining the layout in advance.\n *\n * @class LocusZoom.DataLayers.category_forest\n * @augments LocusZoom.DataLayers.forest\n */\nLocusZoom.DataLayers.extend('forest', 'category_forest', {\n _getDataExtent: function(data, axis_config) {\n // In a forest plot, the data range is determined by *three* fields (beta + CI start/end)\n var ci_config = this.layout.confidence_intervals;\n if (ci_config\n && this.layout.fields.indexOf(ci_config.start_field) !== -1\n && this.layout.fields.indexOf(ci_config.end_field) !== -1) {\n var min = function(d) {\n var f = new LocusZoom.Data.Field(ci_config.start_field);\n return +f.resolve(d);\n };\n\n var max = function(d) {\n var f = new LocusZoom.Data.Field(ci_config.end_field);\n return +f.resolve(d);\n };\n\n return [d3.min(data, min), d3.max(data, max)];\n }\n\n // If there are no confidence intervals set, then range must depend only on a single field\n return LocusZoom.DataLayer.prototype._getDataExtent.call(this, data, axis_config);\n },\n\n getTicks: function(dimension, config) { // Overrides parent method\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier' + dimension);\n }\n\n // Design assumption: one axis (y1 or y2) has the ticks, and the layout says which to use\n // Also assumes that every tick gets assigned a unique matching label\n var axis_num = this.layout.y_axis.axis;\n if (dimension === ('y' + axis_num)) {\n var category_field = this.layout.y_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n\n return this.data.map(function (item, index) {\n return {\n y: index + 1,\n text: item[category_field]\n };\n });\n } else {\n return [];\n }\n },\n\n applyCustomDataMethods: function () {\n // Add a synthetic yaxis field to ensure data is spread out on plot. Then, set axis floor and ceiling to\n // correct extents.\n var field_to_add = this.layout.y_axis.field;\n if (!field_to_add) {\n throw new Error('Layout for ' + this.layout.id + ' must specify yaxis.field');\n }\n\n this.data = this.data.map(function (item, index) {\n item[field_to_add] = index + 1;\n return item;\n });\n // Update axis extents based on one label for every point (with a bit of padding above and below)\n this.layout.y_axis.floor = 0;\n this.layout.y_axis.ceiling = this.data.length + 1;\n return this;\n }\n});\n","'use strict';\n\n/*********************\n * Genes Data Layer\n * Implements a data layer that will render gene tracks\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('genes', function(layout) {\n /**\n * Define a default layout for this DataLayer type and merge it with the passed argument\n * @protected\n * @member {Object}\n * */\n this.DefaultLayout = {\n // Optionally specify different fill and stroke properties\n stroke: 'rgb(54, 54, 150)',\n color: '#363696',\n label_font_size: 12,\n label_exon_spacing: 4,\n exon_height: 16,\n bounding_box_padding: 6,\n track_vertical_spacing: 10\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * Generate a statusnode ID for a given element\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function(element) {\n return this.getElementId(element) + '-statusnode';\n };\n\n /**\n * Helper function to sum layout values to derive total height for a single gene track\n * @returns {number}\n */\n this.getTrackHeight = function() {\n return 2 * this.layout.bounding_box_padding\n + this.layout.label_font_size\n + this.layout.label_exon_spacing\n + this.layout.exon_height\n + this.layout.track_vertical_spacing;\n };\n\n /**\n * A gene may have arbitrarily many transcripts, but this data layer isn't set up to render them yet.\n * Stash a transcript_idx to point to the first transcript and use that for all transcript refs.\n * @member {number}\n * @type {number}\n */\n this.transcript_idx = 0;\n\n /**\n * An internal counter for the number of tracks in the data layer. Used as an internal counter for looping\n * over positions / assignments\n * @protected\n * @member {number}\n */\n this.tracks = 1;\n\n /**\n * Store information about genes in dataset, in a hash indexed by track number: {track_number: [gene_indices]}\n * @member {Object.}\n */\n this.gene_track_index = { 1: [] };\n\n /**\n * Ensure that genes in overlapping chromosome regions are positioned so that parts of different genes do not\n * overlap in the view. A track is a row used to vertically separate overlapping genes.\n * @returns {LocusZoom.DataLayer}\n */\n this.assignTracks = function() {\n /**\n * Function to get the width in pixels of a label given the text and layout attributes\n * TODO: Move to outer scope?\n * @param {String} gene_name\n * @param {number|string} font_size\n * @returns {number}\n */\n this.getLabelWidth = function(gene_name, font_size) {\n try {\n var temp_text = this.svg.group.append('text')\n .attr('x', 0).attr('y', 0).attr('class', 'lz-data_layer-genes lz-label')\n .style('font-size', font_size)\n .text(gene_name + '→');\n var label_width = temp_text.node().getBBox().width;\n temp_text.remove();\n return label_width;\n } catch (e) {\n return 0;\n }\n };\n\n // Reinitialize some metadata\n this.tracks = 1;\n this.gene_track_index = { 1: [] };\n\n this.data.map(function(d, g) {\n\n // If necessary, split combined gene id / version fields into discrete fields.\n // NOTE: this may be an issue with CSG's genes data source that may eventually be solved upstream.\n if (this.data[g].gene_id && this.data[g].gene_id.indexOf('.')) {\n var split = this.data[g].gene_id.split('.');\n this.data[g].gene_id = split[0];\n this.data[g].gene_version = split[1];\n }\n\n // Stash the transcript ID on the parent gene\n this.data[g].transcript_id = this.data[g].transcripts[this.transcript_idx].transcript_id;\n\n // Determine display range start and end, based on minimum allowable gene display width, bounded by what we can see\n // (range: values in terms of pixels on the screen)\n this.data[g].display_range = {\n start: this.parent.x_scale(Math.max(d.start, this.state.start)),\n end: this.parent.x_scale(Math.min(d.end, this.state.end))\n };\n this.data[g].display_range.label_width = this.getLabelWidth(this.data[g].gene_name, this.layout.label_font_size);\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n // Determine label text anchor (default to middle)\n this.data[g].display_range.text_anchor = 'middle';\n if (this.data[g].display_range.width < this.data[g].display_range.label_width) {\n if (d.start < this.state.start) {\n this.data[g].display_range.end = this.data[g].display_range.start\n + this.data[g].display_range.label_width\n + this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'start';\n } else if (d.end > this.state.end) {\n this.data[g].display_range.start = this.data[g].display_range.end\n - this.data[g].display_range.label_width\n - this.layout.label_font_size;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n var centered_margin = ((this.data[g].display_range.label_width - this.data[g].display_range.width) / 2)\n + this.layout.label_font_size;\n if ((this.data[g].display_range.start - centered_margin) < this.parent.x_scale(this.state.start)) {\n this.data[g].display_range.start = this.parent.x_scale(this.state.start);\n this.data[g].display_range.end = this.data[g].display_range.start + this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'start';\n } else if ((this.data[g].display_range.end + centered_margin) > this.parent.x_scale(this.state.end)) {\n this.data[g].display_range.end = this.parent.x_scale(this.state.end);\n this.data[g].display_range.start = this.data[g].display_range.end - this.data[g].display_range.label_width;\n this.data[g].display_range.text_anchor = 'end';\n } else {\n this.data[g].display_range.start -= centered_margin;\n this.data[g].display_range.end += centered_margin;\n }\n }\n this.data[g].display_range.width = this.data[g].display_range.end - this.data[g].display_range.start;\n }\n // Add bounding box padding to the calculated display range start, end, and width\n this.data[g].display_range.start -= this.layout.bounding_box_padding;\n this.data[g].display_range.end += this.layout.bounding_box_padding;\n this.data[g].display_range.width += 2 * this.layout.bounding_box_padding;\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[g].display_domain = {\n start: this.parent.x_scale.invert(this.data[g].display_range.start),\n end: this.parent.x_scale.invert(this.data[g].display_range.end)\n };\n this.data[g].display_domain.width = this.data[g].display_domain.end - this.data[g].display_domain.start;\n\n // Using display range/domain data generated above cast each gene to tracks such that none overlap\n this.data[g].track = null;\n var potential_track = 1;\n while (this.data[g].track === null) {\n var collision_on_potential_track = false;\n this.gene_track_index[potential_track].map(function(placed_gene) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_gene.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_gene.display_range.end, this.display_range.end);\n if ((max_end - min_start) < (placed_gene.display_range.width + this.display_range.width)) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[g]));\n if (!collision_on_potential_track) {\n this.data[g].track = potential_track;\n this.gene_track_index[potential_track].push(this.data[g]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.gene_track_index[potential_track] = [];\n }\n }\n }\n\n // Stash parent references on all genes, trascripts, and exons\n this.data[g].parent = this;\n this.data[g].transcripts.map(function(d, t) {\n this.data[g].transcripts[t].parent = this.data[g];\n this.data[g].transcripts[t].exons.map(function(d, e) {\n this.data[g].transcripts[t].exons[e].parent = this.data[g].transcripts[t];\n }.bind(this));\n }.bind(this));\n\n }.bind(this));\n return this;\n };\n\n /**\n * Main render function\n */\n this.render = function() {\n\n var self = this;\n this.assignTracks();\n\n var width, height, x, y;\n\n // Render gene groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-genes')\n .data(this.data, function(d) { return d.gene_name; });\n\n selection.enter().append('g')\n .attr('class', 'lz-data_layer-genes');\n\n selection.attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .each(function(gene) {\n\n var data_layer = gene.parent;\n\n // Render gene bounding boxes (status nodes to show selected/highlighted)\n var bboxes = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-data_layer-genes-statusnode')\n .data([gene], function(d) { return data_layer.getElementStatusNodeId(d); });\n\n bboxes.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-data_layer-genes-statusnode');\n\n bboxes\n .attr('id', function(d) {\n return data_layer.getElementStatusNodeId(d);\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n bboxes\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n bboxes\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n bboxes.exit().remove();\n\n // Render gene boundaries\n var boundary_fill = function(d) { return self.resolveScalableParameter(self.layout.color, d); };\n var boundary_stroke = function(d) { return self.resolveScalableParameter(self.layout.stroke, d); };\n var boundaries = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-boundary')\n .data([gene], function(d) { return d.gene_name + '_boundary'; })\n .style({ fill: boundary_fill, stroke: boundary_stroke });\n\n boundaries.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-boundary');\n\n width = function(d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function() {\n return 1; // TODO: scale dynamically?\n };\n x = function(d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size\n + data_layer.layout.label_exon_spacing\n + (Math.max(data_layer.layout.exon_height, 3) / 2);\n };\n if (data_layer.canTransition()) {\n boundaries\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n boundaries\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n boundaries.exit().remove();\n\n // Render gene labels\n var labels = d3.select(this).selectAll('text.lz-data_layer-genes.lz-label')\n .data([gene], function(d) { return d.gene_name + '_label'; });\n\n labels.enter().append('text')\n .attr('class', 'lz-data_layer-genes lz-label');\n\n labels\n .attr('text-anchor', function(d) {\n return d.display_range.text_anchor;\n })\n .text(function(d) {\n return (d.strand === '+') ? d.gene_name + '→' : '←' + d.gene_name;\n })\n .style('font-size', gene.parent.layout.label_font_size);\n\n x = function(d) {\n if (d.display_range.text_anchor === 'middle') {\n return d.display_range.start + (d.display_range.width / 2);\n } else if (d.display_range.text_anchor === 'start') {\n return d.display_range.start + data_layer.layout.bounding_box_padding;\n } else if (d.display_range.text_anchor === 'end') {\n return d.display_range.end - data_layer.layout.bounding_box_padding;\n }\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size;\n };\n if (data_layer.canTransition()) {\n labels\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('x', x).attr('y', y);\n } else {\n labels\n .attr('x', x).attr('y', y);\n }\n\n labels.exit().remove();\n\n // Render exon rects (first transcript only, for now)\n // Exons: by default color on gene properties for consistency with the gene boundary track- hence color uses d.parent.parent\n var exon_fill = function(d) { return self.resolveScalableParameter(self.layout.color, d.parent.parent); };\n var exon_stroke = function(d) { return self.resolveScalableParameter(self.layout.stroke, d.parent.parent); };\n\n var exons = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-exon')\n .data(gene.transcripts[gene.parent.transcript_idx].exons, function(d) { return d.exon_id; });\n\n exons.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-exon');\n\n exons\n .style({ fill: exon_fill, stroke: exon_stroke });\n\n width = function(d) {\n return data_layer.parent.x_scale(d.end) - data_layer.parent.x_scale(d.start);\n };\n height = function() {\n return data_layer.layout.exon_height;\n };\n x = function(d) {\n return data_layer.parent.x_scale(d.start);\n };\n y = function() {\n return ((gene.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding\n + data_layer.layout.label_font_size\n + data_layer.layout.label_exon_spacing;\n };\n if (data_layer.canTransition()) {\n exons\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n exons\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n exons.exit().remove();\n\n // Render gene click area\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-genes.lz-clickarea')\n .data([gene], function(d) { return d.gene_name + '_clickarea'; });\n\n clickareas.enter().append('rect')\n .attr('class', 'lz-data_layer-genes lz-clickarea');\n\n clickareas\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '_clickarea';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n clickareas\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n // Remove old clickareas as needed\n clickareas.exit().remove();\n\n // Apply default event emitters to clickareas\n clickareas.on('click.event_emitter', function(element) {\n element.parent.parent.emit('element_clicked', element, true);\n });\n\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n\n });\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n /**\n * Reimplement the positionTooltip() method to be gene-specific\n * @param {String} id\n */\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var gene_bbox_id = this.getElementStatusNodeId(tooltip.data);\n var gene_bbox = d3.select('#' + gene_bbox_id).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the gene that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var gene_center_x = ((tooltip.data.display_range.start + tooltip.data.display_range.end) / 2) - (this.layout.bounding_box_padding / 2);\n var offset_right = Math.max((tooltip_box.width / 2) - gene_center_x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + gene_center_x - data_layer_width, 0);\n var left = page_origin.x + gene_center_x - (tooltip_box.width / 2) - offset_left + offset_right;\n var arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right;\n // Position vertically below the gene unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (gene_bbox.y + gene_bbox.height)) {\n top = page_origin.y + gene_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + gene_bbox.y + gene_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n return this;\n\n});\n","'use strict';\n\n/*********************\n Genome Legend Data Layer\n Implements a data layer that will render a genome legend\n*/\n\n// Build a custom data layer for a genome legend\nLocusZoom.DataLayers.add('genome_legend', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n chromosome_fill_colors: {\n light: 'rgb(155, 155, 188)',\n dark: 'rgb(95, 95, 128)'\n },\n chromosome_label_colors: {\n light: 'rgb(120, 120, 186)',\n dark: 'rgb(0, 0, 66)'\n }\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Implement the main render function\n this.render = function() {\n\n // Iterate over data to generate genome-wide start/end values for each chromosome\n var position = 0;\n this.data.forEach(function(d, i) {\n this.data[i].genome_start = position;\n this.data[i].genome_end = position + d['genome:base_pairs'];\n position += d['genome:base_pairs'];\n }.bind(this));\n\n var chromosomes = this.svg.group\n .selectAll('rect.lz-data_layer-genome_legend')\n .data(this.data, function(d) { return d['genome:chr']; });\n\n // Create chromosome elements, apply class\n chromosomes.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-genome_legend');\n\n // Position and fill chromosome rects\n var data_layer = this;\n var panel = this.parent;\n\n chromosomes\n .attr('fill', function(d) { return (d['genome:chr'] % 2 ? data_layer.layout.chromosome_fill_colors.light : data_layer.layout.chromosome_fill_colors.dark); })\n .attr('x', function(d) { return panel.x_scale(d.genome_start); })\n .attr('y', 0)\n .attr('width', function(d) { return panel.x_scale(d['genome:base_pairs']); })\n .attr('height', panel.layout.cliparea.height);\n\n // Remove old elements as needed\n chromosomes.exit().remove();\n\n // Parse current state variant into a position\n // Assumes that variant string is of the format 10:123352136_C/T or 10:123352136\n var variant_parts = /([^:]+):(\\d+)(?:_.*)?/.exec(this.state.variant);\n if (!variant_parts) {\n throw new Error('Genome legend cannot understand the specified variant position');\n }\n var chr = variant_parts[1];\n var offset = variant_parts[2];\n // TODO: How does this handle representation of X or Y chromosomes?\n position = +this.data[chr - 1].genome_start + +offset;\n\n // Render the position\n var region = this.svg.group\n .selectAll('rect.lz-data_layer-genome_legend-marker')\n .data([{ start: position, end: position + 1 }]);\n\n region.enter()\n .append('rect')\n .attr('class', 'lz-data_layer-genome_legend-marker');\n\n region\n .transition()\n .duration(500)\n .style({\n 'fill': 'rgba(255, 250, 50, 0.8)',\n 'stroke': 'rgba(255, 250, 50, 0.8)',\n 'stroke-width': '3px'\n })\n .attr('x', function(d) { return panel.x_scale(d.start); })\n .attr('y', 0)\n .attr('width', function(d) { return panel.x_scale(d.end - d.start); })\n .attr('height', panel.layout.cliparea.height);\n\n region.exit().remove();\n\n };\n\n return this;\n\n});\n","'use strict';\n\n/**\n * Intervals Data Layer\n * Implements a data layer that will render interval annotation tracks (intervals must provide start and end values)\n * @class LocusZoom.DataLayers.intervals\n * @augments LocusZoom.DataLayer\n */\nLocusZoom.DataLayers.add('intervals', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n start_field: 'start',\n end_field: 'end',\n track_split_field: 'state_id',\n track_split_order: 'DESC',\n track_split_legend_to_y_axis: 2,\n split_tracks: true,\n track_height: 15,\n track_vertical_spacing: 3,\n bounding_box_padding: 2,\n always_hide_legend: false,\n color: '#B8B8B8',\n fill_opacity: 1\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * To define shared highlighting on the track split field define the status node id override\n * to generate an ID common to the track when we're actively splitting data out to separate tracks\n * @override\n * @returns {String}\n */\n this.getElementStatusNodeId = function(element) {\n if (this.layout.split_tracks) {\n return (this.getBaseId() + '-statusnode-' + element[this.layout.track_split_field]).replace(/[:.[\\],]/g, '_');\n }\n return this.getElementId(element) + '-statusnode';\n }.bind(this);\n\n // Helper function to sum layout values to derive total height for a single interval track\n this.getTrackHeight = function() {\n return this.layout.track_height\n + this.layout.track_vertical_spacing\n + (2 * this.layout.bounding_box_padding);\n };\n\n this.tracks = 1;\n this.previous_tracks = 1;\n\n // track-number-indexed object with arrays of interval indexes in the dataset\n this.interval_track_index = { 1: [] };\n\n // After we've loaded interval data interpret it to assign\n // each to a track so that they do not overlap in the view\n this.assignTracks = function() {\n\n // Reinitialize some metadata\n this.previous_tracks = this.tracks;\n this.tracks = 0;\n this.interval_track_index = { 1: [] };\n this.track_split_field_index = {};\n\n // If splitting tracks by a field's value then do a first pass determine\n // a value/track mapping that preserves the order of possible values\n if (this.layout.track_split_field && this.layout.split_tracks) {\n this.data.map(function(d) {\n this.track_split_field_index[d[this.layout.track_split_field]] = null;\n }.bind(this));\n var index = Object.keys(this.track_split_field_index);\n if (this.layout.track_split_order === 'DESC') { index.reverse(); }\n index.forEach(function(val) {\n this.track_split_field_index[val] = this.tracks + 1;\n this.interval_track_index[this.tracks + 1] = [];\n this.tracks++;\n }.bind(this));\n }\n\n this.data.map(function(d, i) {\n\n // Stash a parent reference on the interval\n this.data[i].parent = this;\n\n // Determine display range start and end, based on minimum allowable interval display width,\n // bounded by what we can see (range: values in terms of pixels on the screen)\n this.data[i].display_range = {\n start: this.parent.x_scale(Math.max(d[this.layout.start_field], this.state.start)),\n end: this.parent.x_scale(Math.min(d[this.layout.end_field], this.state.end))\n };\n this.data[i].display_range.width = this.data[i].display_range.end - this.data[i].display_range.start;\n\n // Convert and stash display range values into domain values\n // (domain: values in terms of the data set, e.g. megabases)\n this.data[i].display_domain = {\n start: this.parent.x_scale.invert(this.data[i].display_range.start),\n end: this.parent.x_scale.invert(this.data[i].display_range.end)\n };\n this.data[i].display_domain.width = this.data[i].display_domain.end - this.data[i].display_domain.start;\n\n // If splitting to tracks based on the value of the designated track split field\n // then don't bother with collision detection (intervals will be grouped on tracks\n // solely by the value of track_split_field)\n if (this.layout.track_split_field && this.layout.split_tracks) {\n var val = this.data[i][this.layout.track_split_field];\n this.data[i].track = this.track_split_field_index[val];\n this.interval_track_index[this.data[i].track].push(i);\n } else {\n // If not splitting to tracks based on a field value then do so based on collision\n // detection (as how it's done for genes). Use display range/domain data generated\n // above and cast each interval to tracks such that none overlap\n this.tracks = 1;\n this.data[i].track = null;\n var potential_track = 1;\n while (this.data[i].track === null) {\n var collision_on_potential_track = false;\n this.interval_track_index[potential_track].map(function(placed_interval) {\n if (!collision_on_potential_track) {\n var min_start = Math.min(placed_interval.display_range.start, this.display_range.start);\n var max_end = Math.max(placed_interval.display_range.end, this.display_range.end);\n if ((max_end - min_start) < (placed_interval.display_range.width + this.display_range.width)) {\n collision_on_potential_track = true;\n }\n }\n }.bind(this.data[i]));\n if (!collision_on_potential_track) {\n this.data[i].track = potential_track;\n this.interval_track_index[potential_track].push(this.data[i]);\n } else {\n potential_track++;\n if (potential_track > this.tracks) {\n this.tracks = potential_track;\n this.interval_track_index[potential_track] = [];\n }\n }\n }\n\n }\n\n }.bind(this));\n\n return this;\n };\n\n // Implement the main render function\n this.render = function() {\n\n this.assignTracks();\n\n // Remove any shared highlight nodes and re-render them if we're splitting on tracks\n // At most there will only be dozen or so nodes here (one per track) and each time\n // we render data we may have new tracks, so wiping/redrawing all is reasonable.\n this.svg.group.selectAll('.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-shared').remove();\n Object.keys(this.track_split_field_index).forEach(function(key) {\n // Make a psuedo-element so that we can generate an id for the shared node\n var psuedoElement = {};\n psuedoElement[this.layout.track_split_field] = key;\n // Insert the shared node\n var sharedstatusnode_style = {display: (this.layout.split_tracks ? null : 'none')};\n this.svg.group.insert('rect', ':first-child')\n .attr('id', this.getElementStatusNodeId(psuedoElement))\n .attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-shared')\n .attr('rx', this.layout.bounding_box_padding).attr('ry', this.layout.bounding_box_padding)\n .attr('width', this.parent.layout.cliparea.width)\n .attr('height', this.getTrackHeight() - this.layout.track_vertical_spacing)\n .attr('x', 0)\n .attr('y', (this.track_split_field_index[key] - 1) * this.getTrackHeight())\n .style(sharedstatusnode_style);\n }.bind(this));\n\n var width, height, x, y, fill, fill_opacity;\n\n // Render interval groups\n var selection = this.svg.group.selectAll('g.lz-data_layer-intervals')\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n selection.enter().append('g')\n .attr('class', 'lz-data_layer-intervals');\n\n selection.attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .each(function(interval) {\n\n var data_layer = interval.parent;\n\n // Render interval status nodes (displayed behind intervals to show highlight\n // without needing to modify interval display element(s))\n var statusnode_style = {display: (data_layer.layout.split_tracks ? 'none' : null)};\n var statusnodes = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-data_layer-intervals-statusnode.lz-data_layer-intervals-statusnode-discrete')\n .data([interval], function(d) { return data_layer.getElementId(d) + '-statusnode'; });\n statusnodes.enter().insert('rect', ':first-child')\n .attr('class', 'lz-data_layer-intervals lz-data_layer-intervals-statusnode lz-data_layer-intervals-statusnode-discrete');\n statusnodes\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '-statusnode';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .style(statusnode_style);\n width = function(d) {\n return d.display_range.width + (2 * data_layer.layout.bounding_box_padding);\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start - data_layer.layout.bounding_box_padding;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n statusnodes\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n statusnodes\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n statusnodes.exit().remove();\n\n // Render primary interval rects\n var rects = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-interval_rect')\n .data([interval], function(d) { return d[data_layer.layout.id_field] + '_interval_rect'; });\n\n rects.enter().append('rect')\n .attr('class', 'lz-data_layer-intervals lz-interval_rect');\n\n height = data_layer.layout.track_height;\n width = function(d) {\n return d.display_range.width;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight())\n + data_layer.layout.bounding_box_padding;\n };\n fill = function(d) {\n return data_layer.resolveScalableParameter(data_layer.layout.color, d);\n };\n fill_opacity = function(d) {\n return data_layer.resolveScalableParameter(data_layer.layout.fill_opacity, d);\n };\n\n\n if (data_layer.canTransition()) {\n rects\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height)\n .attr('x', x).attr('y', y)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity);\n } else {\n rects\n .attr('width', width).attr('height', height)\n .attr('x', x).attr('y', y)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity);\n }\n\n rects.exit().remove();\n\n // Render interval click areas\n var clickareas = d3.select(this).selectAll('rect.lz-data_layer-intervals.lz-clickarea')\n .data([interval], function(d) { return d.interval_name + '_clickarea'; });\n\n clickareas.enter().append('rect')\n .attr('class', 'lz-data_layer-intervals lz-clickarea');\n\n clickareas\n .attr('id', function(d) {\n return data_layer.getElementId(d) + '_clickarea';\n })\n .attr('rx', function() {\n return data_layer.layout.bounding_box_padding;\n })\n .attr('ry', function() {\n return data_layer.layout.bounding_box_padding;\n });\n\n width = function(d) {\n return d.display_range.width;\n };\n height = function() {\n return data_layer.getTrackHeight() - data_layer.layout.track_vertical_spacing;\n };\n x = function(d) {\n return d.display_range.start;\n };\n y = function(d) {\n return ((d.track - 1) * data_layer.getTrackHeight());\n };\n if (data_layer.canTransition()) {\n clickareas\n .transition()\n .duration(data_layer.layout.transition.duration || 0)\n .ease(data_layer.layout.transition.ease || 'cubic-in-out')\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n } else {\n clickareas\n .attr('width', width).attr('height', height).attr('x', x).attr('y', y);\n }\n\n // Remove old clickareas as needed\n clickareas.exit().remove();\n\n // Apply default event emitters to clickareas\n clickareas.on('click', function(element_data) {\n element_data.parent.parent.emit('element_clicked', element_data, true);\n }.bind(this));\n\n // Apply mouse behaviors to clickareas\n data_layer.applyBehaviors(clickareas);\n\n });\n\n // Remove old elements as needed\n selection.exit().remove();\n\n // Update the legend axis if the number of ticks changed\n if (this.previous_tracks !== this.tracks) {\n this.updateSplitTrackAxis();\n }\n\n return this;\n\n };\n\n // Reimplement the positionTooltip() method to be interval-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var interval_bbox = d3.select('#' + this.getElementStatusNodeId(tooltip.data)).node().getBBox();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n // Position horizontally: attempt to center on the portion of the interval that's visible,\n // pad to either side if bumping up against the edge of the data layer\n var interval_center_x = ((tooltip.data.display_range.start + tooltip.data.display_range.end) / 2) - (this.layout.bounding_box_padding / 2);\n var offset_right = Math.max((tooltip_box.width / 2) - interval_center_x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + interval_center_x - data_layer_width, 0);\n var left = page_origin.x + interval_center_x - (tooltip_box.width / 2) - offset_left + offset_right;\n var arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right;\n // Position vertically below the interval unless there's insufficient space\n var top, arrow_type, arrow_top;\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (interval_bbox.y + interval_bbox.height)) {\n top = page_origin.y + interval_bbox.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + interval_bbox.y + interval_bbox.height + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Redraw split track axis or hide it, and show/hide the legend, as determined\n // by current layout parameters and data\n this.updateSplitTrackAxis = function() {\n var legend_axis = this.layout.track_split_legend_to_y_axis ? 'y' + this.layout.track_split_legend_to_y_axis : false;\n if (this.layout.split_tracks) {\n var tracks = +this.tracks || 0;\n var track_height = +this.layout.track_height || 0;\n var track_spacing = 2 * (+this.layout.bounding_box_padding || 0) + (+this.layout.track_vertical_spacing || 0);\n var target_height = (tracks * track_height) + ((tracks - 1) * track_spacing);\n this.parent.scaleHeightToData(target_height);\n if (legend_axis && this.parent.legend) {\n this.parent.legend.hide();\n this.parent.layout.axes[legend_axis] = {\n render: true,\n ticks: [],\n range: {\n start: (target_height - (this.layout.track_height / 2)),\n end: (this.layout.track_height / 2)\n }\n };\n this.layout.legend.forEach(function(element) {\n var key = element[this.layout.track_split_field];\n var track = this.track_split_field_index[key];\n if (track) {\n if (this.layout.track_split_order === 'DESC') {\n track = Math.abs(track - tracks - 1);\n }\n this.parent.layout.axes[legend_axis].ticks.push({\n y: track,\n text: element.label\n });\n }\n }.bind(this));\n this.layout.y_axis = {\n axis: this.layout.track_split_legend_to_y_axis,\n floor: 1,\n ceiling: tracks\n };\n this.parent.render();\n }\n this.parent_plot.positionPanels();\n } else {\n if (legend_axis && this.parent.legend) {\n if (!this.layout.always_hide_legend) { this.parent.legend.show(); }\n this.parent.layout.axes[legend_axis] = { render: false };\n this.parent.render();\n }\n }\n return this;\n };\n\n // Method to not only toggle the split tracks boolean but also update\n // necessary display values to animate a complete merge/split\n this.toggleSplitTracks = function() {\n this.layout.split_tracks = !this.layout.split_tracks;\n if (this.parent.legend && !this.layout.always_hide_legend) {\n this.parent.layout.margin.bottom = 5 + (this.layout.split_tracks ? 0 : this.parent.legend.layout.height + 5);\n }\n this.render();\n this.updateSplitTrackAxis();\n return this;\n };\n\n return this;\n\n});\n","'use strict';\n\n/*********************\n * Line Data Layer\n * Implements a standard line plot, representing either a trace or a filled curve.\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('line', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n /** @member {Object} */\n this.DefaultLayout = {\n style: {\n fill: 'none',\n 'stroke-width': '2px'\n },\n interpolate: 'linear',\n x_axis: { field: 'x' },\n y_axis: { field: 'y', axis: 1 },\n hitarea_width: 5\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Var for storing mouse events for use in tool tip positioning\n /** @member {String} */\n this.mouse_event = null;\n\n /**\n * Var for storing the generated line function itself\n * @member {d3.svg.line}\n * */\n this.line = null;\n\n /**\n * The timeout identifier returned by setTimeout\n * @member {Number}\n */\n this.tooltip_timeout = null;\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n\n /**\n * Helper function to get display and data objects representing\n * the x/y coordinates of the current mouse event with respect to the line in terms of the display\n * and the interpolated values of the x/y fields with respect to the line\n * @returns {{display: {x: *, y: null}, data: {}, slope: null}}\n */\n this.getMouseDisplayAndData = function() {\n var ret = {\n display: {\n x: d3.mouse(this.mouse_event)[0],\n y: null\n },\n data: {},\n slope: null\n };\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n ret.data[x_field] = this.parent[x_scale].invert(ret.display.x);\n var bisect = d3.bisector(function(datum) { return +datum[x_field]; }).left;\n var index = bisect(this.data, ret.data[x_field]) - 1;\n var startDatum = this.data[index];\n var endDatum = this.data[index + 1];\n var interpolate = d3.interpolateNumber(+startDatum[y_field], +endDatum[y_field]);\n var range = +endDatum[x_field] - +startDatum[x_field];\n ret.data[y_field] = interpolate((ret.data[x_field] % range) / range);\n ret.display.y = this.parent[y_scale](ret.data[y_field]);\n if (this.layout.tooltip.x_precision) {\n ret.data[x_field] = ret.data[x_field].toPrecision(this.layout.tooltip.x_precision);\n }\n if (this.layout.tooltip.y_precision) {\n ret.data[y_field] = ret.data[y_field].toPrecision(this.layout.tooltip.y_precision);\n }\n ret.slope = (this.parent[y_scale](endDatum[y_field]) - this.parent[y_scale](startDatum[y_field]))\n / (this.parent[x_scale](endDatum[x_field]) - this.parent[x_scale](startDatum[x_field]));\n return ret;\n };\n\n /**\n * Reimplement the positionTooltip() method to be line-specific\n * @param {String} id Identify the tooltip to be positioned\n */\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var tooltip = this.tooltips[id];\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var arrow_width = 7; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var stroke_width = parseFloat(this.layout.style['stroke-width']) || 1;\n var page_origin = this.getPageOrigin();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n var top, left, arrow_top, arrow_left, arrow_type;\n\n // Determine x/y coordinates for display and data\n var dd = this.getMouseDisplayAndData();\n\n // If the absolute value of the slope of the line at this point is above 1 (including Infinity)\n // then position the tool tip left/right. Otherwise position top/bottom.\n if (Math.abs(dd.slope) > 1) {\n\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (dd.display.x <= this.parent.layout.width / 2) {\n left = page_origin.x + dd.display.x + stroke_width + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + dd.display.x - tooltip_box.width - stroke_width - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n if (dd.display.y - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + dd.display.y - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (dd.display.y + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + dd.display.y + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + dd.display.y - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n\n } else {\n\n // Position horizontally: attempt to center on the mouse's x coordinate\n // pad to either side if bumping up against the edge of the data layer\n var offset_right = Math.max((tooltip_box.width / 2) - dd.display.x, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + dd.display.x - data_layer_width, 0);\n left = page_origin.x + dd.display.x - (tooltip_box.width / 2) - offset_left + offset_right;\n var min_arrow_left = arrow_width / 2;\n var max_arrow_left = tooltip_box.width - (2.5 * arrow_width);\n arrow_left = (tooltip_box.width / 2) - arrow_width + offset_left - offset_right;\n arrow_left = Math.min(Math.max(arrow_left, min_arrow_left), max_arrow_left);\n\n // Position vertically above the line unless there's insufficient space\n if (tooltip_box.height + stroke_width + arrow_width > dd.display.y) {\n top = page_origin.y + dd.display.y + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n } else {\n top = page_origin.y + dd.display.y - (tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n }\n }\n\n // Apply positions to the main div\n tooltip.selector.style({ left: left + 'px', top: top + 'px' });\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style({ 'left': arrow_left + 'px', top: arrow_top + 'px' });\n\n };\n\n /**\n * Implement the main render function\n */\n this.render = function() {\n\n // Several vars needed to be in scope\n var data_layer = this;\n var panel = this.parent;\n var x_field = this.layout.x_axis.field;\n var y_field = this.layout.y_axis.field;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n // Join data to the line selection\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-line')\n .data([this.data]);\n\n // Create path element, apply class\n this.path = selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line');\n\n // Generate the line\n if (this.layout.style.fill && this.layout.style.fill !== 'none') {\n // Filled curve: define the line as a filled boundary\n this.line = d3.svg.area()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y0(function(d) {return parseFloat(panel[y_scale](0));})\n .y1(function(d) { return parseFloat(panel[y_scale](d[y_field])); });\n } else {\n // Basic line\n this.line = d3.svg.line()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y(function(d) { return parseFloat(panel[y_scale](d[y_field])); })\n .interpolate(this.layout.interpolate);\n }\n\n // Apply line and style\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('d', this.line)\n .style(this.layout.style);\n } else {\n selection\n .attr('d', this.line)\n .style(this.layout.style);\n }\n\n // Apply tooltip, etc\n if (this.layout.tooltip) {\n // Generate an overlaying transparent \"hit area\" line for more intuitive mouse events\n var hitarea_width = parseFloat(this.layout.hitarea_width).toString() + 'px';\n var hitarea = this.svg.group\n .selectAll('path.lz-data_layer-line-hitarea')\n .data([this.data]);\n hitarea.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line-hitarea')\n .style('stroke-width', hitarea_width);\n var hitarea_line = d3.svg.line()\n .x(function(d) { return parseFloat(panel[x_scale](d[x_field])); })\n .y(function(d) { return parseFloat(panel[y_scale](d[y_field])); })\n .interpolate(this.layout.interpolate);\n hitarea\n .attr('d', hitarea_line)\n .on('mouseover', function() {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.createTooltip(dd.data);\n })\n .on('mousemove', function() {\n clearTimeout(data_layer.tooltip_timeout);\n data_layer.mouse_event = this;\n var dd = data_layer.getMouseDisplayAndData();\n data_layer.updateTooltip(dd.data);\n data_layer.positionTooltip(data_layer.getElementId());\n })\n .on('mouseout', function() {\n data_layer.tooltip_timeout = setTimeout(function() {\n data_layer.mouse_event = null;\n data_layer.destroyTooltip(data_layer.getElementId());\n }, 300);\n });\n hitarea.exit().remove();\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n /**\n * Redefine setElementStatus family of methods as line data layers will only ever have a single path element\n * @param {String} status A member of `LocusZoom.DataLayer.Statuses.adjectives`\n * @param {String|Object} element\n * @param {Boolean} toggle\n * @returns {LocusZoom.DataLayer}\n */\n this.setElementStatus = function(status, element, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setElementStatusByFilters = function(status, toggle) {\n return this.setAllElementStatus(status, toggle);\n };\n this.setAllElementStatus = function(status, toggle) {\n // Sanity check\n if (typeof status == 'undefined' || LocusZoom.DataLayer.Statuses.adjectives.indexOf(status) === -1) {\n throw new Error('Invalid status passed to DataLayer.setAllElementStatus()');\n }\n if (typeof this.state[this.state_id][status] == 'undefined') { return this; }\n if (typeof toggle == 'undefined') { toggle = true; }\n\n // Update global status flag\n this.global_statuses[status] = toggle;\n\n // Apply class to path based on global status flags\n var path_class = 'lz-data_layer-line';\n Object.keys(this.global_statuses).forEach(function(global_status) {\n if (this.global_statuses[global_status]) { path_class += ' lz-data_layer-line-' + global_status; }\n }.bind(this));\n this.path.attr('class', path_class);\n\n // Trigger layout changed event hook\n this.parent.emit('layout_changed', true);\n return this;\n };\n\n return this;\n\n});\n\n\n/***************************\n * Orthogonal Line Data Layer\n * Implements a horizontal or vertical line given an orientation and an offset in the layout\n * Does not require a data source\n * @class\n * @augments LocusZoom.DataLayer\n*/\nLocusZoom.DataLayers.add('orthogonal_line', function(layout) {\n\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n style: {\n 'stroke': '#D3D3D3',\n 'stroke-width': '3px',\n 'stroke-dasharray': '10px 10px'\n },\n orientation: 'horizontal',\n x_axis: {\n axis: 1,\n decoupled: true\n },\n y_axis: {\n axis: 1,\n decoupled: true\n },\n offset: 0\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Require that orientation be \"horizontal\" or \"vertical\" only\n if (['horizontal','vertical'].indexOf(layout.orientation) === -1) {\n layout.orientation = 'horizontal';\n }\n\n // Vars for storing the data generated line\n /** @member {Array} */\n this.data = [];\n /** @member {d3.svg.line} */\n this.line = null;\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n /**\n * Implement the main render function\n */\n this.render = function() {\n\n // Several vars needed to be in scope\n var panel = this.parent;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var x_extent = 'x_extent';\n var y_extent = 'y' + this.layout.y_axis.axis + '_extent';\n var x_range = 'x_range';\n\n // Generate data using extents depending on orientation\n if (this.layout.orientation === 'horizontal') {\n this.data = [\n { x: panel[x_extent][0], y: this.layout.offset },\n { x: panel[x_extent][1], y: this.layout.offset }\n ];\n } else if (this.layout.orientation === 'vertical') {\n this.data = [\n { x: this.layout.offset, y: panel[y_extent][0] },\n { x: this.layout.offset, y: panel[y_extent][1] }\n ];\n } else {\n throw new Error('Unrecognized vertical line type. Must be \"vertical\" or \"horizontal\"');\n }\n\n // Join data to the line selection\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-line')\n .data([this.data]);\n\n // Create path element, apply class\n this.path = selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-line');\n\n // In some cases, a vertical line may overlay a track that has no inherent y-values (extent)\n // When that happens, provide a default height based on the current panel dimensions (accounting\n // for any resizing that happened after the panel was created)\n var default_y = [panel.layout.cliparea.height, 0];\n\n // Generate the line\n this.line = d3.svg.line()\n .x(function(d, i) {\n var x = parseFloat(panel[x_scale](d['x']));\n return isNaN(x) ? panel[x_range][i] : x;\n })\n .y(function(d, i) {\n var y = parseFloat(panel[y_scale](d['y']));\n return isNaN(y) ? default_y[i] : y;\n })\n .interpolate('linear');\n\n // Apply line and style\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('d', this.line)\n .style(this.layout.style);\n } else {\n selection\n .attr('d', this.line)\n .style(this.layout.style);\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n };\n\n return this;\n\n});\n","'use strict';\n\n/**\n * Scatter Data Layer\n * Implements a standard scatter plot\n * @class LocusZoom.DataLayers.scatter\n */\nLocusZoom.DataLayers.add('scatter', function(layout) {\n // Define a default layout for this DataLayer type and merge it with the passed argument\n this.DefaultLayout = {\n point_size: 40,\n point_shape: 'circle',\n tooltip_positioning: 'horizontal',\n color: '#888888',\n fill_opacity: 1,\n y_axis: {\n axis: 1\n },\n id_field: 'id'\n };\n layout = LocusZoom.Layouts.merge(layout, this.DefaultLayout);\n\n // Extra default for layout spacing\n // Not in default layout since that would make the label attribute always present\n if (layout.label && isNaN(layout.label.spacing)) {\n layout.label.spacing = 4;\n }\n\n // Apply the arguments to set LocusZoom.DataLayer as the prototype\n LocusZoom.DataLayer.apply(this, arguments);\n\n // Reimplement the positionTooltip() method to be scatter-specific\n this.positionTooltip = function(id) {\n if (typeof id != 'string') {\n throw new Error('Unable to position tooltip: id is not a string');\n }\n if (!this.tooltips[id]) {\n throw new Error('Unable to position tooltip: id does not point to a valid tooltip');\n }\n var top, left, arrow_type, arrow_top, arrow_left;\n var tooltip = this.tooltips[id];\n var point_size = this.resolveScalableParameter(this.layout.point_size, tooltip.data);\n var offset = Math.sqrt(point_size / Math.PI);\n var arrow_width = 7; // as defined in the default stylesheet\n var stroke_width = 1; // as defined in the default stylesheet\n var border_radius = 6; // as defined in the default stylesheet\n var page_origin = this.getPageOrigin();\n var x_center = this.parent.x_scale(tooltip.data[this.layout.x_axis.field]);\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n var y_center = this.parent[y_scale](tooltip.data[this.layout.y_axis.field]);\n var tooltip_box = tooltip.selector.node().getBoundingClientRect();\n var data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n var data_layer_width = this.parent.layout.width - (this.parent.layout.margin.left + this.parent.layout.margin.right);\n if (this.layout.tooltip_positioning === 'vertical') {\n // Position horizontally centered above the point\n var offset_right = Math.max((tooltip_box.width / 2) - x_center, 0);\n var offset_left = Math.max((tooltip_box.width / 2) + x_center - data_layer_width, 0);\n left = page_origin.x + x_center - (tooltip_box.width / 2) - offset_left + offset_right;\n arrow_left = (tooltip_box.width / 2) - (arrow_width / 2) + offset_left - offset_right - offset;\n // Position vertically above the point unless there's insufficient space, then go below\n if (tooltip_box.height + stroke_width + arrow_width > data_layer_height - (y_center + offset)) {\n top = page_origin.y + y_center - (offset + tooltip_box.height + stroke_width + arrow_width);\n arrow_type = 'down';\n arrow_top = tooltip_box.height - stroke_width;\n } else {\n top = page_origin.y + y_center + offset + stroke_width + arrow_width;\n arrow_type = 'up';\n arrow_top = 0 - stroke_width - arrow_width;\n }\n } else {\n // Position horizontally on the left or the right depending on which side of the plot the point is on\n if (x_center <= this.parent.layout.width / 2) {\n left = page_origin.x + x_center + offset + arrow_width + stroke_width;\n arrow_type = 'left';\n arrow_left = -1 * (arrow_width + stroke_width);\n } else {\n left = page_origin.x + x_center - tooltip_box.width - offset - arrow_width - stroke_width;\n arrow_type = 'right';\n arrow_left = tooltip_box.width - stroke_width;\n }\n // Position vertically centered unless we're at the top or bottom of the plot\n data_layer_height = this.parent.layout.height - (this.parent.layout.margin.top + this.parent.layout.margin.bottom);\n if (y_center - (tooltip_box.height / 2) <= 0) { // Too close to the top, push it down\n top = page_origin.y + y_center - (1.5 * arrow_width) - border_radius;\n arrow_top = border_radius;\n } else if (y_center + (tooltip_box.height / 2) >= data_layer_height) { // Too close to the bottom, pull it up\n top = page_origin.y + y_center + arrow_width + border_radius - tooltip_box.height;\n arrow_top = tooltip_box.height - (2 * arrow_width) - border_radius;\n } else { // vertically centered\n top = page_origin.y + y_center - (tooltip_box.height / 2);\n arrow_top = (tooltip_box.height / 2) - arrow_width;\n }\n }\n // Apply positions to the main div\n tooltip.selector.style('left', left + 'px').style('top', top + 'px');\n // Create / update position on arrow connecting tooltip to data\n if (!tooltip.arrow) {\n tooltip.arrow = tooltip.selector.append('div').style('position', 'absolute');\n }\n tooltip.arrow\n .attr('class', 'lz-data_layer-tooltip-arrow_' + arrow_type)\n .style('left', arrow_left + 'px')\n .style('top', arrow_top + 'px');\n };\n\n // Function to flip labels from being anchored at the start of the text to the end\n // Both to keep labels from running outside the data layer and also as a first\n // pass on recursive separation\n this.flip_labels = function() {\n var data_layer = this;\n var point_size = data_layer.resolveScalableParameter(data_layer.layout.point_size, {});\n var spacing = data_layer.layout.label.spacing;\n var handle_lines = Boolean(data_layer.layout.label.lines);\n var min_x = 2 * spacing;\n var max_x = data_layer.parent.layout.width - data_layer.parent.layout.margin.left - data_layer.parent.layout.margin.right - (2 * spacing);\n var flip = function(dn, dnl) {\n var dnx = +dn.attr('x');\n var text_swing = (2 * spacing) + (2 * Math.sqrt(point_size));\n if (handle_lines) {\n var dnlx2 = +dnl.attr('x2');\n var line_swing = spacing + (2 * Math.sqrt(point_size));\n }\n if (dn.style('text-anchor') === 'start') {\n dn.style('text-anchor', 'end');\n dn.attr('x', dnx - text_swing);\n if (handle_lines) { dnl.attr('x2', dnlx2 - line_swing); }\n } else {\n dn.style('text-anchor', 'start');\n dn.attr('x', dnx + text_swing);\n if (handle_lines) { dnl.attr('x2', dnlx2 + line_swing); }\n }\n };\n // Flip any going over the right edge from the right side to the left side\n // (all labels start on the right side)\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n if (dax + abound.width + spacing > max_x) {\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n flip(da, dal);\n }\n });\n // Second pass to flip any others that haven't flipped yet if they collide with another label\n data_layer.label_texts.each(function (d, i) {\n var a = this;\n var da = d3.select(a);\n if (da.style('text-anchor') === 'end') {\n return;\n }\n var dax = +da.attr('x');\n var abound = da.node().getBoundingClientRect();\n var dal = handle_lines ? d3.select(data_layer.label_lines[0][i]) : null;\n data_layer.label_texts.each(function () {\n var b = this;\n var db = d3.select(b);\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + (2 * spacing) &&\n abound.left + abound.width + (2 * spacing) > bbound.left &&\n abound.top < bbound.top + bbound.height + (2 * spacing) &&\n abound.height + abound.top + (2 * spacing) > bbound.top;\n if (collision) {\n flip(da, dal);\n // Double check that this flip didn't push the label past min_x. If it did, immediately flip back.\n dax = +da.attr('x');\n if (dax - abound.width - spacing < min_x) {\n flip(da, dal);\n }\n }\n return;\n });\n });\n };\n\n // Recursive function to space labels apart immediately after initial render\n // Adapted from thudfactor's fiddle here: https://jsfiddle.net/thudfactor/HdwTH/\n // TODO: Make labels also aware of data elements\n this.separate_labels = function() {\n this.seperate_iterations++;\n var data_layer = this;\n var alpha = 0.5;\n if (!this.layout.label) {\n // Guard against layout changing in the midst of iterative rerender\n return;\n }\n var spacing = this.layout.label.spacing;\n var again = false;\n data_layer.label_texts.each(function () {\n var a = this;\n var da = d3.select(a);\n var y1 = da.attr('y');\n data_layer.label_texts.each(function () {\n var b = this;\n // a & b are the same element and don't collide.\n if (a === b) {\n return;\n }\n var db = d3.select(b);\n // a & b are on opposite sides of the chart and\n // don't collide\n if (da.attr('text-anchor') !== db.attr('text-anchor')) {\n return;\n }\n // Determine if the bounding rects for the two text elements collide\n var abound = da.node().getBoundingClientRect();\n var bbound = db.node().getBoundingClientRect();\n var collision = abound.left < bbound.left + bbound.width + (2 * spacing) &&\n abound.left + abound.width + (2 * spacing) > bbound.left &&\n abound.top < bbound.top + bbound.height + (2 * spacing) &&\n abound.height + abound.top + (2 * spacing) > bbound.top;\n if (!collision) {\n return;\n }\n again = true;\n // If the labels collide, we'll push each\n // of the two labels up and down a little bit.\n var y2 = db.attr('y');\n var sign = abound.top < bbound.top ? 1 : -1;\n var adjust = sign * alpha;\n var new_a_y = +y1 - adjust;\n var new_b_y = +y2 + adjust;\n // Keep new values from extending outside the data layer\n var min_y = 2 * spacing;\n var max_y = data_layer.parent.layout.height - data_layer.parent.layout.margin.top - data_layer.parent.layout.margin.bottom - (2 * spacing);\n var delta;\n if (new_a_y - (abound.height / 2) < min_y) {\n delta = +y1 - new_a_y;\n new_a_y = +y1;\n new_b_y += delta;\n } else if (new_b_y - (bbound.height / 2) < min_y) {\n delta = +y2 - new_b_y;\n new_b_y = +y2;\n new_a_y += delta;\n }\n if (new_a_y + (abound.height / 2) > max_y) {\n delta = new_a_y - +y1;\n new_a_y = +y1;\n new_b_y -= delta;\n } else if (new_b_y + (bbound.height / 2) > max_y) {\n delta = new_b_y - +y2;\n new_b_y = +y2;\n new_a_y -= delta;\n }\n da.attr('y',new_a_y);\n db.attr('y',new_b_y);\n });\n });\n if (again) {\n // Adjust lines to follow the labels\n if (data_layer.layout.label.lines) {\n var label_elements = data_layer.label_texts[0];\n data_layer.label_lines.attr('y2',function(d,i) {\n var label_line = d3.select(label_elements[i]);\n return label_line.attr('y');\n });\n }\n // After ~150 iterations we're probably beyond diminising returns, so stop recursing\n if (this.seperate_iterations < 150) {\n setTimeout(function() {\n this.separate_labels();\n }.bind(this), 1);\n }\n }\n };\n\n // Implement the main render function\n this.render = function() {\n\n var data_layer = this;\n var x_scale = 'x_scale';\n var y_scale = 'y' + this.layout.y_axis.axis + '_scale';\n\n if (this.layout.label) {\n // Apply filters to generate a filtered data set\n var filtered_data = this.data.filter(function(d) {\n if (!data_layer.layout.label.filters) {\n return true;\n } else {\n // Start by assuming a match, run through all filters to test if not a match on any one\n var match = true;\n data_layer.layout.label.filters.forEach(function(filter) {\n var field_value = (new LocusZoom.Data.Field(filter.field)).resolve(d);\n if (['!=', '='].indexOf(filter.operator) === -1 && isNaN(field_value)) {\n // If the filter can only be used with numbers, then the value must be numeric.\n match = false;\n } else {\n switch (filter.operator) {\n case '<':\n if (!(field_value < filter.value)) { match = false; }\n break;\n case '<=':\n if (!(field_value <= filter.value)) { match = false; }\n break;\n case '>':\n if (!(field_value > filter.value)) { match = false; }\n break;\n case '>=':\n if (!(field_value >= filter.value)) { match = false; }\n break;\n case '=':\n if (!(field_value === filter.value)) { match = false; }\n break;\n case '!=':\n // Deliberately allow weak comparisons to test for \"anything with a value present\" (null or undefined)\n // eslint-disable-next-line eqeqeq\n if (field_value == filter.value) { match = false; }\n break;\n default:\n // If we got here the operator is not valid, so the filter should fail\n match = false;\n break;\n }\n }\n });\n return match;\n }\n });\n // Render label groups\n var self = this;\n this.label_groups = this.svg.group\n .selectAll('g.lz-data_layer-' + this.layout.type + '-label')\n .data(filtered_data, function(d) { return d[self.layout.id_field] + '_label'; });\n this.label_groups.enter()\n .append('g')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n // Render label texts\n if (this.label_texts) { this.label_texts.remove(); }\n this.label_texts = this.label_groups.append('text')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_texts\n .text(function(d) {\n return LocusZoom.parseFields(d, data_layer.layout.label.text || '');\n })\n .style(data_layer.layout.label.style || {})\n .attr({\n 'x': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field])\n + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d))\n + data_layer.layout.label.spacing;\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n },\n 'text-anchor': function() {\n return 'start';\n }\n });\n // Render label lines\n if (data_layer.layout.label.lines) {\n if (this.label_lines) { this.label_lines.remove(); }\n this.label_lines = this.label_groups.append('line')\n .attr('class', 'lz-data_layer-' + this.layout.type + '-label');\n this.label_lines\n .style(data_layer.layout.label.lines.style || {})\n .attr({\n 'x1': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field]);\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y1': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n },\n 'x2': function(d) {\n var x = data_layer.parent[x_scale](d[data_layer.layout.x_axis.field])\n + Math.sqrt(data_layer.resolveScalableParameter(data_layer.layout.point_size, d))\n + (data_layer.layout.label.spacing / 2);\n if (isNaN(x)) { x = -1000; }\n return x;\n },\n 'y2': function(d) {\n var y = data_layer.parent[y_scale](d[data_layer.layout.y_axis.field]);\n if (isNaN(y)) { y = -1000; }\n return y;\n }\n });\n }\n // Remove labels when they're no longer in the filtered data set\n this.label_groups.exit().remove();\n } else {\n // If the layout definition has changed (& no longer specifies labels), strip any previously rendered\n if (this.label_groups) { this.label_groups.remove(); }\n if (this.label_lines) { this.label_lines.remove(); }\n }\n\n // Generate main scatter data elements\n var selection = this.svg.group\n .selectAll('path.lz-data_layer-' + this.layout.type)\n .data(this.data, function(d) { return d[this.layout.id_field]; }.bind(this));\n\n // Create elements, apply class, ID, and initial position\n var initial_y = isNaN(this.parent.layout.height) ? 0 : this.parent.layout.height;\n selection.enter()\n .append('path')\n .attr('class', 'lz-data_layer-' + this.layout.type)\n .attr('id', function(d) { return this.getElementId(d); }.bind(this))\n .attr('transform', 'translate(0,' + initial_y + ')');\n\n // Generate new values (or functions for them) for position, color, size, and shape\n var transform = function(d) {\n var x = this.parent[x_scale](d[this.layout.x_axis.field]);\n var y = this.parent[y_scale](d[this.layout.y_axis.field]);\n if (isNaN(x)) { x = -1000; }\n if (isNaN(y)) { y = -1000; }\n return 'translate(' + x + ',' + y + ')';\n }.bind(this);\n\n var fill = function(d) { return this.resolveScalableParameter(this.layout.color, d); }.bind(this);\n var fill_opacity = function(d) { return this.resolveScalableParameter(this.layout.fill_opacity, d); }.bind(this);\n\n var shape = d3.svg.symbol()\n .size(function(d) { return this.resolveScalableParameter(this.layout.point_size, d); }.bind(this))\n .type(function(d) { return this.resolveScalableParameter(this.layout.point_shape, d); }.bind(this));\n\n // Apply position and color, using a transition if necessary\n\n if (this.canTransition()) {\n selection\n .transition()\n .duration(this.layout.transition.duration || 0)\n .ease(this.layout.transition.ease || 'cubic-in-out')\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n } else {\n selection\n .attr('transform', transform)\n .attr('fill', fill)\n .attr('fill-opacity', fill_opacity)\n .attr('d', shape);\n }\n\n // Remove old elements as needed\n selection.exit().remove();\n\n // Apply default event emitters to selection\n selection.on('click.event_emitter', function(element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n\n // Apply mouse behaviors\n this.applyBehaviors(selection);\n\n // Apply method to keep labels from overlapping each other\n if (this.layout.label) {\n this.flip_labels();\n this.seperate_iterations = 0;\n this.separate_labels();\n // Apply default event emitters to selection\n this.label_texts.on('click.event_emitter', function(element) {\n this.parent.emit('element_clicked', element, true);\n }.bind(this));\n // Extend mouse behaviors to labels\n this.applyBehaviors(this.label_texts);\n }\n\n };\n\n // Method to set a passed element as the LD reference in the plot-level state\n this.makeLDReference = function(element) {\n var ref = null;\n if (typeof element == 'undefined') {\n throw new Error('makeLDReference requires one argument of any type');\n } else if (typeof element == 'object') {\n if (this.layout.id_field && typeof element[this.layout.id_field] != 'undefined') {\n ref = element[this.layout.id_field].toString();\n } else if (typeof element['id'] != 'undefined') {\n ref = element['id'].toString();\n } else {\n ref = element.toString();\n }\n } else {\n ref = element.toString();\n }\n this.parent_plot.applyState({ ldrefvar: ref });\n };\n\n return this;\n\n});\n\n/**\n * A scatter plot in which the x-axis represents categories, rather than individual positions.\n * For example, this can be used by PheWAS plots to show related groups. This plot allows the categories to be\n * determined dynamically when data is first loaded.\n *\n * @class LocusZoom.DataLayers.category_scatter\n * @augments LocusZoom.DataLayers.scatter\n */\nLocusZoom.DataLayers.extend('scatter', 'category_scatter', {\n /**\n * This plot layer makes certain assumptions about the data passed in. Transform the raw array of records from\n * the datasource to prepare it for plotting, as follows:\n * 1. The scatter plot assumes that all records are given in sequence (pre-grouped by `category_field`)\n * 2. It assumes that all records have an x coordinate for individual plotting\n * @private\n */\n _prepareData: function() {\n var xField = this.layout.x_axis.field || 'x';\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n if (!category_field) {\n throw new Error('Layout for ' + this.layout.id + ' must specify category_field');\n }\n // Sort the data so that things in the same category are adjacent (case-insensitive by specified field)\n var sourceData = this.data\n .sort(function(a, b) {\n var ak = a[category_field];\n var bk = b[category_field];\n var av = (typeof ak === 'string') ? ak.toLowerCase() : ak;\n var bv = (typeof bk === 'string') ? bk.toLowerCase() : bk;\n return (av === bv) ? 0 : (av < bv ? -1 : 1);});\n sourceData.forEach(function(d, i) {\n // Implementation detail: Scatter plot requires specifying an x-axis value, and most datasources do not\n // specify plotting positions. If a point is missing this field, fill in a synthetic value.\n d[xField] = d[xField] || i;\n });\n return sourceData;\n },\n\n /**\n * Identify the unique categories on the plot, and update the layout with an appropriate color scheme.\n * Also identify the min and max x value associated with the category, which will be used to generate ticks\n * @private\n * @returns {Object.} Series of entries used to build category name ticks {category_name: [min_x, max_x]}\n */\n _generateCategoryBounds: function() {\n // TODO: API may return null values in category_field; should we add placeholder category label?\n // The (namespaced) field from `this.data` that will be used to assign datapoints to a given category & color\n var category_field = this.layout.x_axis.category_field;\n var xField = this.layout.x_axis.field || 'x';\n var uniqueCategories = {};\n this.data.forEach(function(item) {\n var category = item[category_field];\n var x = item[xField];\n var bounds = uniqueCategories[category] || [x, x];\n uniqueCategories[category] = [Math.min(bounds[0], x), Math.max(bounds[1], x)];\n });\n\n var categoryNames = Object.keys(uniqueCategories);\n this._setDynamicColorScheme(categoryNames);\n\n return uniqueCategories;\n },\n\n /**\n * This layer relies on defining its own category-based color scheme. Find the correct color config object to\n * be modified.\n * @param [from_source]\n * @returns {Object} A mutable reference to the layout configuration object\n * @private\n */\n _getColorScale: function(from_source) {\n from_source = from_source || this.layout;\n // If the layout does not use a supported coloring scheme, or is already complete, this method should do nothing\n\n // For legacy reasons, layouts can specify color as an object (only one way to set color), as opposed to the\n // preferred mechanism of array (multiple coloring options)\n var color_params = from_source.color || []; // Object or scalar, no other options allowed\n if (Array.isArray(color_params)) {\n color_params = color_params.find(function(item) { return item.scale_function === 'categorical_bin'; });\n }\n if (!color_params || color_params.scale_function !== 'categorical_bin') {\n throw new Error('This layer requires that color options be provided as a `categorical_bin`');\n }\n return color_params;\n },\n\n /**\n * Automatically define a color scheme for the layer based on data returned from the server.\n * If part of the color scheme has been specified, it will fill in remaining missing information.\n *\n * There are three scenarios:\n * 1. The layout does not specify either category names or (color) values. Dynamically build both based on\n * the data and update the layout.\n * 2. The layout specifies colors, but not categories. Use that exact color information provided, and dynamically\n * determine what categories are present in the data. (cycle through the available colors, reusing if there\n * are a lot of categories)\n * 3. The layout specifies exactly what colors and categories to use (and they match the data!). This is useful to\n * specify an explicit mapping between color scheme and category names, when you want to be sure that the\n * plot matches a standard color scheme.\n * (If the layout specifies categories that do not match the data, the user specified categories will be ignored)\n *\n * This method will only act if the layout defines a `categorical_bin` scale function for coloring. It may be\n * overridden in a subclass to suit other types of coloring methods.\n *\n * @param {String[]} categoryNames\n * @private\n */\n _setDynamicColorScheme: function(categoryNames) {\n var colorParams = this._getColorScale(this.layout).parameters;\n var baseParams = this._getColorScale(this._base_layout).parameters;\n\n if (baseParams.categories.length && baseParams.values.length) {\n // If there are preset category/color combos, make sure that they apply to the actual dataset\n var parameters_categories_hash = {};\n baseParams.categories.forEach(function (category) { parameters_categories_hash[category] = 1; });\n if (categoryNames.every(function (name) { return parameters_categories_hash.hasOwnProperty(name); })) {\n // The layout doesn't have to specify categories in order, but make sure they are all there\n colorParams.categories = baseParams.categories;\n } else {\n colorParams.categories = categoryNames;\n }\n } else {\n colorParams.categories = categoryNames;\n }\n // Prefer user-specified colors if provided. Make sure that there are enough colors for all the categories.\n var colors;\n if (baseParams.values.length) {\n colors = baseParams.values;\n } else {\n var color_scale = categoryNames.length <= 10 ? d3.scale.category10 : d3.scale.category20;\n colors = color_scale().range();\n }\n while (colors.length < categoryNames.length) { colors = colors.concat(colors); }\n colors = colors.slice(0, categoryNames.length); // List of hex values, should be of same length as categories array\n colorParams.values = colors;\n },\n\n /**\n *\n * @param dimension\n * @param {Object} [config] Parameters that customize how ticks are calculated (not style)\n * @param {('left'|'center'|'right')} [config.position='left'] Align ticks with the center or edge of category\n * @returns {Array}\n */\n getTicks: function(dimension, config) { // Overrides parent method\n if (['x', 'y1', 'y2'].indexOf(dimension) === -1) {\n throw new Error('Invalid dimension identifier');\n }\n var position = config.position || 'left';\n if (['left', 'center', 'right'].indexOf(position) === -1) {\n throw new Error('Invalid tick position');\n }\n\n var categoryBounds = this._categories;\n if (!categoryBounds || !Object.keys(categoryBounds).length) {\n return [];\n }\n\n if (dimension === 'y') {\n return [];\n }\n\n if (dimension === 'x') {\n // If colors have been defined by this layer, use them to make tick colors match scatterplot point colors\n var colors = this._getColorScale(this.layout);\n var knownCategories = colors.parameters.categories || [];\n var knownColors = colors.parameters.values || [];\n\n return Object.keys(categoryBounds).map(function (category, index) {\n var bounds = categoryBounds[category];\n var xPos;\n\n switch(position) {\n case 'left':\n xPos = bounds[0];\n break;\n case 'center':\n // Center tick under one or many elements as appropriate\n var diff = bounds[1] - bounds[0];\n xPos = bounds[0] + (diff !== 0 ? diff : bounds[0]) / 2;\n break;\n case 'right':\n xPos = bounds[1];\n break;\n }\n return {\n x: xPos,\n text: category,\n style: {\n 'fill': knownColors[knownCategories.indexOf(category)] || '#000000'\n }\n };\n });\n }\n },\n\n applyCustomDataMethods: function() {\n this.data = this._prepareData();\n /**\n * Define category names and extents (boundaries) for plotting. TODO: properties in constructor\n * @member {Object.} Category names and extents, in the form {category_name: [min_x, max_x]}\n */\n this._categories = this._generateCategoryBounds();\n return this;\n }\n});\n","/* global LocusZoom */\n'use strict';\n\n/**\n * An SVG object used to display contextual information about a panel.\n * Panel layouts determine basic features of a legend - its position in the panel, orientation, title, etc.\n * Layouts of child data layers of the panel determine the actual content of the legend.\n *\n * @class\n * @param {LocusZoom.Panel} parent\n*/\nLocusZoom.Legend = function(parent) {\n if (!(parent instanceof LocusZoom.Panel)) {\n throw new Error('Unable to create legend, parent must be a locuszoom panel');\n }\n /** @member {LocusZoom.Panel} */\n this.parent = parent;\n /** @member {String} */\n this.id = this.parent.getBaseId() + '.legend';\n\n this.parent.layout.legend = LocusZoom.Layouts.merge(this.parent.layout.legend || {}, LocusZoom.Legend.DefaultLayout);\n /** @member {Object} */\n this.layout = this.parent.layout.legend;\n\n /** @member {d3.selection} */\n this.selector = null;\n /** @member {d3.selection} */\n this.background_rect = null;\n /** @member {d3.selection[]} */\n this.elements = [];\n /**\n * SVG selector for the group containing all elements in the legend\n * @protected\n * @member {d3.selection|null}\n */\n this.elements_group = null;\n\n /**\n * TODO: Not sure if this property is used; the external-facing methods are setting `layout.hidden` instead. Tentatively mark deprecated.\n * @deprecated\n * @protected\n * @member {Boolean}\n */\n this.hidden = false;\n\n // TODO Revisit constructor return value; see https://stackoverflow.com/a/3350364/1422268\n return this.render();\n};\n\n/**\n * The default layout used by legends (used internally)\n * @protected\n * @member {Object}\n */\nLocusZoom.Legend.DefaultLayout = {\n orientation: 'vertical',\n origin: { x: 0, y: 0 },\n width: 10,\n height: 10,\n padding: 5,\n label_size: 12,\n hidden: false\n};\n\n/**\n * Render the legend in the parent panel\n */\nLocusZoom.Legend.prototype.render = function() {\n\n // Get a legend group selector if not yet defined\n if (!this.selector) {\n this.selector = this.parent.svg.group.append('g')\n .attr('id', this.parent.getBaseId() + '.legend').attr('class', 'lz-legend');\n }\n\n // Get a legend background rect selector if not yet defined\n if (!this.background_rect) {\n this.background_rect = this.selector.append('rect')\n .attr('width', 100).attr('height', 100).attr('class', 'lz-legend-background');\n }\n\n // Get a legend elements group selector if not yet defined\n if (!this.elements_group) {\n this.elements_group = this.selector.append('g');\n }\n\n // Remove all elements from the document and re-render from scratch\n this.elements.forEach(function(element) {\n element.remove();\n });\n this.elements = [];\n\n // Gather all elements from data layers in order (top to bottom) and render them\n var padding = +this.layout.padding || 1;\n var x = padding;\n var y = padding;\n var line_height = 0;\n this.parent.data_layer_ids_by_z_index.slice().reverse().forEach(function(id) {\n if (Array.isArray(this.parent.data_layers[id].layout.legend)) {\n this.parent.data_layers[id].layout.legend.forEach(function(element) {\n var selector = this.elements_group.append('g')\n .attr('transform', 'translate(' + x + ',' + y + ')');\n var label_size = +element.label_size || +this.layout.label_size || 12;\n var label_x = 0;\n var label_y = (label_size / 2) + (padding / 2);\n line_height = Math.max(line_height, label_size + padding);\n // Draw the legend element symbol (line, rect, shape, etc)\n if (element.shape === 'line') {\n // Line symbol\n var length = +element.length || 16;\n var path_y = (label_size / 4) + (padding / 2);\n selector.append('path').attr('class', element.class || '')\n .attr('d', 'M0,' + path_y + 'L' + length + ',' + path_y)\n .style(element.style || {});\n label_x = length + padding;\n } else if (element.shape === 'rect') {\n // Rect symbol\n var width = +element.width || 16;\n var height = +element.height || width;\n selector.append('rect').attr('class', element.class || '')\n .attr('width', width).attr('height', height)\n .attr('fill', element.color || {})\n .style(element.style || {});\n label_x = width + padding;\n line_height = Math.max(line_height, height + padding);\n } else if (d3.svg.symbolTypes.indexOf(element.shape) !== -1) {\n // Shape symbol (circle, diamond, etc.)\n var size = +element.size || 40;\n var radius = Math.ceil(Math.sqrt(size / Math.PI));\n selector.append('path').attr('class', element.class || '')\n .attr('d', d3.svg.symbol().size(size).type(element.shape))\n .attr('transform', 'translate(' + radius + ',' + (radius + (padding / 2)) + ')')\n .attr('fill', element.color || {})\n .style(element.style || {});\n label_x = (2 * radius) + padding;\n label_y = Math.max((2 * radius) + (padding / 2), label_y);\n line_height = Math.max(line_height, (2 * radius) + padding);\n }\n // Draw the legend element label\n selector.append('text').attr('text-anchor', 'left').attr('class', 'lz-label')\n .attr('x', label_x).attr('y', label_y).style({'font-size': label_size}).text(element.label);\n // Position the legend element group based on legend layout orientation\n var bcr = selector.node().getBoundingClientRect();\n if (this.layout.orientation === 'vertical') {\n y += bcr.height + padding;\n line_height = 0;\n } else {\n // Ensure this element does not exceed the panel width\n // (E.g. drop to the next line if it does, but only if it's not the only element on this line)\n var right_x = this.layout.origin.x + x + bcr.width;\n if (x > padding && right_x > this.parent.layout.width) {\n y += line_height;\n x = padding;\n selector.attr('transform', 'translate(' + x + ',' + y + ')');\n }\n x += bcr.width + (3 * padding);\n }\n // Store the element\n this.elements.push(selector);\n }.bind(this));\n }\n }.bind(this));\n\n // Scale the background rect to the elements in the legend\n var bcr = this.elements_group.node().getBoundingClientRect();\n this.layout.width = bcr.width + (2 * this.layout.padding);\n this.layout.height = bcr.height + (2 * this.layout.padding);\n this.background_rect\n .attr('width', this.layout.width)\n .attr('height', this.layout.height);\n\n // Set the visibility on the legend from the \"hidden\" flag\n // TODO: `show()` and `hide()` call a full rerender; might be able to make this more lightweight?\n this.selector.style({ visibility: this.layout.hidden ? 'hidden' : 'visible' });\n\n // TODO: Annotate return type and make consistent\n return this.position();\n};\n\n/**\n * Place the legend in position relative to the panel, as specified in the layout configuration\n * @returns {LocusZoom.Legend | null}\n * TODO: should this always be chainable?\n */\nLocusZoom.Legend.prototype.position = function() {\n if (!this.selector) { return this; }\n var bcr = this.selector.node().getBoundingClientRect();\n if (!isNaN(+this.layout.pad_from_bottom)) {\n this.layout.origin.y = this.parent.layout.height - bcr.height - +this.layout.pad_from_bottom;\n }\n if (!isNaN(+this.layout.pad_from_right)) {\n this.layout.origin.x = this.parent.layout.width - bcr.width - +this.layout.pad_from_right;\n }\n this.selector.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n};\n\n/**\n * Hide the legend (triggers a re-render)\n * @public\n */\nLocusZoom.Legend.prototype.hide = function() {\n this.layout.hidden = true;\n this.render();\n};\n\n/**\n * Show the legend (triggers a re-render)\n * @public\n */\nLocusZoom.Legend.prototype.show = function() {\n this.layout.hidden = false;\n this.render();\n};\n","/* global LocusZoom */\n'use strict';\n\n/**\n * An independent LocusZoom object that renders a unique set of data and subpanels.\n * Many such LocusZoom objects can exist simultaneously on a single page, each having its own layout.\n *\n * This creates a new plot instance, but does not immediately render it. For practical use, it may be more convenient\n * to use the `LocusZoom.populate` helper method.\n *\n * @class\n * @param {String} id The ID of the plot. Often corresponds to the ID of the container element on the page\n * where the plot is rendered..\n * @param {LocusZoom.DataSources} datasource Ensemble of data providers used by the plot\n * @param {Object} layout A JSON-serializable object of layout configuration parameters\n*/\nLocusZoom.Plot = function(id, datasource, layout) {\n /** @member Boolean} */\n this.initialized = false;\n // TODO: This makes sense for all other locuszoom elements to have; determine whether this is interface boilerplate or something that can be removed\n this.parent_plot = this;\n\n /** @member {String} */\n this.id = id;\n\n /** @member {Element} */\n this.container = null;\n /**\n * Selector for a node that will contain the plot. (set externally by populate methods)\n * @member {d3.selection}\n */\n this.svg = null;\n\n /** @member {Object.} */\n this.panels = {};\n /**\n * TODO: This is currently used by external classes that manipulate the parent and may indicate room for a helper method in the api to coordinate boilerplate\n * @protected\n * @member {String[]}\n */\n this.panel_ids_by_y_index = [];\n\n /**\n * Notify each child panel of the plot of changes in panel ordering/ arrangement\n */\n this.applyPanelYIndexesToPanelLayouts = function() {\n this.panel_ids_by_y_index.forEach(function(pid, idx) {\n this.panels[pid].layout.y_index = idx;\n }.bind(this));\n };\n\n /**\n * Get the qualified ID pathname for the plot\n * @returns {String}\n */\n this.getBaseId = function() {\n return this.id;\n };\n\n /**\n * Track update operations (reMap) performed on all child panels, and notify the parent plot when complete\n * TODO: Reconsider whether we need to be tracking this as global state outside of context of specific operations\n * @protected\n * @member {Promise[]}\n */\n this.remap_promises = [];\n\n if (typeof layout == 'undefined') {\n /**\n * The layout is a serializable object used to describe the composition of the Plot\n * If no layout was passed, use the Standard Association Layout\n * Otherwise merge whatever was passed with the Default Layout\n * TODO: Review description; we *always* merge with default layout?\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge({}, LocusZoom.Layouts.get('plot', 'standard_association'));\n } else {\n this.layout = layout;\n }\n LocusZoom.Layouts.merge(this.layout, LocusZoom.Plot.DefaultLayout);\n\n /**\n * Values in the layout object may change during rendering etc. Retain a copy of the original plot state\n * @member {Object}\n */\n this._base_layout = JSON.parse(JSON.stringify(this.layout));\n\n\n /**\n * Create a shortcut to the state in the layout on the Plot. Tracking in the layout allows the plot to be created\n * with initial state/setup.\n *\n * Tracks state of the plot, eg start and end position\n * @member {Object}\n */\n this.state = this.layout.state;\n\n /** @member {LocusZoom.Data.Requester} */\n this.lzd = new LocusZoom.Data.Requester(datasource);\n\n /**\n * Window.onresize listener (responsive layouts only)\n * TODO: .on appears to return a selection, not a listener? Check logic here\n * https://github.com/d3/d3-selection/blob/00b904b9bcec4dfaf154ae0bbc777b1fc1d7bc08/test/selection/on-test.js#L11\n * @deprecated\n * @member {d3.selection}\n */\n this.window_onresize = null;\n\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [], // Select or unselect\n 'element_selection': [], // Element becomes active (only)\n 'match_requested': [], // A data layer is attempting to highlight matching points (internal use only)\n 'panel_removed': [],\n 'state_changed': [] // Only triggered when a state change causes rerender\n };\n\n /**\n * @callback eventCallback\n * @param {object} eventData A description of the event\n * @param {String|null} eventData.sourceID The unique identifier (eg plot or parent name) of the element that\n * triggered the event. Will be automatically filled in if not explicitly provided.\n * @param {Object|null} eventData.context Any additional information to be passed to the callback, eg the data\n * associated with a clicked plot element\n */\n\n /**\n * There are several events that a LocusZoom plot can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following plot-level events are currently supported:\n * - `layout_changed` - context: plot - Any aspect of the plot's layout (including dimensions or state) has changed.\n * - `data_requested` - context: plot - A request for new data from any data source used in the plot has been made.\n * - `data_rendered` - context: plot - Data from a request has been received and rendered in the plot.\n * - `element_clicked` - context: plot - A data element in any of the plot's data layers has been clicked.\n * - `element_selection` - context: plot - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `plot.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * plot itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} hook\n * @returns {function} The registered event listener\n */\n this.on = function(event, hook) {\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Plot}\n */\n this.off = function(event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n * @param {string} event A known event name\n * @param {*} eventData Data or event description that will be passed to the event listener\n * @returns {LocusZoom.Plot}\n */\n this.emit = function(event, eventData) {\n // TODO: there are small differences between the emit implementation between plots and panels. In the future,\n // DRY this code via mixins, and make sure to keep the interfaces compatible when refactoring.\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n var sourceID = this.getBaseId();\n var self = this;\n this.event_hooks[event].forEach(function(hookToRun) {\n var eventContext;\n if (eventData && eventData.sourceID) {\n // If we detect that an event originated elsewhere (via bubbling or externally), preserve the context\n // when re-emitting the event to plot-level listeners\n eventContext = eventData;\n } else {\n eventContext = {sourceID: sourceID, data: eventData || null};\n }\n // By default, any handlers fired here (either directly, or bubbled) will see the plot as the\n // value of `this`. If a bound function is registered as a handler, the previously bound `this` will\n // override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n return this;\n };\n\n /**\n * Get an object with the x and y coordinates of the plot's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the plot\n * @returns {{x: Number, y: Number, width: Number, height: Number}}\n */\n this.getPageOrigin = function() {\n var bounding_client_rect = this.svg.node().getBoundingClientRect();\n var x_offset = document.documentElement.scrollLeft || document.body.scrollLeft;\n var y_offset = document.documentElement.scrollTop || document.body.scrollTop;\n var container = this.svg.node();\n while (container.parentNode !== null) {\n container = container.parentNode;\n if (container !== document && d3.select(container).style('position') !== 'static') {\n x_offset = -1 * container.getBoundingClientRect().left;\n y_offset = -1 * container.getBoundingClientRect().top;\n break;\n }\n }\n return {\n x: x_offset + bounding_client_rect.left,\n y: y_offset + bounding_client_rect.top,\n width: bounding_client_rect.width,\n height: bounding_client_rect.height\n };\n };\n\n /**\n * Get the top and left offset values for the plot's container element (the div that was populated)\n * @returns {{top: number, left: number}}\n */\n this.getContainerOffset = function() {\n var offset = { top: 0, left: 0 };\n var container = this.container.offsetParent || null;\n while (container !== null) {\n offset.top += container.offsetTop;\n offset.left += container.offsetLeft;\n container = container.offsetParent || null;\n }\n return offset;\n };\n\n //\n /**\n * Event information describing interaction (e.g. panning and zooming) is stored on the plot\n * TODO: Add/ document details of interaction structure as we expand\n * @member {{panel_id: String, linked_panel_ids: Array, x_linked: *, dragging: *, zooming: *}}\n * @returns {LocusZoom.Plot}\n */\n this.interaction = {};\n\n /**\n * Track whether the target panel can respond to mouse interaction events\n * @param {String} panel_id\n * @returns {boolean}\n */\n this.canInteract = function(panel_id) {\n panel_id = panel_id || null;\n if (panel_id) {\n return ((typeof this.interaction.panel_id == 'undefined' || this.interaction.panel_id === panel_id) && !this.loading_data);\n } else {\n return !(this.interaction.dragging || this.interaction.zooming || this.loading_data);\n }\n };\n\n // Initialize the layout\n this.initializeLayout();\n return this;\n};\n\n/**\n * Default/ expected configuration parameters for basic plotting; most plots will override\n *\n * @protected\n * @static\n * @type {Object}\n */\nLocusZoom.Plot.DefaultLayout = {\n state: {},\n width: 1,\n height: 1,\n min_width: 1,\n min_height: 1,\n responsive_resize: false, // Allowed values: false, \"width_only\", \"both\" (synonym for true)\n aspect_ratio: 1,\n panels: [],\n dashboard: {\n components: []\n },\n panel_boundaries: true,\n mouse_guide: true\n};\n\n/**\n * Helper method to sum the proportional dimensions of panels, a value that's checked often as panels are added/removed\n * @param {('Height'|'Width')} dimension\n * @returns {number}\n */\nLocusZoom.Plot.prototype.sumProportional = function(dimension) {\n if (dimension !== 'height' && dimension !== 'width') {\n throw new Error('Bad dimension value passed to LocusZoom.Plot.prototype.sumProportional');\n }\n var total = 0;\n for (var id in this.panels) {\n // Ensure every panel contributing to the sum has a non-zero proportional dimension\n if (!this.panels[id].layout['proportional_' + dimension]) {\n this.panels[id].layout['proportional_' + dimension] = 1 / Object.keys(this.panels).length;\n }\n total += this.panels[id].layout['proportional_' + dimension];\n }\n return total;\n};\n\n/**\n * Resize the plot to fit the bounding container\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.rescaleSVG = function() {\n var clientRect = this.svg.node().getBoundingClientRect();\n this.setDimensions(clientRect.width, clientRect.height);\n return this;\n};\n\n/**\n * Prepare the plot for first use by performing parameter validation, setting up panels, and calculating dimensions\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.initializeLayout = function() {\n\n // Sanity check layout values\n if (isNaN(this.layout.width) || this.layout.width <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.height) || this.layout.height <= 0) {\n throw new Error('Plot layout parameter `width` must be a positive number');\n }\n if (isNaN(this.layout.aspect_ratio) || this.layout.aspect_ratio <= 0) {\n throw new Error('Plot layout parameter `aspect_ratio` must be a positive number');\n }\n if (this.layout.responsive_resize === true) {\n // Backwards compatible support\n console.warn('LocusZoom \"responsive_resize\" specifies a deprecated value. The new value should be \"both\". Please update your layout.');\n this.layout.responsive_resize = 'both';\n }\n var RESIZE_MODES = [false, 'both', 'width_only'];\n if (RESIZE_MODES.indexOf(this.layout.responsive_resize) === -1) {\n throw new Error('LocusZoom option \"responsive_resize\" should specify one of the following modes: ' + RESIZE_MODES.join(', '));\n }\n\n // If this is a responsive layout then set a namespaced/unique onresize event listener on the window\n if (this.layout.responsive_resize) {\n this.window_onresize = d3.select(window).on('resize.lz-' + this.id, function() {\n this.rescaleSVG();\n }.bind(this));\n // Forcing one additional setDimensions() call after the page is loaded clears up\n // any disagreements between the initial layout and the loaded responsive container's size\n d3.select(window).on('load.lz-' + this.id, function() {\n this.setDimensions();\n }.bind(this));\n }\n\n // Add panels\n this.layout.panels.forEach(function(panel_layout) {\n this.addPanel(panel_layout);\n }.bind(this));\n\n return this;\n};\n\n/**\n * Set the dimensions for a plot, and ensure that panels are sized and positioned correctly.\n *\n * If dimensions are provided, resizes each panel proportionally to match the new plot dimensions. Otherwise,\n * calculates the appropriate plot dimensions based on all panels.\n * @param {Number} [width] If provided and larger than minimum size, set plot to this width\n * @param {Number} [height] If provided and larger than minimum size, set plot to this height\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.setDimensions = function(width, height) {\n\n var id;\n\n // Update minimum allowable width and height by aggregating minimums from panels, then apply minimums to containing element.\n var min_width = parseFloat(this.layout.min_width) || 0;\n var min_height = parseFloat(this.layout.min_height) || 0;\n for (id in this.panels) {\n min_width = Math.max(min_width, this.panels[id].layout.min_width);\n if (parseFloat(this.panels[id].layout.min_height) > 0 && parseFloat(this.panels[id].layout.proportional_height) > 0) {\n min_height = Math.max(min_height, (this.panels[id].layout.min_height / this.panels[id].layout.proportional_height));\n }\n }\n this.layout.min_width = Math.max(min_width, 1);\n this.layout.min_height = Math.max(min_height, 1);\n d3.select(this.svg.node().parentNode).style({\n 'min-width': this.layout.min_width + 'px',\n 'min-height': this.layout.min_height + 'px'\n });\n\n // If width and height arguments were passed then adjust them against plot minimums if necessary.\n // Then resize the plot and proportionally resize panels to fit inside the new plot dimensions.\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n // Override discrete values if resizing responsively\n if (this.layout.responsive_resize) {\n // All resize modes will affect width\n if (this.svg) {\n this.layout.width = Math.max(this.svg.node().parentNode.getBoundingClientRect().width, this.layout.min_width);\n }\n\n if (this.layout.responsive_resize === 'both') { // Then also change the height\n this.layout.height = this.layout.width / this.layout.aspect_ratio;\n if (this.layout.height < this.layout.min_height) {\n this.layout.height = this.layout.min_height;\n this.layout.width = this.layout.height * this.layout.aspect_ratio;\n }\n }\n }\n // Resize/reposition panels to fit, update proportional origins if necessary\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n var panel_width = this.layout.width;\n var panel_height = this.panels[panel_id].layout.proportional_height * this.layout.height;\n this.panels[panel_id].setDimensions(panel_width, panel_height);\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n this.panels[panel_id].layout.proportional_origin.y = y_offset / this.layout.height;\n y_offset += panel_height;\n this.panels[panel_id].dashboard.update();\n }.bind(this));\n }\n\n // If width and height arguments were NOT passed (and panels exist) then determine the plot dimensions\n // by making it conform to panel dimensions, assuming panels are already positioned correctly.\n else if (Object.keys(this.panels).length) {\n this.layout.width = 0;\n this.layout.height = 0;\n for (id in this.panels) {\n this.layout.width = Math.max(this.panels[id].layout.width, this.layout.width);\n this.layout.height += this.panels[id].layout.height;\n }\n this.layout.width = Math.max(this.layout.width, this.layout.min_width);\n this.layout.height = Math.max(this.layout.height, this.layout.min_height);\n }\n\n // Keep aspect ratio in agreement with dimensions\n this.layout.aspect_ratio = this.layout.width / this.layout.height;\n\n // Apply layout width and height as discrete values or viewbox values\n if (this.svg !== null) {\n if (this.layout.responsive_resize === 'both') {\n this.svg\n .attr('viewBox', '0 0 ' + this.layout.width + ' ' + this.layout.height)\n .attr('preserveAspectRatio', 'xMinYMin meet');\n } else {\n this.svg.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n }\n\n // If the plot has been initialized then trigger some necessary render functions\n if (this.initialized) {\n this.panel_boundaries.position();\n this.dashboard.update();\n this.curtain.update();\n this.loader.update();\n }\n\n return this.emit('layout_changed');\n};\n\n/**\n * Create a new panel from a layout, and handle the work of initializing and placing the panel on the plot\n * @param {Object} layout\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Plot.prototype.addPanel = function(layout) {\n\n // Sanity checks\n if (typeof layout !== 'object') {\n throw new Error('Invalid panel layout passed to LocusZoom.Plot.prototype.addPanel()');\n }\n\n // Create the Panel and set its parent\n var panel = new LocusZoom.Panel(layout, this);\n\n // Store the Panel on the Plot\n this.panels[panel.id] = panel;\n\n // If a discrete y_index was set in the layout then adjust other panel y_index values to accommodate this one\n if (panel.layout.y_index !== null && !isNaN(panel.layout.y_index)\n && this.panel_ids_by_y_index.length > 0) {\n // Negative y_index values should count backwards from the end, so convert negatives to appropriate values here\n if (panel.layout.y_index < 0) {\n panel.layout.y_index = Math.max(this.panel_ids_by_y_index.length + panel.layout.y_index, 0);\n }\n this.panel_ids_by_y_index.splice(panel.layout.y_index, 0, panel.id);\n this.applyPanelYIndexesToPanelLayouts();\n } else {\n var length = this.panel_ids_by_y_index.push(panel.id);\n this.panels[panel.id].layout.y_index = length - 1;\n }\n\n // Determine if this panel was already in the layout.panels array.\n // If it wasn't, add it. Either way store the layout.panels array index on the panel.\n var layout_idx = null;\n this.layout.panels.forEach(function(panel_layout, idx) {\n if (panel_layout.id === panel.id) { layout_idx = idx; }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.panels.push(this.panels[panel.id].layout) - 1;\n }\n this.panels[panel.id].layout_idx = layout_idx;\n\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n this.positionPanels();\n // Initialize and load data into the new panel\n this.panels[panel.id].initialize();\n this.panels[panel.id].reMap();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n\n return this.panels[panel.id];\n};\n\n\n/**\n * Clear all state, tooltips, and other persisted data associated with one (or all) panel(s) in the plot\n *\n * This is useful when reloading an existing plot with new data, eg \"click for genome region\" links.\n * This is a utility method for custom usage. It is not fired automatically during normal rerender of existing panels\n * @param {String} [panelId] If provided, clear state for only this panel. Otherwise, clear state for all panels.\n * @param {('wipe'|'reset')} [mode='wipe'] Optionally specify how state should be cleared. `wipe` deletes all data\n * and is useful for when the panel is being removed; `reset` is best when the panel will be reused in place.\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.clearPanelData = function(panelId, mode) {\n mode = mode || 'wipe';\n\n // TODO: Add unit tests for this method\n var panelsList;\n if (panelId) {\n panelsList = [panelId];\n } else {\n panelsList = Object.keys(this.panels);\n }\n var self = this;\n panelsList.forEach(function(pid) {\n self.panels[pid].data_layer_ids_by_z_index.forEach(function(dlid) {\n var layer = self.panels[pid].data_layers[dlid];\n layer.destroyAllTooltips();\n\n delete self.layout.state[pid + '.' + dlid];\n if(mode === 'reset') {\n layer.setDefaultState();\n }\n });\n });\n return this;\n};\n\n/**\n * Remove the panel from the plot, and clear any state, tooltips, or other visual elements belonging to nested content\n * @param {String} id\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.removePanel = function(id) {\n if (!this.panels[id]) {\n throw new Error('Unable to remove panel, ID not found: ' + id);\n }\n\n // Hide all panel boundaries\n this.panel_boundaries.hide();\n\n // Destroy all tooltips and state vars for all data layers on the panel\n this.clearPanelData(id);\n\n // Remove all panel-level HTML overlay elements\n this.panels[id].loader.hide();\n this.panels[id].dashboard.destroy(true);\n this.panels[id].curtain.hide();\n\n // Remove the svg container for the panel if it exists\n if (this.panels[id].svg.container) {\n this.panels[id].svg.container.remove();\n }\n\n // Delete the panel and its presence in the plot layout and state\n this.layout.panels.splice(this.panels[id].layout_idx, 1);\n delete this.panels[id];\n delete this.layout.state[id];\n\n // Update layout_idx values for all remaining panels\n this.layout.panels.forEach(function(panel_layout, idx) {\n this.panels[panel_layout.id].layout_idx = idx;\n }.bind(this));\n\n // Remove the panel id from the y_index array\n this.panel_ids_by_y_index.splice(this.panel_ids_by_y_index.indexOf(id), 1);\n this.applyPanelYIndexesToPanelLayouts();\n\n // Call positionPanels() to keep panels from overlapping and ensure filling all available vertical space\n if (this.initialized) {\n // Allow the plot to shrink when panels are removed, by forcing it to recalculate min dimensions from scratch\n this.layout.min_height = this._base_layout.min_height;\n this.layout.min_width = this._base_layout.min_width;\n\n this.positionPanels();\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n this.setDimensions(this.layout.width, this.layout.height);\n }\n\n this.emit('panel_removed', id);\n\n return this;\n};\n\n\n/**\n * Automatically position panels based on panel positioning rules and values.\n * Keep panels from overlapping vertically by adjusting origins, and keep the sum of proportional heights at 1.\n *\n * TODO: This logic currently only supports dynamic positioning of panels to prevent overlap in a VERTICAL orientation.\n * Some framework exists for positioning panels in horizontal orientations as well (width, proportional_width, origin.x, etc.)\n * but the logic for keeping these user-definable values straight approaches the complexity of a 2D box-packing algorithm.\n * That's complexity we don't need right now, and may not ever need, so it's on hiatus until a use case materializes.\n */\nLocusZoom.Plot.prototype.positionPanels = function() {\n\n var id;\n\n // We want to enforce that all x-linked panels have consistent horizontal margins\n // (to ensure that aligned items stay aligned despite inconsistent initial layout parameters)\n // NOTE: This assumes panels have consistent widths already. That should probably be enforced too!\n var x_linked_margins = { left: 0, right: 0 };\n\n // Proportional heights for newly added panels default to null unless explicitly set, so determine appropriate\n // proportional heights for all panels with a null value from discretely set dimensions.\n // Likewise handle default nulls for proportional widths, but instead just force a value of 1 (full width)\n for (id in this.panels) {\n if (this.panels[id].layout.proportional_height === null) {\n this.panels[id].layout.proportional_height = this.panels[id].layout.height / this.layout.height;\n }\n if (this.panels[id].layout.proportional_width === null) {\n this.panels[id].layout.proportional_width = 1;\n }\n if (this.panels[id].layout.interaction.x_linked) {\n x_linked_margins.left = Math.max(x_linked_margins.left, this.panels[id].layout.margin.left);\n x_linked_margins.right = Math.max(x_linked_margins.right, this.panels[id].layout.margin.right);\n }\n }\n\n // Sum the proportional heights and then adjust all proportionally so that the sum is exactly 1\n var total_proportional_height = this.sumProportional('height');\n if (!total_proportional_height) {\n return this;\n }\n var proportional_adjustment = 1 / total_proportional_height;\n for (id in this.panels) {\n this.panels[id].layout.proportional_height *= proportional_adjustment;\n }\n\n // Update origins on all panels without changing plot-level dimensions yet\n // Also apply x-linked margins to x-linked panels, updating widths as needed\n var y_offset = 0;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].setOrigin(0, y_offset);\n this.panels[panel_id].layout.proportional_origin.x = 0;\n y_offset += this.panels[panel_id].layout.height;\n if (this.panels[panel_id].layout.interaction.x_linked) {\n var delta = Math.max(x_linked_margins.left - this.panels[panel_id].layout.margin.left, 0)\n + Math.max(x_linked_margins.right - this.panels[panel_id].layout.margin.right, 0);\n this.panels[panel_id].layout.width += delta;\n this.panels[panel_id].layout.margin.left = x_linked_margins.left;\n this.panels[panel_id].layout.margin.right = x_linked_margins.right;\n this.panels[panel_id].layout.cliparea.origin.x = x_linked_margins.left;\n }\n }.bind(this));\n var calculated_plot_height = y_offset;\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].layout.proportional_origin.y = this.panels[panel_id].layout.origin.y / calculated_plot_height;\n }.bind(this));\n\n // Update dimensions on the plot to accommodate repositioned panels\n this.setDimensions();\n\n // Set dimensions on all panels using newly set plot-level dimensions and panel-level proportional dimensions\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n this.panels[panel_id].setDimensions(this.layout.width * this.panels[panel_id].layout.proportional_width,\n this.layout.height * this.panels[panel_id].layout.proportional_height);\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Prepare the first rendering of the plot. This includes initializing the individual panels, but also creates shared\n * elements such as mouse events, panel guides/boundaries, and loader/curtain.\n *\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.initialize = function() {\n\n // Ensure proper responsive class is present on the containing node if called for\n if (this.layout.responsive_resize) {\n d3.select(this.container).classed('lz-container-responsive', true);\n }\n\n // Create an element/layer for containing mouse guides\n if (this.layout.mouse_guide) {\n var mouse_guide_svg = this.svg.append('g')\n .attr('class', 'lz-mouse_guide').attr('id', this.id + '.mouse_guide');\n var mouse_guide_vertical_svg = mouse_guide_svg.append('rect')\n .attr('class', 'lz-mouse_guide-vertical').attr('x',-1);\n var mouse_guide_horizontal_svg = mouse_guide_svg.append('rect')\n .attr('class', 'lz-mouse_guide-horizontal').attr('y',-1);\n this.mouse_guide = {\n svg: mouse_guide_svg,\n vertical: mouse_guide_vertical_svg,\n horizontal: mouse_guide_horizontal_svg\n };\n }\n\n // Add curtain and loader prototpyes to the plot\n this.curtain = LocusZoom.generateCurtain.call(this);\n this.loader = LocusZoom.generateLoader.call(this);\n\n // Create the panel_boundaries object with show/position/hide methods\n this.panel_boundaries = {\n parent: this,\n hide_timeout: null,\n showing: false,\n dragging: false,\n selectors: [],\n corner_selector: null,\n show: function() {\n // Generate panel boundaries\n if (!this.showing && !this.parent.curtain.showing) {\n this.showing = true;\n // Loop through all panels to create a horizontal boundary for each\n this.parent.panel_ids_by_y_index.forEach(function(panel_id, panel_idx) {\n var selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip')\n .attr('class', 'lz-panel-boundary')\n .attr('title', 'Resize panel');\n selector.append('span');\n var panel_resize_drag = d3.behavior.drag();\n panel_resize_drag.on('dragstart', function() { this.dragging = true; }.bind(this));\n panel_resize_drag.on('dragend', function() { this.dragging = false; }.bind(this));\n panel_resize_drag.on('drag', function() {\n // First set the dimensions on the panel we're resizing\n var this_panel = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]];\n var original_panel_height = this_panel.layout.height;\n this_panel.setDimensions(this_panel.layout.width, this_panel.layout.height + d3.event.dy);\n var panel_height_change = this_panel.layout.height - original_panel_height;\n var new_calculated_plot_height = this.parent.layout.height + panel_height_change;\n // Next loop through all panels.\n // Update proportional dimensions for all panels including the one we've resized using discrete heights.\n // Reposition panels with a greater y-index than this panel to their appropriate new origin.\n this.parent.panel_ids_by_y_index.forEach(function(loop_panel_id, loop_panel_idx) {\n var loop_panel = this.parent.panels[this.parent.panel_ids_by_y_index[loop_panel_idx]];\n loop_panel.layout.proportional_height = loop_panel.layout.height / new_calculated_plot_height;\n if (loop_panel_idx > panel_idx) {\n loop_panel.setOrigin(loop_panel.layout.origin.x, loop_panel.layout.origin.y + panel_height_change);\n loop_panel.dashboard.position();\n }\n }.bind(this));\n // Reset dimensions on the entire plot and reposition panel boundaries\n this.parent.positionPanels();\n this.position();\n }.bind(this));\n selector.call(panel_resize_drag);\n this.parent.panel_boundaries.selectors.push(selector);\n }.bind(this));\n // Create a corner boundary / resize element on the bottom-most panel that resizes the entire plot\n var corner_selector = d3.select(this.parent.svg.node().parentNode).insert('div', '.lz-data_layer-tooltip')\n .attr('class', 'lz-panel-corner-boundary')\n .attr('title', 'Resize plot');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-outer');\n corner_selector.append('span').attr('class', 'lz-panel-corner-boundary-inner');\n var corner_drag = d3.behavior.drag();\n corner_drag.on('dragstart', function() { this.dragging = true; }.bind(this));\n corner_drag.on('dragend', function() { this.dragging = false; }.bind(this));\n corner_drag.on('drag', function() {\n this.setDimensions(this.layout.width + d3.event.dx, this.layout.height + d3.event.dy);\n }.bind(this.parent));\n corner_selector.call(corner_drag);\n this.parent.panel_boundaries.corner_selector = corner_selector;\n }\n return this.position();\n },\n position: function() {\n if (!this.showing) { return this; }\n // Position panel boundaries\n var plot_page_origin = this.parent.getPageOrigin();\n this.selectors.forEach(function(selector, panel_idx) {\n var panel_page_origin = this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].getPageOrigin();\n var left = plot_page_origin.x;\n var top = panel_page_origin.y + this.parent.panels[this.parent.panel_ids_by_y_index[panel_idx]].layout.height - 12;\n var width = this.parent.layout.width - 1;\n selector.style({\n top: top + 'px',\n left: left + 'px',\n width: width + 'px'\n });\n selector.select('span').style({\n width: width + 'px'\n });\n }.bind(this));\n // Position corner selector\n var corner_padding = 10;\n var corner_size = 16;\n this.corner_selector.style({\n top: (plot_page_origin.y + this.parent.layout.height - corner_padding - corner_size) + 'px',\n left: (plot_page_origin.x + this.parent.layout.width - corner_padding - corner_size) + 'px'\n });\n return this;\n },\n hide: function() {\n if (!this.showing) { return this; }\n this.showing = false;\n // Remove panel boundaries\n this.selectors.forEach(function(selector) { selector.remove(); });\n this.selectors = [];\n // Remove corner boundary\n this.corner_selector.remove();\n this.corner_selector = null;\n return this;\n }\n };\n\n // Show panel boundaries stipulated by the layout (basic toggle, only show on mouse over plot)\n if (this.layout.panel_boundaries) {\n d3.select(this.svg.node().parentNode).on('mouseover.' + this.id + '.panel_boundaries', function() {\n clearTimeout(this.panel_boundaries.hide_timeout);\n this.panel_boundaries.show();\n }.bind(this));\n d3.select(this.svg.node().parentNode).on('mouseout.' + this.id + '.panel_boundaries', function() {\n this.panel_boundaries.hide_timeout = setTimeout(function() {\n this.panel_boundaries.hide();\n }.bind(this), 300);\n }.bind(this));\n }\n\n // Create the dashboard object and immediately show it\n this.dashboard = new LocusZoom.Dashboard(this).show();\n\n // Initialize all panels\n for (var id in this.panels) {\n this.panels[id].initialize();\n }\n\n // Define plot-level mouse events\n var namespace = '.' + this.id;\n if (this.layout.mouse_guide) {\n var mouseout_mouse_guide = function() {\n this.mouse_guide.vertical.attr('x', -1);\n this.mouse_guide.horizontal.attr('y', -1);\n }.bind(this);\n var mousemove_mouse_guide = function() {\n var coords = d3.mouse(this.svg.node());\n this.mouse_guide.vertical.attr('x', coords[0]);\n this.mouse_guide.horizontal.attr('y', coords[1]);\n }.bind(this);\n this.svg\n .on('mouseout' + namespace + '-mouse_guide', mouseout_mouse_guide)\n .on('touchleave' + namespace + '-mouse_guide', mouseout_mouse_guide)\n .on('mousemove' + namespace + '-mouse_guide', mousemove_mouse_guide);\n }\n var mouseup = function() {\n this.stopDrag();\n }.bind(this);\n var mousemove = function() {\n if (this.interaction.dragging) {\n var coords = d3.mouse(this.svg.node());\n if (d3.event) { d3.event.preventDefault(); }\n this.interaction.dragging.dragged_x = coords[0] - this.interaction.dragging.start_x;\n this.interaction.dragging.dragged_y = coords[1] - this.interaction.dragging.start_y;\n this.panels[this.interaction.panel_id].render();\n this.interaction.linked_panel_ids.forEach(function(panel_id) {\n this.panels[panel_id].render();\n }.bind(this));\n }\n }.bind(this);\n this.svg\n .on('mouseup' + namespace, mouseup)\n .on('touchend' + namespace, mouseup)\n .on('mousemove' + namespace, mousemove)\n .on('touchmove' + namespace, mousemove);\n\n // Add an extra namespaced mouseup handler to the containing body, if there is one\n // This helps to stop interaction events gracefully when dragging outside of the plot element\n if (!d3.select('body').empty()) {\n d3.select('body')\n .on('mouseup' + namespace, mouseup)\n .on('touchend' + namespace, mouseup);\n }\n\n this.on('match_requested', function(eventData) {\n // Layers can broadcast that a specific point has been selected, and the plot will tell every other layer\n // to look for that value. Whenever a point is de-selected, it clears the match.\n var data = eventData.data;\n var to_send = (data.active ? data.value : null);\n this.applyState({ lz_match_value: to_send });\n }.bind(this));\n\n this.initialized = true;\n\n // An extra call to setDimensions with existing discrete dimensions fixes some rounding errors with tooltip\n // positioning. TODO: make this additional call unnecessary.\n var client_rect = this.svg.node().getBoundingClientRect();\n var width = client_rect.width ? client_rect.width : this.layout.width;\n var height = client_rect.height ? client_rect.height : this.layout.height;\n this.setDimensions(width, height);\n\n return this;\n\n};\n\n/**\n * Refresh (or fetch) a plot's data from sources, regardless of whether position or state has changed\n * @returns {Promise}\n */\nLocusZoom.Plot.prototype.refresh = function() {\n return this.applyState();\n};\n\n\n/**\n * A user-defined callback function that can receive (and potentially act on) new plot data.\n * @callback externalDataCallback\n * @param {Object} new_data The body resulting from a data request. This represents the same information that would be passed to\n * a data layer making an equivalent request.\n */\n\n/**\n * A user-defined callback function that can respond to errors received during a previous operation\n * @callback externalErrorCallback\n * @param err A representation of the error that occurred\n */\n\n/**\n * Allow newly fetched data to be made available outside the LocusZoom plot. For example, a callback could be\n * registered to draw an HTML table of top GWAS hits, and update that table whenever the plot region changes.\n *\n * This is a convenience method for external hooks. It registers an event listener and returns parsed data,\n * using the same fields syntax and underlying methods as data layers.\n *\n * @param {String[]} fields An array of field names and transforms, in the same syntax used by a data layer.\n * Different data sources should be prefixed by the source name.\n * @param {externalDataCallback} success_callback Used defined function that is automatically called any time that\n * new data is received by the plot.\n * @param {Object} [opts] Options\n * @param {externalErrorCallback} [opts.onerror] User defined function that is automatically called if a problem\n * occurs during the data request or subsequent callback operations\n * @param {boolean} [opts.discrete=false] Normally the callback will subscribe to the combined body from the chain,\n * which may not be in a format that matches what the external callback wants to do. If discrete=true, returns the\n * uncombined record info\n * @return {function} The newly created event listener, to allow for later cleanup/removal\n */\nLocusZoom.Plot.prototype.subscribeToData = function(fields, success_callback, opts) {\n opts = opts || {};\n\n // Register an event listener that is notified whenever new data has been rendered\n var error_callback = opts.onerror || function(err) {\n console.log('An error occurred while acting on an external callback', err);\n };\n var self = this;\n\n var listener = function() {\n try {\n self.lzd.getData(self.state, fields)\n .then(function (new_data) {\n success_callback(opts.discrete ? new_data.discrete : new_data.body);\n }).catch(error_callback);\n } catch (error) {\n // In certain cases, errors are thrown before a promise can be generated, and LZ error display seems to rely on these errors bubbling up\n error_callback(error);\n }\n };\n this.on('data_rendered', listener);\n return listener;\n};\n\n/**\n * Update state values and trigger a pull for fresh data on all data sources for all data layers\n * @param state_changes\n * @returns {Promise} A promise that resolves when all data fetch and update operations are complete\n */\nLocusZoom.Plot.prototype.applyState = function(state_changes) {\n state_changes = state_changes || {};\n if (typeof state_changes != 'object') {\n throw new Error('LocusZoom.applyState only accepts an object; ' + (typeof state_changes) + ' given');\n }\n\n // First make a copy of the current (old) state to work with\n var new_state = JSON.parse(JSON.stringify(this.state));\n\n // Apply changes by top-level property to the new state\n for (var property in state_changes) {\n new_state[property] = state_changes[property];\n }\n\n // Validate the new state (may do nothing, may do a lot, depends on how the user has things set up)\n new_state = LocusZoom.validateState(new_state, this.layout);\n\n // Apply new state to the actual state\n for (property in new_state) {\n this.state[property] = new_state[property];\n }\n\n // Generate requests for all panels given new state\n this.emit('data_requested');\n this.remap_promises = [];\n this.loading_data = true;\n for (var id in this.panels) {\n this.remap_promises.push(this.panels[id].reMap());\n }\n\n return Promise.all(this.remap_promises)\n .catch(function(error) {\n console.error(error);\n this.curtain.show(error.message || error);\n this.loading_data = false;\n }.bind(this))\n .then(function() {\n // Update dashboard / components\n this.dashboard.update();\n\n // Apply panel-level state values\n this.panel_ids_by_y_index.forEach(function(panel_id) {\n var panel = this.panels[panel_id];\n panel.dashboard.update();\n // Apply data-layer-level state values\n panel.data_layer_ids_by_z_index.forEach(function(data_layer_id) {\n var data_layer = this.data_layers[data_layer_id];\n var state_id = panel_id + '.' + data_layer_id;\n for (var property in this.state[state_id]) {\n if (!this.state[state_id].hasOwnProperty(property)) { continue; }\n if (Array.isArray(this.state[state_id][property])) {\n this.state[state_id][property].forEach(function(element_id) {\n try {\n this.setElementStatus(property, this.getElementById(element_id), true);\n } catch (e) {\n console.warn('Unable to apply state: ' + state_id + ', ' + property);\n console.error(e);\n }\n }.bind(data_layer));\n }\n }\n }.bind(panel));\n }.bind(this));\n\n // Emit events\n this.emit('layout_changed');\n this.emit('data_rendered');\n this.emit('state_changed', state_changes);\n\n this.loading_data = false;\n\n }.bind(this));\n};\n\n/**\n * Register interactions along the specified axis, provided that the target panel allows interaction.\n *\n * @param {LocusZoom.Panel} panel\n * @param {('x_tick'|'y1_tick'|'y2_tick')} method The direction (axis) along which dragging is being performed.\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.startDrag = function(panel, method) {\n\n panel = panel || null;\n method = method || null;\n\n var axis = null;\n switch (method) {\n case 'background':\n case 'x_tick':\n axis = 'x';\n break;\n case 'y1_tick':\n axis = 'y1';\n break;\n case 'y2_tick':\n axis = 'y2';\n break;\n }\n\n if (!(panel instanceof LocusZoom.Panel) || !axis || !this.canInteract()) { return this.stopDrag(); }\n\n var coords = d3.mouse(this.svg.node());\n this.interaction = {\n panel_id: panel.id,\n linked_panel_ids: panel.getLinkedPanelIds(axis),\n dragging: {\n method: method,\n start_x: coords[0],\n start_y: coords[1],\n dragged_x: 0,\n dragged_y: 0,\n axis: axis\n }\n };\n\n this.svg.style('cursor', 'all-scroll');\n\n return this;\n\n};\n\n/**\n * Process drag interactions across the target panel and synchronize plot state across other panels in sync;\n * clear the event when complete\n * @returns {LocusZoom.Plot}\n */\nLocusZoom.Plot.prototype.stopDrag = function() {\n\n if (!this.interaction.dragging) { return this; }\n\n if (typeof this.panels[this.interaction.panel_id] != 'object') {\n this.interaction = {};\n return this;\n }\n var panel = this.panels[this.interaction.panel_id];\n\n // Helper function to find the appropriate axis layouts on child data layers\n // Once found, apply the extent as floor/ceiling and remove all other directives\n // This forces all associated axes to conform to the extent generated by a drag action\n var overrideAxisLayout = function(axis, axis_number, extent) {\n panel.data_layer_ids_by_z_index.forEach(function(id) {\n if (panel.data_layers[id].layout[axis + '_axis'].axis === axis_number) {\n panel.data_layers[id].layout[axis + '_axis'].floor = extent[0];\n panel.data_layers[id].layout[axis + '_axis'].ceiling = extent[1];\n delete panel.data_layers[id].layout[axis + '_axis'].lower_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].upper_buffer;\n delete panel.data_layers[id].layout[axis + '_axis'].min_extent;\n delete panel.data_layers[id].layout[axis + '_axis'].ticks;\n }\n });\n };\n\n switch(this.interaction.dragging.method) {\n case 'background':\n case 'x_tick':\n if (this.interaction.dragging.dragged_x !== 0) {\n overrideAxisLayout('x', 1, panel.x_extent);\n this.applyState({ start: panel.x_extent[0], end: panel.x_extent[1] });\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n if (this.interaction.dragging.dragged_y !== 0) {\n // TODO: Hardcoded assumption of only two possible axes with single-digit #s (switch/case)\n var y_axis_number = parseInt(this.interaction.dragging.method[1]);\n overrideAxisLayout('y', y_axis_number, panel['y' + y_axis_number + '_extent']);\n }\n break;\n }\n\n this.interaction = {};\n this.svg.style('cursor', null);\n\n return this;\n\n};\n","/* global LocusZoom */\n'use strict';\n\n/**\n * A panel is an abstract class representing a subdivision of the LocusZoom stage\n * to display a distinct data representation as a collection of data layers.\n * @class\n * @param {Object} layout\n * @param {LocusZoom.Plot|null} parent\n*/\nLocusZoom.Panel = function(layout, parent) {\n\n if (typeof layout !== 'object') {\n throw new Error('Unable to create panel, invalid layout');\n }\n\n /** @member {LocusZoom.Plot|null} */\n this.parent = parent || null;\n /** @member {LocusZoom.Plot|null} */\n this.parent_plot = parent;\n\n // Ensure a valid ID is present. If there is no valid ID then generate one\n if (typeof layout.id !== 'string' || !layout.id.length) {\n if (!this.parent) {\n layout.id = 'p' + Math.floor(Math.random() * Math.pow(10,8));\n } else {\n var id = null;\n var generateID = function() {\n id = 'p' + Math.floor(Math.random() * Math.pow(10,8));\n if (id == null || typeof this.parent.panels[id] != 'undefined') {\n id = generateID();\n }\n }.bind(this);\n layout.id = id;\n }\n } else if (this.parent) {\n if (typeof this.parent.panels[layout.id] !== 'undefined') {\n throw new Error('Cannot create panel with id [' + layout.id + ']; panel with that id already exists');\n }\n }\n /** @member {String} */\n this.id = layout.id;\n\n /** @member {Boolean} */\n this.initialized = false;\n /**\n * The index of this panel in the parent plot's `layout.panels`\n * @member {number}\n * */\n this.layout_idx = null;\n /** @member {Object} */\n this.svg = {};\n\n /**\n * A JSON-serializable object used to describe the composition of the Panel\n * @member {Object}\n */\n this.layout = LocusZoom.Layouts.merge(layout || {}, LocusZoom.Panel.DefaultLayout);\n\n // Define state parameters specific to this panel\n if (this.parent) {\n /** @member {Object} */\n this.state = this.parent.state;\n\n /** @member {String} */\n this.state_id = this.id;\n this.state[this.state_id] = this.state[this.state_id] || {};\n } else {\n this.state = null;\n this.state_id = null;\n }\n\n /** @member {Object} */\n this.data_layers = {};\n /** @member {String[]} */\n this.data_layer_ids_by_z_index = [];\n\n /** @protected */\n this.applyDataLayerZIndexesToDataLayerLayouts = function() {\n this.data_layer_ids_by_z_index.forEach(function(dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n }.bind(this);\n\n /**\n * Track data requests in progress\n * @member {Promise[]}\n * @protected\n */\n this.data_promises = [];\n\n /** @member {d3.scale} */\n this.x_scale = null;\n /** @member {d3.scale} */\n this.y1_scale = null;\n /** @member {d3.scale} */\n this.y2_scale = null;\n\n /** @member {d3.extent} */\n this.x_extent = null;\n /** @member {d3.extent} */\n this.y1_extent = null;\n /** @member {d3.extent} */\n this.y2_extent = null;\n\n /** @member {Number[]} */\n this.x_ticks = [];\n /** @member {Number[]} */\n this.y1_ticks = [];\n /** @member {Number[]} */\n this.y2_ticks = [];\n\n /**\n * A timeout ID as returned by setTimeout\n * @protected\n * @member {number}\n */\n this.zoom_timeout = null;\n\n /** @returns {string} */\n this.getBaseId = function() {\n return this.parent.id + '.' + this.id;\n };\n\n /**\n * Known event hooks that the panel can respond to\n * @protected\n * @member {Object}\n */\n this.event_hooks = {\n 'layout_changed': [],\n 'data_requested': [],\n 'data_rendered': [],\n 'element_clicked': [],\n 'element_selection': [],\n 'match_requested': [] // A data layer is attempting to highlight matching points (internal use only)\n };\n\n /**\n * There are several events that a LocusZoom panel can \"emit\" when appropriate, and LocusZoom supports registering\n * \"hooks\" for these events which are essentially custom functions intended to fire at certain times.\n *\n * The following panel-level events are currently supported:\n * - `layout_changed` - context: panel - Any aspect of the panel's layout (including dimensions or state) has changed.\n * - `data_requested` - context: panel - A request for new data from any data source used in the panel has been made.\n * - `data_rendered` - context: panel - Data from a request has been received and rendered in the panel.\n * - `element_clicked` - context: panel - A data element in any of the panel's data layers has been clicked.\n * - `element_selection` - context: panel - Triggered when an element changes \"selection\" status, and identifies\n * whether the element is being selected or deselected.\n *\n * To register a hook for any of these events use `panel.on('event_name', function() {})`.\n *\n * There can be arbitrarily many functions registered to the same event. They will be executed in the order they\n * were registered. The this context bound to each event hook function is dependent on the type of event, as\n * denoted above. For example, when data_requested is emitted the context for this in the event hook will be the\n * panel itself, but when element_clicked is emitted the context for this in the event hook will be the element\n * that was clicked.\n *\n * @param {String} event The name of the event (as defined in `event_hooks`)\n * @param {function} hook\n * @returns {function} The registered event listener\n */\n this.on = function(event, hook) {\n // TODO: Dry plot and panel event code into a shared mixin\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('Unable to register event hook, invalid event: ' + event.toString());\n }\n if (typeof hook != 'function') {\n throw new Error('Unable to register event hook, invalid hook function passed');\n }\n this.event_hooks[event].push(hook);\n return hook;\n };\n /**\n * Remove one or more previously defined event listeners\n * @param {String} event The name of an event (as defined in `event_hooks`)\n * @param {eventCallback} [hook] The callback to deregister\n * @returns {LocusZoom.Panel}\n */\n this.off = function(event, hook) {\n var theseHooks = this.event_hooks[event];\n if (typeof 'event' != 'string' || !Array.isArray(theseHooks)) {\n throw new Error('Unable to remove event hook, invalid event: ' + event.toString());\n }\n if (hook === undefined) {\n // Deregistering all hooks for this event may break basic functionality, and should only be used during\n // cleanup operations (eg to prevent memory leaks)\n this.event_hooks[event] = [];\n } else {\n var hookMatch = theseHooks.indexOf(hook);\n if (hookMatch !== -1) {\n theseHooks.splice(hookMatch, 1);\n } else {\n throw new Error('The specified event listener is not registered and therefore cannot be removed');\n }\n }\n return this;\n };\n /**\n * Handle running of event hooks when an event is emitted\n *\n * There is a shorter overloaded form of this method: if the event does not have any data, the second\n * argument can be a boolean to control bubbling\n *\n * @param {string} event A known event name\n * @param {*} [eventData] Data or event description that will be passed to the event listener\n * @param {boolean} [bubble=false] Whether to bubble the event to the parent\n * @returns {LocusZoom.Panel}\n */\n this.emit = function(event, eventData, bubble) {\n bubble = bubble || false;\n\n // TODO: DRY this with the parent plot implementation. Ensure interfaces remain compatible.\n // TODO: Improve documentation for overloaded method signature (JSDoc may have trouble here)\n if (typeof 'event' != 'string' || !Array.isArray(this.event_hooks[event])) {\n throw new Error('LocusZoom attempted to throw an invalid event: ' + event.toString());\n }\n if (typeof eventData === 'boolean' && arguments.length === 2) {\n // Overloaded method signature: emit(event, bubble)\n bubble = eventData;\n eventData = null;\n }\n var sourceID = this.getBaseId();\n var self = this;\n var eventContext = {sourceID: sourceID, data: eventData || null};\n this.event_hooks[event].forEach(function(hookToRun) {\n // By default, any handlers fired here will see the panel as the value of `this`. If a bound function is\n // registered as a handler, the previously bound `this` will override anything provided to `call` below.\n hookToRun.call(self, eventContext);\n });\n if (bubble && this.parent) {\n this.parent.emit(event, eventContext);\n }\n return this;\n };\n\n /**\n * Get an object with the x and y coordinates of the panel's origin in terms of the entire page\n * Necessary for positioning any HTML elements over the panel\n * @returns {{x: Number, y: Number}}\n */\n this.getPageOrigin = function() {\n var plot_origin = this.parent.getPageOrigin();\n return {\n x: plot_origin.x + this.layout.origin.x,\n y: plot_origin.y + this.layout.origin.y\n };\n };\n\n // Initialize the layout\n this.initializeLayout();\n\n return this;\n\n};\n\n/**\n * Default panel layout\n * @static\n * @type {Object}\n */\nLocusZoom.Panel.DefaultLayout = {\n title: { text: '', style: {}, x: 10, y: 22 },\n y_index: null,\n width: 0,\n height: 0,\n origin: { x: 0, y: null },\n min_width: 1,\n min_height: 1,\n proportional_width: null,\n proportional_height: null,\n proportional_origin: { x: 0, y: null },\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n background_click: 'clear_selections',\n dashboard: {\n components: []\n },\n cliparea: {\n height: 0,\n width: 0,\n origin: { x: 0, y: 0 }\n },\n axes: { // These are the only axes supported!!\n x: {},\n y1: {},\n y2: {}\n },\n legend: null,\n interaction: {\n drag_background_to_pan: false,\n drag_x_ticks_to_scale: false,\n drag_y1_ticks_to_scale: false,\n drag_y2_ticks_to_scale: false,\n scroll_to_zoom: false,\n x_linked: false,\n y1_linked: false,\n y2_linked: false\n },\n data_layers: []\n};\n\n/**\n * Prepare the panel for first use by performing parameter validation, creating axes, setting default dimensions,\n * and preparing / positioning data layers as appropriate.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.initializeLayout = function() {\n\n // If the layout is missing BOTH width and proportional width then set the proportional width to 1.\n // This will default the panel to taking up the full width of the plot.\n if (this.layout.width === 0 && this.layout.proportional_width === null) {\n this.layout.proportional_width = 1;\n }\n\n // If the layout is missing BOTH height and proportional height then set the proportional height to\n // an equal share of the plot's current height.\n if (this.layout.height === 0 && this.layout.proportional_height === null) {\n var panel_count = Object.keys(this.parent.panels).length;\n if (panel_count > 0) {\n this.layout.proportional_height = (1 / panel_count);\n } else {\n this.layout.proportional_height = 1;\n }\n }\n\n // Set panel dimensions, origin, and margin\n this.setDimensions();\n this.setOrigin();\n this.setMargin();\n\n // Set ranges\n // TODO: Define stub values in constructor\n this.x_range = [0, this.layout.cliparea.width];\n this.y1_range = [this.layout.cliparea.height, 0];\n this.y2_range = [this.layout.cliparea.height, 0];\n\n // Initialize panel axes\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (!Object.keys(this.layout.axes[axis]).length || this.layout.axes[axis].render === false) {\n // The default layout sets the axis to an empty object, so set its render boolean here\n this.layout.axes[axis].render = false;\n } else {\n this.layout.axes[axis].render = true;\n this.layout.axes[axis].label = this.layout.axes[axis].label || null;\n this.layout.axes[axis].label_function = this.layout.axes[axis].label_function || null;\n }\n }.bind(this));\n\n // Add data layers (which define x and y extents)\n this.layout.data_layers.forEach(function(data_layer_layout) {\n this.addDataLayer(data_layer_layout);\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Set the dimensions for the panel. If passed with no arguments will calculate optimal size based on layout\n * directives and the available area within the plot. If passed discrete width (number) and height (number) will\n * attempt to resize the panel to them, but may be limited by minimum dimensions defined on the plot or panel.\n *\n * @public\n * @param {number} [width]\n * @param {number} [height]\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setDimensions = function(width, height) {\n if (typeof width != 'undefined' && typeof height != 'undefined') {\n if (!isNaN(width) && width >= 0 && !isNaN(height) && height >= 0) {\n this.layout.width = Math.max(Math.round(+width), this.layout.min_width);\n this.layout.height = Math.max(Math.round(+height), this.layout.min_height);\n }\n } else {\n if (this.layout.proportional_width !== null) {\n this.layout.width = Math.max(this.layout.proportional_width * this.parent.layout.width, this.layout.min_width);\n }\n if (this.layout.proportional_height !== null) {\n this.layout.height = Math.max(this.layout.proportional_height * this.parent.layout.height, this.layout.min_height);\n }\n }\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n if (this.svg.clipRect) {\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n }\n if (this.initialized) {\n this.render();\n this.curtain.update();\n this.loader.update();\n this.dashboard.update();\n if (this.legend) { this.legend.position(); }\n }\n return this;\n};\n\n/**\n * Set panel origin on the plot, and re-render as appropriate\n *\n * @public\n * @param {number} x\n * @param {number} y\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setOrigin = function(x, y) {\n if (!isNaN(x) && x >= 0) { this.layout.origin.x = Math.max(Math.round(+x), 0); }\n if (!isNaN(y) && y >= 0) { this.layout.origin.y = Math.max(Math.round(+y), 0); }\n if (this.initialized) { this.render(); }\n return this;\n};\n\n/**\n * Set margins around this panel\n * @public\n * @param {number} top\n * @param {number} right\n * @param {number} bottom\n * @param {number} left\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setMargin = function(top, right, bottom, left) {\n var extra;\n if (!isNaN(top) && top >= 0) { this.layout.margin.top = Math.max(Math.round(+top), 0); }\n if (!isNaN(right) && right >= 0) { this.layout.margin.right = Math.max(Math.round(+right), 0); }\n if (!isNaN(bottom) && bottom >= 0) { this.layout.margin.bottom = Math.max(Math.round(+bottom), 0); }\n if (!isNaN(left) && left >= 0) { this.layout.margin.left = Math.max(Math.round(+left), 0); }\n if (this.layout.margin.top + this.layout.margin.bottom > this.layout.height) {\n extra = Math.floor(((this.layout.margin.top + this.layout.margin.bottom) - this.layout.height) / 2);\n this.layout.margin.top -= extra;\n this.layout.margin.bottom -= extra;\n }\n if (this.layout.margin.left + this.layout.margin.right > this.layout.width) {\n extra = Math.floor(((this.layout.margin.left + this.layout.margin.right) - this.layout.width) / 2);\n this.layout.margin.left -= extra;\n this.layout.margin.right -= extra;\n }\n ['top', 'right', 'bottom', 'left'].forEach(function(m) {\n this.layout.margin[m] = Math.max(this.layout.margin[m], 0);\n }.bind(this));\n this.layout.cliparea.width = Math.max(this.layout.width - (this.layout.margin.left + this.layout.margin.right), 0);\n this.layout.cliparea.height = Math.max(this.layout.height - (this.layout.margin.top + this.layout.margin.bottom), 0);\n this.layout.cliparea.origin.x = this.layout.margin.left;\n this.layout.cliparea.origin.y = this.layout.margin.top;\n\n if (this.initialized) { this.render(); }\n return this;\n};\n\n/**\n * Set the title for the panel. If passed an object, will merge the object with the existing layout configuration, so\n * that all or only some of the title layout object's parameters can be customized. If passed null, false, or an empty\n * string, the title DOM element will be set to display: none.\n *\n * @param {string|object|null} title The title text, or an object with additional configuration\n * @param {string} title.text Text to display. Since titles are rendered as SVG text, HTML and newlines will not be rendered.\n * @param {number} title.x X-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n * @param {number} title.y Y-offset, in pixels, for the title's text anchor (default left) relative to the top-left corner of the panel.\n NOTE: SVG y values go from the top down, so the SVG origin of (0,0) is in the top left corner.\n * @param {object} title.style CSS styles object to be applied to the title's DOM element.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.setTitle = function(title) {\n if (typeof this.layout.title == 'string') {\n var text = this.layout.title;\n this.layout.title = { text: text, x: 0, y: 0, style: {} };\n }\n if (typeof title == 'string') {\n this.layout.title.text = title;\n } else if (typeof title == 'object' && title !== null) {\n this.layout.title = LocusZoom.Layouts.merge(title, this.layout.title);\n }\n if (this.layout.title.text.length) {\n this.title.attr('display', null)\n .attr('x', parseFloat(this.layout.title.x))\n .attr('y', parseFloat(this.layout.title.y))\n .style(this.layout.title.style)\n .text(this.layout.title.text);\n } else {\n this.title.attr('display', 'none');\n }\n return this;\n};\n\n\n/**\n * Prepare the first rendering of the panel. This includes drawing the individual data layers, but also creates shared\n * elements such as axes, title, and loader/curtain.\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.initialize = function() {\n\n // Append a container group element to house the main panel group element and the clip path\n // Position with initial layout parameters\n this.svg.container = this.parent.svg.append('g')\n .attr('id', this.getBaseId() + '.panel_container')\n .attr('transform', 'translate(' + (this.layout.origin.x || 0) + ',' + (this.layout.origin.y || 0) + ')');\n\n // Append clip path to the parent svg element, size with initial layout parameters\n var clipPath = this.svg.container.append('clipPath')\n .attr('id', this.getBaseId() + '.clip');\n this.svg.clipRect = clipPath.append('rect')\n .attr('width', this.layout.width).attr('height', this.layout.height);\n\n // Append svg group for rendering all panel child elements, clipped by the clip path\n this.svg.group = this.svg.container.append('g')\n .attr('id', this.getBaseId() + '.panel')\n .attr('clip-path', 'url(#' + this.getBaseId() + '.clip)');\n\n // Add curtain and loader prototypes to the panel\n /** @member {Object} */\n this.curtain = LocusZoom.generateCurtain.call(this);\n /** @member {Object} */\n this.loader = LocusZoom.generateLoader.call(this);\n\n /**\n * Create the dashboard object and hang components on it as defined by panel layout\n * @member {LocusZoom.Dashboard}\n */\n this.dashboard = new LocusZoom.Dashboard(this);\n\n // Inner border\n this.inner_border = this.svg.group.append('rect')\n .attr('class', 'lz-panel-background')\n .on('click', function() {\n if (this.layout.background_click === 'clear_selections') { this.clearSelections(); }\n }.bind(this));\n\n // Add the title\n /** @member {Element} */\n this.title = this.svg.group.append('text').attr('class', 'lz-panel-title');\n if (typeof this.layout.title != 'undefined') { this.setTitle(); }\n\n // Initialize Axes\n this.svg.x_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.x_axis').attr('class', 'lz-x lz-axis');\n if (this.layout.axes.x.render) {\n this.svg.x_axis_label = this.svg.x_axis.append('text')\n .attr('class', 'lz-x lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n this.svg.y1_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.y1_axis').attr('class', 'lz-y lz-y1 lz-axis');\n if (this.layout.axes.y1.render) {\n this.svg.y1_axis_label = this.svg.y1_axis.append('text')\n .attr('class', 'lz-y1 lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n this.svg.y2_axis = this.svg.group.append('g')\n .attr('id', this.getBaseId() + '.y2_axis').attr('class', 'lz-y lz-y2 lz-axis');\n if (this.layout.axes.y2.render) {\n this.svg.y2_axis_label = this.svg.y2_axis.append('text')\n .attr('class', 'lz-y2 lz-axis lz-label')\n .attr('text-anchor', 'middle');\n }\n\n // Initialize child Data Layers\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].initialize();\n }.bind(this));\n\n /**\n * Legend object, as defined by panel layout and child data layer layouts\n * @member {LocusZoom.Legend}\n * */\n this.legend = null;\n if (this.layout.legend) {\n this.legend = new LocusZoom.Legend(this);\n }\n\n // Establish panel background drag interaction mousedown event handler (on the panel background)\n if (this.layout.interaction.drag_background_to_pan) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var mousedown = function() {\n this.parent.startDrag(this, 'background');\n }.bind(this);\n this.svg.container.select('.lz-panel-background')\n .on('mousedown' + namespace + '.background', mousedown)\n .on('touchstart' + namespace + '.background', mousedown);\n }\n\n return this;\n\n};\n\n/**\n * Refresh the sort order of all data layers (called by data layer moveUp and moveDown methods)\n */\nLocusZoom.Panel.prototype.resortDataLayers = function() {\n var sort = [];\n this.data_layer_ids_by_z_index.forEach(function(id) {\n sort.push(this.data_layers[id].layout.z_index);\n }.bind(this));\n this.svg.group.selectAll('g.lz-data_layer-container').data(sort).sort(d3.ascending);\n this.applyDataLayerZIndexesToDataLayerLayouts();\n};\n\n/**\n * Get an array of panel IDs that are axis-linked to this panel\n * @param {('x'|'y1'|'y2')} axis\n * @returns {Array}\n */\nLocusZoom.Panel.prototype.getLinkedPanelIds = function(axis) {\n axis = axis || null;\n var linked_panel_ids = [];\n if (['x','y1','y2'].indexOf(axis) === -1) { return linked_panel_ids; }\n if (!this.layout.interaction[axis + '_linked']) { return linked_panel_ids; }\n this.parent.panel_ids_by_y_index.forEach(function(panel_id) {\n if (panel_id !== this.id && this.parent.panels[panel_id].layout.interaction[axis + '_linked']) {\n linked_panel_ids.push(panel_id);\n }\n }.bind(this));\n return linked_panel_ids;\n};\n\n/**\n * Move a panel up relative to others by y-index\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.moveUp = function() {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index - 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index - 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index - 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n};\n\n/**\n * Move a panel down (y-axis) relative to others in the plot\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.moveDown = function() {\n if (this.parent.panel_ids_by_y_index[this.layout.y_index + 1]) {\n this.parent.panel_ids_by_y_index[this.layout.y_index] = this.parent.panel_ids_by_y_index[this.layout.y_index + 1];\n this.parent.panel_ids_by_y_index[this.layout.y_index + 1] = this.id;\n this.parent.applyPanelYIndexesToPanelLayouts();\n this.parent.positionPanels();\n }\n return this;\n};\n\n/**\n * Create a new data layer from a provided layout object. Should have the keys specified in `DefaultLayout`\n * Will automatically add at the top (depth/z-index) of the panel unless explicitly directed differently\n * in the layout provided.\n * @param {object} layout\n * @returns {*}\n */\nLocusZoom.Panel.prototype.addDataLayer = function(layout) {\n\n // Sanity checks\n if (typeof layout !== 'object' || typeof layout.id !== 'string' || !layout.id.length) {\n throw new Error('Invalid data layer layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n if (typeof this.data_layers[layout.id] !== 'undefined') {\n throw new Error('Cannot create data_layer with id [' + layout.id + ']; data layer with that id already exists in the panel');\n }\n if (typeof layout.type !== 'string') {\n throw new Error('Invalid data layer type in layout passed to LocusZoom.Panel.prototype.addDataLayer()');\n }\n\n // If the layout defines a y axis make sure the axis number is set and is 1 or 2 (default to 1)\n if (typeof layout.y_axis == 'object' && (typeof layout.y_axis.axis == 'undefined' || [1,2].indexOf(layout.y_axis.axis) === -1)) {\n layout.y_axis.axis = 1;\n }\n\n // Create the Data Layer\n var data_layer = LocusZoom.DataLayers.get(layout.type, layout, this);\n\n // Store the Data Layer on the Panel\n this.data_layers[data_layer.id] = data_layer;\n\n // If a discrete z_index was set in the layout then adjust other data layer z_index values to accommodate this one\n if (data_layer.layout.z_index !== null && !isNaN(data_layer.layout.z_index)\n && this.data_layer_ids_by_z_index.length > 0) {\n // Negative z_index values should count backwards from the end, so convert negatives to appropriate values here\n if (data_layer.layout.z_index < 0) {\n data_layer.layout.z_index = Math.max(this.data_layer_ids_by_z_index.length + data_layer.layout.z_index, 0);\n }\n this.data_layer_ids_by_z_index.splice(data_layer.layout.z_index, 0, data_layer.id);\n this.data_layer_ids_by_z_index.forEach(function(dlid, idx) {\n this.data_layers[dlid].layout.z_index = idx;\n }.bind(this));\n } else {\n var length = this.data_layer_ids_by_z_index.push(data_layer.id);\n this.data_layers[data_layer.id].layout.z_index = length - 1;\n }\n\n // Determine if this data layer was already in the layout.data_layers array.\n // If it wasn't, add it. Either way store the layout.data_layers array index on the data_layer.\n var layout_idx = null;\n this.layout.data_layers.forEach(function(data_layer_layout, idx) {\n if (data_layer_layout.id === data_layer.id) { layout_idx = idx; }\n });\n if (layout_idx === null) {\n layout_idx = this.layout.data_layers.push(this.data_layers[data_layer.id].layout) - 1;\n }\n this.data_layers[data_layer.id].layout_idx = layout_idx;\n\n return this.data_layers[data_layer.id];\n};\n\n/**\n * Remove a data layer by id\n * @param {string} id\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.removeDataLayer = function(id) {\n if (!this.data_layers[id]) {\n throw new Error('Unable to remove data layer, ID not found: ' + id);\n }\n\n // Destroy all tooltips for the data layer\n this.data_layers[id].destroyAllTooltips();\n\n // Remove the svg container for the data layer if it exists\n if (this.data_layers[id].svg.container) {\n this.data_layers[id].svg.container.remove();\n }\n\n // Delete the data layer and its presence in the panel layout and state\n this.layout.data_layers.splice(this.data_layers[id].layout_idx, 1);\n delete this.state[this.data_layers[id].state_id];\n delete this.data_layers[id];\n\n // Remove the data_layer id from the z_index array\n this.data_layer_ids_by_z_index.splice(this.data_layer_ids_by_z_index.indexOf(id), 1);\n\n // Update layout_idx and layout.z_index values for all remaining data_layers\n this.applyDataLayerZIndexesToDataLayerLayouts();\n this.layout.data_layers.forEach(function(data_layer_layout, idx) {\n this.data_layers[data_layer_layout.id].layout_idx = idx;\n }.bind(this));\n\n return this;\n};\n\n/**\n * Clear all selections on all data layers\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.clearSelections = function() {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setAllElementStatus('selected', false);\n }.bind(this));\n return this;\n};\n\n/**\n * When the parent plot changes state, adjust the panel accordingly. For example, this may include fetching new data\n * from the API as the viewing region changes\n * @returns {Promise}\n */\nLocusZoom.Panel.prototype.reMap = function() {\n this.emit('data_requested');\n this.data_promises = [];\n\n // Remove any previous error messages before attempting to load new data\n this.curtain.hide();\n // Trigger reMap on each Data Layer\n for (var id in this.data_layers) {\n try {\n this.data_promises.push(this.data_layers[id].reMap());\n } catch (error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }\n }\n // When all finished trigger a render\n return Promise.all(this.data_promises)\n .then(function() {\n this.initialized = true;\n this.render();\n this.emit('layout_changed', true);\n this.emit('data_rendered');\n }.bind(this))\n .catch(function(error) {\n console.error(error);\n this.curtain.show(error.message || error);\n }.bind(this));\n};\n\n/**\n * Iterate over data layers to generate panel axis extents\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.generateExtents = function() {\n\n // Reset extents\n ['x', 'y1', 'y2'].forEach(function(axis) {\n this[axis + '_extent'] = null;\n }.bind(this));\n\n // Loop through the data layers\n for (var id in this.data_layers) {\n\n var data_layer = this.data_layers[id];\n\n // If defined and not decoupled, merge the x extent of the data layer with the panel's x extent\n if (data_layer.layout.x_axis && !data_layer.layout.x_axis.decoupled) {\n this.x_extent = d3.extent((this.x_extent || []).concat(data_layer.getAxisExtent('x')));\n }\n\n // If defined and not decoupled, merge the y extent of the data layer with the panel's appropriate y extent\n if (data_layer.layout.y_axis && !data_layer.layout.y_axis.decoupled) {\n var y_axis = 'y' + data_layer.layout.y_axis.axis;\n this[y_axis + '_extent'] = d3.extent((this[y_axis + '_extent'] || []).concat(data_layer.getAxisExtent('y')));\n }\n\n }\n\n // Override x_extent from state if explicitly defined to do so\n if (this.layout.axes.x && this.layout.axes.x.extent === 'state') {\n this.x_extent = [ this.state.start, this.state.end ];\n }\n\n return this;\n\n};\n\n/**\n * Generate an array of ticks for an axis. These ticks are generated in one of three ways (highest wins):\n * 1. An array of specific tick marks\n * 2. Query each data layer for what ticks are appropriate, and allow a panel-level tick configuration parameter\n * object to override the layer's default presentation settings\n * 3. Generate generic tick marks based on the extent of the data\n * @param {('x'|'y1'|'y2')} axis The string identifier of the axis\n * @returns {Number[]|Object[]} TODO: number format?\n * An array of numbers: interpreted as an array of axis value offsets for positioning.\n * An array of objects: each object must have an 'x' attribute to position the tick.\n * Other supported object keys:\n * * text: string to render for a given tick\n * * style: d3-compatible CSS style object\n * * transform: SVG transform attribute string\n * * color: string or LocusZoom scalable parameter object\n */\nLocusZoom.Panel.prototype.generateTicks = function(axis) {\n\n // Parse an explicit 'ticks' attribute in the axis layout\n if (this.layout.axes[axis].ticks) {\n var layout = this.layout.axes[axis];\n\n var baseTickConfig = layout.ticks;\n if (Array.isArray(baseTickConfig)) {\n // Array of specific ticks hard-coded into a panel will override any ticks that an individual layer might specify\n return baseTickConfig;\n }\n\n if (typeof baseTickConfig === 'object') {\n // If the layout specifies base configuration for ticks- but without specific positions- then ask each\n // data layer to report the tick marks that it thinks it needs\n // TODO: Few layers currently need to specify custom ticks (which is ok!). But if it becomes common, consider adding mechanisms to deduplicate ticks across layers\n var self = this;\n\n // Pass any layer-specific customizations for how ticks are calculated. (styles are overridden separately)\n var config = { position: baseTickConfig.position };\n\n var combinedTicks = this.data_layer_ids_by_z_index.reduce(function(acc, data_layer_id) {\n var nextLayer = self.data_layers[data_layer_id];\n return acc.concat(nextLayer.getTicks(axis, config));\n }, []);\n\n return combinedTicks.map(function(item) {\n // The layer makes suggestions, but tick configuration params specified on the panel take precedence\n var itemConfig = {};\n itemConfig = LocusZoom.Layouts.merge(itemConfig, baseTickConfig);\n return LocusZoom.Layouts.merge(itemConfig, item);\n });\n }\n }\n\n // If no other configuration is provided, attempt to generate ticks from the extent\n if (this[axis + '_extent']) {\n return LocusZoom.prettyTicks(this[axis + '_extent'], 'both');\n }\n return [];\n};\n\n/**\n * Update rendering of this panel whenever an event triggers a redraw. Assumes that the panel has already been\n * prepared the first time via `initialize`\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.render = function() {\n\n // Position the panel container\n this.svg.container.attr('transform', 'translate(' + this.layout.origin.x + ',' + this.layout.origin.y + ')');\n\n // Set size on the clip rect\n this.svg.clipRect.attr('width', this.layout.width).attr('height', this.layout.height);\n\n // Set and position the inner border, style if necessary\n this.inner_border\n .attr('x', this.layout.margin.left).attr('y', this.layout.margin.top)\n .attr('width', this.layout.width - (this.layout.margin.left + this.layout.margin.right))\n .attr('height', this.layout.height - (this.layout.margin.top + this.layout.margin.bottom));\n if (this.layout.inner_border) {\n this.inner_border.style({ 'stroke-width': 1, 'stroke': this.layout.inner_border });\n }\n\n // Set/update panel title if necessary\n this.setTitle();\n\n // Regenerate all extents\n this.generateExtents();\n\n // Helper function to constrain any procedurally generated vectors (e.g. ranges, extents)\n // Constraints applied here keep vectors from going to infinity or beyond a definable power of ten\n var constrain = function(value, limit_exponent) {\n var neg_min = Math.pow(-10, limit_exponent);\n var neg_max = Math.pow(-10, -limit_exponent);\n var pos_min = Math.pow(10, -limit_exponent);\n var pos_max = Math.pow(10, limit_exponent);\n if (value === Infinity) { value = pos_max; }\n if (value === -Infinity) { value = neg_min; }\n if (value === 0) { value = pos_min; }\n if (value > 0) { value = Math.max(Math.min(value, pos_max), pos_min); }\n if (value < 0) { value = Math.max(Math.min(value, neg_max), neg_min); }\n return value;\n };\n\n // Define default and shifted ranges for all axes\n var ranges = {};\n if (this.x_extent) {\n var base_x_range = { start: 0, end: this.layout.cliparea.width };\n if (this.layout.axes.x.range) {\n base_x_range.start = this.layout.axes.x.range.start || base_x_range.start;\n base_x_range.end = this.layout.axes.x.range.end || base_x_range.end;\n }\n ranges.x = [base_x_range.start, base_x_range.end];\n ranges.x_shifted = [base_x_range.start, base_x_range.end];\n }\n if (this.y1_extent) {\n var base_y1_range = { start: this.layout.cliparea.height, end: 0 };\n if (this.layout.axes.y1.range) {\n base_y1_range.start = this.layout.axes.y1.range.start || base_y1_range.start;\n base_y1_range.end = this.layout.axes.y1.range.end || base_y1_range.end;\n }\n ranges.y1 = [base_y1_range.start, base_y1_range.end];\n ranges.y1_shifted = [base_y1_range.start, base_y1_range.end];\n }\n if (this.y2_extent) {\n var base_y2_range = { start: this.layout.cliparea.height, end: 0 };\n if (this.layout.axes.y2.range) {\n base_y2_range.start = this.layout.axes.y2.range.start || base_y2_range.start;\n base_y2_range.end = this.layout.axes.y2.range.end || base_y2_range.end;\n }\n ranges.y2 = [base_y2_range.start, base_y2_range.end];\n ranges.y2_shifted = [base_y2_range.start, base_y2_range.end];\n }\n\n // Shift ranges based on any drag or zoom interactions currently underway\n if (this.parent.interaction.panel_id && (this.parent.interaction.panel_id === this.id || this.parent.interaction.linked_panel_ids.indexOf(this.id) !== -1)) {\n var anchor, scalar = null;\n if (this.parent.interaction.zooming && typeof this.x_scale == 'function') {\n var current_extent_size = Math.abs(this.x_extent[1] - this.x_extent[0]);\n var current_scaled_extent_size = Math.round(this.x_scale.invert(ranges.x_shifted[1])) - Math.round(this.x_scale.invert(ranges.x_shifted[0]));\n var zoom_factor = this.parent.interaction.zooming.scale;\n var potential_extent_size = Math.floor(current_scaled_extent_size * (1 / zoom_factor));\n if (zoom_factor < 1 && !isNaN(this.parent.layout.max_region_scale)) {\n zoom_factor = 1 / (Math.min(potential_extent_size, this.parent.layout.max_region_scale) / current_scaled_extent_size);\n } else if (zoom_factor > 1 && !isNaN(this.parent.layout.min_region_scale)) {\n zoom_factor = 1 / (Math.max(potential_extent_size, this.parent.layout.min_region_scale) / current_scaled_extent_size);\n }\n var new_extent_size = Math.floor(current_extent_size * zoom_factor);\n anchor = this.parent.interaction.zooming.center - this.layout.margin.left - this.layout.origin.x;\n var offset_ratio = anchor / this.layout.cliparea.width;\n var new_x_extent_start = Math.max(Math.floor(this.x_scale.invert(ranges.x_shifted[0]) - ((new_extent_size - current_scaled_extent_size) * offset_ratio)), 1);\n ranges.x_shifted = [ this.x_scale(new_x_extent_start), this.x_scale(new_x_extent_start + new_extent_size) ];\n } else if (this.parent.interaction.dragging) {\n switch (this.parent.interaction.dragging.method) {\n case 'background':\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n break;\n case 'x_tick':\n if (d3.event && d3.event.shiftKey) {\n ranges.x_shifted[0] = +this.parent.interaction.dragging.dragged_x;\n ranges.x_shifted[1] = this.layout.cliparea.width + this.parent.interaction.dragging.dragged_x;\n } else {\n anchor = this.parent.interaction.dragging.start_x - this.layout.margin.left - this.layout.origin.x;\n scalar = constrain(anchor / (anchor + this.parent.interaction.dragging.dragged_x), 3);\n ranges.x_shifted[0] = 0;\n ranges.x_shifted[1] = Math.max(this.layout.cliparea.width * (1 / scalar), 1);\n }\n break;\n case 'y1_tick':\n case 'y2_tick':\n var y_shifted = 'y' + this.parent.interaction.dragging.method[1] + '_shifted';\n if (d3.event && d3.event.shiftKey) {\n ranges[y_shifted][0] = this.layout.cliparea.height + this.parent.interaction.dragging.dragged_y;\n ranges[y_shifted][1] = +this.parent.interaction.dragging.dragged_y;\n } else {\n anchor = this.layout.cliparea.height - (this.parent.interaction.dragging.start_y - this.layout.margin.top - this.layout.origin.y);\n scalar = constrain(anchor / (anchor - this.parent.interaction.dragging.dragged_y), 3);\n ranges[y_shifted][0] = this.layout.cliparea.height;\n ranges[y_shifted][1] = this.layout.cliparea.height - (this.layout.cliparea.height * (1 / scalar));\n }\n }\n }\n }\n\n // Generate scales and ticks for all axes, then render them\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (!this[axis + '_extent']) { return; }\n\n // Base Scale\n this[axis + '_scale'] = d3.scale.linear()\n .domain(this[axis + '_extent'])\n .range(ranges[axis + '_shifted']);\n\n // Shift the extent\n this[axis + '_extent'] = [\n this[axis + '_scale'].invert(ranges[axis][0]),\n this[axis + '_scale'].invert(ranges[axis][1])\n ];\n\n // Finalize Scale\n this[axis + '_scale'] = d3.scale.linear()\n .domain(this[axis + '_extent']).range(ranges[axis]);\n\n // Render axis (and generate ticks as needed)\n this.renderAxis(axis);\n }.bind(this));\n\n // Establish mousewheel zoom event handers on the panel (namespacing not passed through by d3, so not used here)\n if (this.layout.interaction.scroll_to_zoom) {\n var zoom_handler = function() {\n // Look for a shift key press while scrolling to execute.\n // If not present, gracefully raise a notification and allow conventional scrolling\n if (!d3.event.shiftKey) {\n if (this.parent.canInteract(this.id)) {\n this.loader.show('Press [SHIFT] while scrolling to zoom').hide(1000);\n }\n return;\n }\n d3.event.preventDefault();\n if (!this.parent.canInteract(this.id)) { return; }\n var coords = d3.mouse(this.svg.container.node());\n var delta = Math.max(-1, Math.min(1, (d3.event.wheelDelta || -d3.event.detail || -d3.event.deltaY)));\n if (delta === 0) { return; }\n this.parent.interaction = {\n panel_id: this.id,\n linked_panel_ids: this.getLinkedPanelIds('x'),\n zooming: {\n scale: (delta < 1) ? 0.9 : 1.1,\n center: coords[0]\n }\n };\n this.render();\n this.parent.interaction.linked_panel_ids.forEach(function(panel_id) {\n this.parent.panels[panel_id].render();\n }.bind(this));\n if (this.zoom_timeout !== null) { clearTimeout(this.zoom_timeout); }\n this.zoom_timeout = setTimeout(function() {\n this.parent.interaction = {};\n this.parent.applyState({ start: this.x_extent[0], end: this.x_extent[1] });\n }.bind(this), 500);\n }.bind(this);\n this.zoom_listener = d3.behavior.zoom();\n this.svg.container.call(this.zoom_listener)\n .on('wheel.zoom', zoom_handler)\n .on('mousewheel.zoom', zoom_handler)\n .on('DOMMouseScroll.zoom', zoom_handler);\n }\n\n // Render data layers in order by z-index\n this.data_layer_ids_by_z_index.forEach(function(data_layer_id) {\n this.data_layers[data_layer_id].draw().render();\n }.bind(this));\n\n return this;\n};\n\n\n/**\n * Render ticks for a particular axis\n * @param {('x'|'y1'|'y2')} axis The identifier of the axes\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.renderAxis = function(axis) {\n\n if (['x', 'y1', 'y2'].indexOf(axis) === -1) {\n throw new Error('Unable to render axis; invalid axis identifier: ' + axis);\n }\n\n var canRender = this.layout.axes[axis].render\n && typeof this[axis + '_scale'] == 'function'\n && !isNaN(this[axis + '_scale'](0));\n\n // If the axis has already been rendered then check if we can/can't render it\n // Make sure the axis element is shown/hidden to suit\n if (this[axis + '_axis']) {\n this.svg.container.select('g.lz-axis.lz-' + axis).style('display', canRender ? null : 'none');\n }\n\n if (!canRender) { return this; }\n\n // Axis-specific values to plug in where needed\n var axis_params = {\n x: {\n position: 'translate(' + this.layout.margin.left + ',' + (this.layout.height - this.layout.margin.bottom) + ')',\n orientation: 'bottom',\n label_x: this.layout.cliparea.width / 2,\n label_y: (this.layout.axes[axis].label_offset || 0),\n label_rotate: null\n },\n y1: {\n position: 'translate(' + this.layout.margin.left + ',' + this.layout.margin.top + ')',\n orientation: 'left',\n label_x: -1 * (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n },\n y2: {\n position: 'translate(' + (this.layout.width - this.layout.margin.right) + ',' + this.layout.margin.top + ')',\n orientation: 'right',\n label_x: (this.layout.axes[axis].label_offset || 0),\n label_y: this.layout.cliparea.height / 2,\n label_rotate: -90\n }\n };\n\n // Generate Ticks\n this[axis + '_ticks'] = this.generateTicks(axis);\n\n // Determine if the ticks are all numbers (d3-automated tick rendering) or not (manual tick rendering)\n var ticksAreAllNumbers = (function(ticks) {\n for (var i = 0; i < ticks.length; i++) {\n if (isNaN(ticks[i])) {\n return false;\n }\n }\n return true;\n })(this[axis + '_ticks']);\n\n // Initialize the axis; set scale and orientation\n this[axis + '_axis'] = d3.svg.axis().scale(this[axis + '_scale']).orient(axis_params[axis].orientation).tickPadding(3);\n\n // Set tick values and format\n if (ticksAreAllNumbers) {\n this[axis + '_axis'].tickValues(this[axis + '_ticks']);\n if (this.layout.axes[axis].tick_format === 'region') {\n this[axis + '_axis'].tickFormat(function(d) { return LocusZoom.positionIntToString(d, 6); });\n }\n } else {\n var ticks = this[axis + '_ticks'].map(function(t) {\n return(t[axis.substr(0,1)]);\n });\n this[axis + '_axis'].tickValues(ticks)\n .tickFormat(function(t, i) { return this[axis + '_ticks'][i].text; }.bind(this));\n }\n\n // Position the axis in the SVG and apply the axis construct\n this.svg[axis + '_axis']\n .attr('transform', axis_params[axis].position)\n .call(this[axis + '_axis']);\n\n // If necessary manually apply styles and transforms to ticks as specified by the layout\n if (!ticksAreAllNumbers) {\n var tick_selector = d3.selectAll('g#' + this.getBaseId().replace('.','\\\\.') + '\\\\.' + axis + '_axis g.tick');\n var panel = this;\n tick_selector.each(function(d, i) {\n var selector = d3.select(this).select('text');\n if (panel[axis + '_ticks'][i].style) {\n selector.style(panel[axis + '_ticks'][i].style);\n }\n if (panel[axis + '_ticks'][i].transform) {\n selector.attr('transform', panel[axis + '_ticks'][i].transform);\n }\n });\n }\n\n // Render the axis label if necessary\n var label = this.layout.axes[axis].label || null;\n if (label !== null) {\n this.svg[axis + '_axis_label']\n .attr('x', axis_params[axis].label_x).attr('y', axis_params[axis].label_y)\n .text(LocusZoom.parseFields(this.state, label));\n if (axis_params[axis].label_rotate !== null) {\n this.svg[axis + '_axis_label']\n .attr('transform', 'rotate(' + axis_params[axis].label_rotate + ' ' + axis_params[axis].label_x + ',' + axis_params[axis].label_y + ')');\n }\n }\n\n // Attach interactive handlers to ticks as needed\n ['x', 'y1', 'y2'].forEach(function(axis) {\n if (this.layout.interaction['drag_' + axis + '_ticks_to_scale']) {\n var namespace = '.' + this.parent.id + '.' + this.id + '.interaction.drag';\n var tick_mouseover = function() {\n if (typeof d3.select(this).node().focus == 'function') { d3.select(this).node().focus(); }\n var cursor = (axis === 'x') ? 'ew-resize' : 'ns-resize';\n if (d3.event && d3.event.shiftKey) { cursor = 'move'; }\n d3.select(this)\n .style({'font-weight': 'bold', 'cursor': cursor})\n .on('keydown' + namespace, tick_mouseover)\n .on('keyup' + namespace, tick_mouseover);\n };\n this.svg.container.selectAll('.lz-axis.lz-' + axis + ' .tick text')\n .attr('tabindex', 0) // necessary to make the tick focusable so keypress events can be captured\n .on('mouseover' + namespace, tick_mouseover)\n .on('mouseout' + namespace, function() {\n d3.select(this).style({'font-weight': 'normal'});\n d3.select(this).on('keydown' + namespace, null).on('keyup' + namespace, null);\n })\n .on('mousedown' + namespace, function() {\n this.parent.startDrag(this, axis + '_tick');\n }.bind(this));\n }\n }.bind(this));\n\n return this;\n\n};\n\n/**\n * Force the height of this panel to the largest absolute height of the data in\n * all child data layers (if not null for any child data layers)\n * @param {number|null} [target_height] A target height, which will be used in situations when the expected height can be\n * pre-calculated (eg when the layers are transitioning)\n */\nLocusZoom.Panel.prototype.scaleHeightToData = function(target_height) {\n target_height = +target_height || null;\n if (target_height === null) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n var dh = this.data_layers[id].getAbsoluteDataHeight();\n if (+dh) {\n if (target_height === null) {\n target_height = +dh;\n }\n else {\n target_height = Math.max(target_height, +dh);\n }\n }\n }.bind(this));\n }\n if (+target_height) {\n target_height += +this.layout.margin.top + +this.layout.margin.bottom;\n this.setDimensions(this.layout.width, target_height);\n this.parent.setDimensions();\n this.parent.panel_ids_by_y_index.forEach(function(id) {\n this.parent.panels[id].layout.proportional_height = null;\n }.bind(this));\n this.parent.positionPanels();\n }\n};\n\n/**\n * Methods to set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n * @param {Array} filters\n * @param {Boolean} exclusive\n */\nLocusZoom.Panel.prototype.setElementStatusByFilters = function(status, toggle, filters, exclusive) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setElementStatusByFilters(status, toggle, filters, exclusive);\n }.bind(this));\n};\n/**\n * Set/unset element statuses across all data layers\n * @param {String} status\n * @param {Boolean} toggle\n */\nLocusZoom.Panel.prototype.setAllElementStatus = function(status, toggle) {\n this.data_layer_ids_by_z_index.forEach(function(id) {\n this.data_layers[id].setAllElementStatus(status, toggle);\n }.bind(this));\n};\n// TODO: Capture documentation for dynamically generated methods\nLocusZoom.DataLayer.Statuses.verbs.forEach(function(verb, idx) {\n var adjective = LocusZoom.DataLayer.Statuses.adjectives[idx];\n var antiverb = 'un' + verb;\n // Set/unset status for arbitrarily many elements given a set of filters\n LocusZoom.Panel.prototype[verb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, true, filters, exclusive);\n };\n LocusZoom.Panel.prototype[antiverb + 'ElementsByFilters'] = function(filters, exclusive) {\n if (typeof exclusive == 'undefined') { exclusive = false; } else { exclusive = !!exclusive; }\n return this.setElementStatusByFilters(adjective, false, filters, exclusive);\n };\n // Set/unset status for all elements\n LocusZoom.Panel.prototype[verb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, true);\n return this;\n };\n LocusZoom.Panel.prototype[antiverb + 'AllElements'] = function() {\n this.setAllElementStatus(adjective, false);\n return this;\n };\n});\n\n\n/**\n * Add a \"basic\" loader to a panel\n * This method is just a shortcut for adding the most commonly used type of loading indicator, which appears when\n * data is requested, animates (e.g. shows an infinitely cycling progress bar as opposed to one that loads from\n * 0-100% based on actual load progress), and disappears when new data is loaded and rendered.\n *\n *\n * @param {Boolean} show_immediately\n * @returns {LocusZoom.Panel}\n */\nLocusZoom.Panel.prototype.addBasicLoader = function(show_immediately) {\n if (typeof show_immediately != 'undefined') { show_immediately = true; }\n if (show_immediately) {\n this.loader.show('Loading...').animate();\n }\n this.on('data_requested', function() {\n this.loader.show('Loading...').animate();\n }.bind(this));\n this.on('data_rendered', function() {\n this.loader.hide();\n }.bind(this));\n return this;\n};\n"]} \ No newline at end of file diff --git a/index.html b/index.html index 94558bf7..1bcbade2 100644 --- a/index.html +++ b/index.html @@ -76,7 +76,7 @@

Get LocusZoom.js

CSS
@@ -87,7 +87,7 @@
CSS
Dependencies
@@ -98,7 +98,7 @@
Dependencies
Javascript
diff --git a/package-lock.json b/package-lock.json index 61a05a30..9d199f6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "locuszoom", - "version": "0.10.0", + "version": "0.10.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d30381a7..9aa41a22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "locuszoom", - "version": "0.10.0", + "version": "0.10.1", "description": "Generate interactive visualizations of statistical genetic data", "keywords": [ "visualization",