Skip to content

Commit

Permalink
Merge branch 'release/0.10.0-beta.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
abought committed Oct 7, 2019
2 parents d28a9bd + 3c83441 commit bf811b9
Show file tree
Hide file tree
Showing 45 changed files with 953 additions and 651 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2017 University of Michigan Center for Statistical Genetics
Copyright (c) 2019 University of Michigan Center for Statistical Genetics

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ and [statgen.github.io/locuszoom/#examples](http://statgen.github.io/locuszoom/#
The page you build that embeds the LocusZoom plugin must include the following resources, found in the `dist` directory:

* `locuszoom.vendor.min.js`
This file contains the concatenated vendor libraries. You can alternatively include [d3](http://d3js.org/) and
[Q](https://github.com/kriskowal/q) from other sources, so long as they are included **before including LocusZoom files**.
This file contains the concatenated vendor libraries. You can alternatively include [d3](http://d3js.org/)
from other sources, so long as it is included **before including LocusZoom files**. This bundle also contains a
polyfill for ES6 `Promise`, which you may need if your site supports certain older browsers such as Internet Explorer.

* `locuszoom.app.js` OR `locuszoom.app.min.js`
This is the primary application logic. It should only be included *after* the vendor dependencies have been included.
Expand Down Expand Up @@ -227,7 +228,6 @@ LocusZoom is an entirely client-side application designed to plug into arbitrary
or something else entirely. It has the following vendor dependencies:

* [d3](http://d3js.org/) for a data visualization framework
* [Q](https://github.com/kriskowal/q) for a promises framework

### Build System and Automated Testing

Expand All @@ -244,7 +244,7 @@ following files (in the `dist` folder):
* `locuszoom.app.js` - A concatenated app file suitable for use in development
* `locuszoom.app.min.js` - A concatenated and minified app file suitable for use in production
* `locuszoom.vendor.min.js` - A concatenated vendor file suitable for use as a single vendor include in either
development or production (contains d3 and Q)
development or production (contains d3)
* `locuszoom.css` - A generated CSS file for all LocusZoom styles

This build process will also write sourcemaps, to help with debugging code even in production environments.
Expand Down
2 changes: 1 addition & 1 deletion assets/js/app/.eslintrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"globals": {
"d3": false,
"Q": false
"Promise": false
},
"env": {
"browser": true
Expand Down
15 changes: 8 additions & 7 deletions assets/js/app/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -856,9 +856,11 @@ LocusZoom.Dashboard.Components.add('download', function(layout) {
this.button.selector
.classed('lz-dashboard-button-gray-disabled', true)
.html('Preparing Image');
this.generateBase64SVG().then(function(base64_string) {
this.generateBase64SVG().then(function(url) {
var old = this.button.selector.attr('href');
if (old) { URL.revokeObjectURL(old); } // Clean up old url instance to prevent memory leaks
this.button.selector
.attr('href', 'data:image/svg+xml;base64,\n' + base64_string)
.attr('href', url)
.classed('lz-dashboard-button-gray-disabled', false)
.classed('lz-dashboard-button-gray-highlighted', true)
.html('Download Image');
Expand Down Expand Up @@ -887,7 +889,7 @@ LocusZoom.Dashboard.Components.add('download', function(layout) {
}
}
this.generateBase64SVG = function() {
return Q.fcall(function () {
return new Promise(function (resolve, reject) {
// Insert a hidden div, clone the node into that so we can modify it with d3
var container = this.parent.selector.append('div').style('display', 'none')
.html(this.parent_plot.svg.node().outerHTML);
Expand All @@ -907,10 +909,9 @@ LocusZoom.Dashboard.Components.add('download', function(layout) {
initial_html = initial_html.slice(0,insert_at) + style_def + initial_html.slice(insert_at);
// Delete the container node
container.remove();
// Base64-encode the string and return it
return btoa(encodeURIComponent(initial_html).replace(/%([0-9A-F]{2})/g, function(match, p1) {
return String.fromCharCode('0x' + p1);
}));
// Create an object URL based on the rendered markup
var content = new Blob([initial_html], { type: 'image/svg+xml' });
resolve(URL.createObjectURL(content));
}.bind(this));
};
});
Expand Down
22 changes: 11 additions & 11 deletions assets/js/app/Data.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ LocusZoom.Data.Requester = function(sources) {
});
//assume the fields are requested in dependent order
//TODO: better manage dependencies
var ret = Q.when({header:{}, body: [], discrete: {}});
var ret = Promise.resolve({header:{}, body: [], discrete: {}});
for(var i = 0; i < request_handles.length; i++) {
// If a single datalayer uses multiple sources, perform the next request when the previous one completes
ret = ret.then(request_handles[i]);
Expand Down Expand Up @@ -331,7 +331,7 @@ LocusZoom.Data.Source.prototype.getRequest = function(state, chain, fields) {
var req;
var cacheKey = this.getCacheKey(state, chain, fields);
if (this.enableCache && typeof(cacheKey) !== 'undefined' && cacheKey === this._cachedKey) {
req = Q.when(this._cachedResponse); // Resolve to the value of the current promise
req = Promise.resolve(this._cachedResponse); // Resolve to the value of the current promise
} else {
req = this.fetchRequest(state, chain, fields);
if (this.enableCache) {
Expand Down Expand Up @@ -371,7 +371,7 @@ LocusZoom.Data.Source.prototype.getData = function(state, fields, outnames, tran
if (self.dependentSource && chain && chain.body && !chain.body.length) {
// A "dependent" source should not attempt to fire a request if there is no data for it to act on.
// Therefore, it should simply return the previous data chain.
return Q.when(chain);
return Promise.resolve(chain);
}

return self.getRequest(state, chain, fields).then(function(resp) {
Expand Down Expand Up @@ -537,24 +537,24 @@ LocusZoom.Data.Source.prototype.parseResponse = function(resp, chain, fields, ou
// to occur for annotation sources (such as from ExAC). If empty response is received, skip parsing and log.
// FIXME: Throw an error after pending, eg https://github.com/konradjk/exac_browser/issues/345
console.error("No usable response was returned for source: '" + source_id + "'. Parsing will be skipped.");
return Q.when(chain);
return Promise.resolve(chain);
}

var json = typeof resp == 'string' ? JSON.parse(resp) : resp;

var self = this;
// Perform the 4 steps of parsing the payload and return a combined chain object
return Q.when(self.normalizeResponse(json.data || json))
return Promise.resolve(self.normalizeResponse(json.data || json))
.then(function(standardized) {
// Perform calculations on the data from just this source
return Q.when(self.annotateData(standardized, chain));
return Promise.resolve(self.annotateData(standardized, chain));
}).then(function (data) {
return Q.when(self.extractFields(data, fields, outnames, trans));
return Promise.resolve(self.extractFields(data, fields, outnames, trans));
}).then(function (one_source_body) {
// Store a copy of the data that would be returned by parsing this source in isolation (and taking the
// fields array into account). This is useful when we want to re-use the source output in many ways.
chain.discrete[source_id] = one_source_body;
return Q.when(self.combineChainBody(one_source_body, chain, fields, outnames, trans));
return Promise.resolve(self.combineChainBody(one_source_body, chain, fields, outnames, trans));
}).then(function (new_body) {
return { header: chain.header || {}, discrete: chain.discrete, body: new_body };
});
Expand Down Expand Up @@ -1143,7 +1143,7 @@ LocusZoom.Data.StaticSource = LocusZoom.Data.Source.extend(function(data) {
},'StaticJSON');

LocusZoom.Data.StaticSource.prototype.getRequest = function(state, chain, fields) {
return Q.fcall(function() {return this._data;}.bind(this));
return Promise.resolve(this._data);
};

LocusZoom.Data.StaticSource.prototype.toJSON = function() {
Expand Down Expand Up @@ -1233,7 +1233,7 @@ LocusZoom.Data.ConnectorSource.prototype.getRequest = function(state, chain, fie
throw new Error(self.constructor.SOURCE_NAME + ' cannot be used before loading required data for: ' + chain_source_id);
}
});
return Q.when(chain.body || []);
return Promise.resolve(chain.body || []);
};

LocusZoom.Data.ConnectorSource.prototype.parseResponse = function(data, chain, fields, outnames, trans) {
Expand All @@ -1242,7 +1242,7 @@ LocusZoom.Data.ConnectorSource.prototype.parseResponse = function(data, chain, f

// Because of how the chain works, connectors are not very good at applying new transformations or namespacing.
// Typically connectors are called with `connector_name:all` in the fields array.
return Q.when(this.combineChainBody(data, chain, fields, outnames, trans))
return Promise.resolve(this.combineChainBody(data, chain, fields, outnames, trans))
.then(function(new_body) {
return {header: chain.header || {}, discrete: chain.discrete || {}, body: new_body};
});
Expand Down
Loading

0 comments on commit bf811b9

Please sign in to comment.