-
Notifications
You must be signed in to change notification settings - Fork 967
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,078 additions
and
0 deletions.
There are no files selected for viewing
101 changes: 101 additions & 0 deletions
101
client/galaxy/scripts/mvc/visualization/client/components/model.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
define(["utils/utils", "mvc/visualization/visualization-model"], function(Utils) { | ||
return Backbone.Model.extend({ | ||
defaults: { | ||
title: "", | ||
type: "", | ||
date: null, | ||
state: "", | ||
state_info: "", | ||
modified: false, | ||
dataset_id: "", | ||
dataset_id_job: "" | ||
}, | ||
|
||
initialize: function(options, viz_options) { | ||
this.groups = new Backbone.Collection(); | ||
this.settings = new Backbone.Model(); | ||
this.definition = {}; | ||
this.viz_options = viz_options; | ||
console.debug("model::initialize() - Initialized with configuration:"); | ||
console.debug(viz_options); | ||
}, | ||
|
||
reset: function() { | ||
this.clear().set({ | ||
title: "New Chart", | ||
type: "__first", | ||
dataset_id: this.viz_options.dataset_id | ||
}); | ||
this.settings.clear(); | ||
this.groups.reset(); | ||
this.groups.add({ id: Utils.uid() }); | ||
}, | ||
|
||
state: function(value, info) { | ||
this.set({ state: value, state_info: info }); | ||
this.trigger("set:state"); | ||
console.debug("model::state() - " + info + " (" + value + ")"); | ||
}, | ||
|
||
/** Pack and save nested chart model */ | ||
save: function(options) { | ||
var self = this; | ||
options = options || {}; | ||
var chart_dict = { | ||
attributes: this.attributes, | ||
settings: this.settings.attributes, | ||
groups: [] | ||
}; | ||
this.groups.each(function(group) { | ||
chart_dict.groups.push(group.attributes); | ||
}); | ||
var viz = new Visualization({ | ||
id: this.viz_options.visualization_id || undefined, | ||
type: "charts", | ||
title: this.get("title") || "", | ||
config: { | ||
dataset_id: this.viz_options.dataset_id, | ||
chart_dict: (this.viz_options.chart_dict = chart_dict) | ||
} | ||
}); | ||
viz | ||
.save() | ||
.then(function(response) { | ||
if (response && response.id) { | ||
self.viz_options.visualization_id = response.id; | ||
options.success && options.success(); | ||
console.debug("model::save() - Received visualization id: " + response.id); | ||
} else { | ||
options.error && options.error(); | ||
console.debug("model::save() - Unrecognized response. Saving may have failed."); | ||
} | ||
}) | ||
.fail(function(response) { | ||
options.error && options.error(); | ||
console.debug("model::save() - Saving failed."); | ||
}); | ||
console.debug("model::save() - Saved with configuration:"); | ||
console.debug(this.viz_options); | ||
}, | ||
|
||
/** Load nested models/collections from packed dictionary */ | ||
load: function() { | ||
console.debug("model::load() - Attempting to load with configuration:"); | ||
console.debug(this.viz_options); | ||
var chart_dict = this.viz_options.chart_dict; | ||
if (chart_dict && chart_dict.attributes) { | ||
this.set(chart_dict.attributes); | ||
this.state("ok", "Loading saved visualization..."); | ||
this.settings.set(chart_dict.settings); | ||
this.groups.reset(); | ||
this.groups.add(chart_dict.groups); | ||
this.set("modified", false); | ||
console.debug("model::load() - Loading chart model " + chart_dict.attributes.type + "."); | ||
this.trigger("redraw"); | ||
return true; | ||
} | ||
console.debug("model::load() - Visualization attributes unavailable."); | ||
return false; | ||
} | ||
}); | ||
}); |
188 changes: 188 additions & 0 deletions
188
client/galaxy/scripts/mvc/visualization/client/components/screenshot.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
/** This class enables users to export/download a chart as PNG, SVG or PDF. */ | ||
define(["libs/underscore"], function(_) { | ||
/** PNG export */ | ||
function createPNG(options) { | ||
if (options.$el.find("svg").length > 0) { | ||
_svg2png(options); | ||
} else { | ||
_canvas2png(options.$el.find(".charts-viewport-canvas")); | ||
} | ||
} | ||
|
||
/** Convert canvas to png */ | ||
function _canvas2png($canvas) { | ||
try { | ||
if ($canvas.width() !== 0 && $canvas.height() !== 0) { | ||
var newCanvas = document.createElement("canvas"); | ||
newCanvas.width = $canvas.outerWidth(true); | ||
newCanvas.height = $canvas.outerHeight(true); | ||
var newContext = newCanvas.getContext("2d"); | ||
newContext.save(); | ||
newContext.fillStyle = "rgb(255,255,255)"; | ||
newContext.fillRect(0, 0, newCanvas.width, newCanvas.height); | ||
newContext.restore(); | ||
newContext.translate(0, 0); | ||
newContext.textAlign = "left"; | ||
newContext.textBaseline = "top"; | ||
function _toImage($el, x_offset, y_offset) { | ||
var tagname = $el.prop("tagName").toLowerCase(); | ||
var p = $el.position(); | ||
var left = | ||
x_offset + | ||
p.left + | ||
parseInt($el.css("marginLeft"), 10) + | ||
parseInt($el.css("borderLeftWidth"), 10) + | ||
parseInt($el.css("paddingLeft"), 10); | ||
var top = | ||
y_offset + | ||
p.top + | ||
parseInt($el.css("marginTop"), 10) + | ||
parseInt($el.css("borderTopWidth"), 10) + | ||
parseInt($el.css("paddingTop"), 10); | ||
var w = newCanvas.width; | ||
if (tagname == "div" || tagname == "span") { | ||
$el.children().each(function() { | ||
_toImage($(this), left, top); | ||
}); | ||
} else if (tagname == "canvas") { | ||
newContext.drawImage($el[0], left, top); | ||
} | ||
} | ||
$canvas.children().each(function() { | ||
_toImage($(this), 0, 0); | ||
}); | ||
var imgData = newCanvas.toDataURL("image/png"); | ||
if (imgData) { | ||
window.location.href = imgData.replace("image/png", "image/octet-stream"); | ||
} | ||
} | ||
} catch (err) { | ||
console.debug("FAILED - screenshot::_canvas2png() - " + err); | ||
if (options.error) { | ||
options.error("Please reduce your visualization to a single panel and try again."); | ||
} | ||
} | ||
} | ||
|
||
/** Convert svg to png */ | ||
function _svg2png(options) { | ||
var scale = 5; | ||
var xml = toXML(options); | ||
var canvas = document.createElement("canvas"); | ||
var context = canvas.getContext("2d"); | ||
var source = new Image(); | ||
var $container = $('<div style="display:none;"/>').append($(canvas)); | ||
$("body").append($container); | ||
canvas.width = xml.width * scale; | ||
canvas.height = xml.height * scale; | ||
source.src = "data:image/svg+xml;base64," + btoa(xml.string); | ||
source.onload = function() { | ||
context.drawImage(source, 0, 0, canvas.width, canvas.height); | ||
window.location.href = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); | ||
$container.remove(); | ||
}; | ||
} | ||
|
||
/** SVG export */ | ||
function createSVG(options) { | ||
window.location.href = "data:none/none;base64," + btoa(toXML(options).string); | ||
} | ||
|
||
/** PDF export */ | ||
function createPDF(options) { | ||
var xml = toXML(options); | ||
var data = { | ||
filename: "visualization", | ||
type: "application/pdf", | ||
height: xml.height, | ||
width: xml.width, | ||
scale: 2, | ||
svg: xml.string | ||
}; | ||
var $el = $("body"); | ||
var form = $el.find("#viewport-form"); | ||
if (form.length === 0) { | ||
form = $("<form>", { | ||
id: "viewport-form", | ||
method: "post", | ||
action: "http://export.highcharts.com/", | ||
display: "none" | ||
}); | ||
$el.append(form); | ||
} | ||
form.empty(); | ||
for (var name in data) { | ||
var input = $("<input/>", { | ||
type: "hidden", | ||
name: name, | ||
value: data[name] | ||
}); | ||
form.append(input); | ||
} | ||
try { | ||
form.submit(); | ||
} catch (err) { | ||
console.log(err); | ||
} | ||
} | ||
|
||
/** XML export */ | ||
function toXML(options) { | ||
var $svg = options.$el.find("svg"); | ||
if ($svg.length == 0) { | ||
if (options.error) { | ||
options.error("No SVG found. This visualization type does not support SVG/PDF export."); | ||
return; | ||
} | ||
} | ||
var $el = options.$el; | ||
var nsvgs = $svg.length; | ||
var height = parseInt($svg.first().css("height")); | ||
var width = parseInt($svg.first().css("width")); | ||
var serializer = new XMLSerializer(); | ||
var $composite = $("<svg/>").attr({ | ||
version: "1.1", | ||
xmlns: "http://www.w3.org/2000/svg", | ||
width: width * nsvgs, | ||
height: height | ||
}); | ||
var xmlString = ""; | ||
var offsetX = 0; | ||
$svg.each(function() { | ||
var $svg = $(this).clone(); | ||
_inline($svg); | ||
var $g = $('<g transform="translate(' + offsetX + ', 0)">').attr("xmlns", "http://www.w3.org/2000/svg"); | ||
$g.append($svg.find("g").first()); | ||
$composite.append($g); | ||
offsetX += width; | ||
}); | ||
return { | ||
string: serializer.serializeToString($composite[0]), | ||
height: height, | ||
width: width | ||
}; | ||
} | ||
|
||
/** inlines CSS code */ | ||
function _inline($target) { | ||
for (var sheet_id in document.styleSheets) { | ||
var sheet = document.styleSheets[sheet_id]; | ||
var rules = sheet.cssRules; | ||
if (rules) { | ||
for (var idx = 0, len = rules.length; idx < len; idx++) { | ||
try { | ||
$target.find(rules[idx].selectorText).each(function(i, elem) { | ||
elem.style.cssText += rules[idx].style.cssText; | ||
}); | ||
} catch (err) {} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return { | ||
createPNG: createPNG, | ||
createSVG: createSVG, | ||
createPDF: createPDF | ||
}; | ||
}); |
47 changes: 47 additions & 0 deletions
47
client/galaxy/scripts/mvc/visualization/client/views/description.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** This class renders the chart configuration form. */ | ||
import Utils from "utils/utils"; | ||
export default Backbone.View.extend({ | ||
initialize: function(app, options) { | ||
var self = this; | ||
this.chart = app.chart; | ||
this.app = app; | ||
this.setElement(this._template()); | ||
this.$title = this.$(".charts-description-title"); | ||
this.$image = this.$(".charts-description-image"); | ||
this.$text = this.$(".charts-description-text"); | ||
this.listenTo(this.chart, "change", function() { | ||
self.render(); | ||
}); | ||
this.render(); | ||
}, | ||
render: function() { | ||
if (this.chart.get("type")) { | ||
/*this.$image.attr( | ||
"src", | ||
repository_root + "/visualizations/" + this.app.split(this.chart.get("type")) + "/logo.png" | ||
);*/ | ||
this.$title.html(this.chart.definition.title + " (" + this.chart.definition.library + ")"); | ||
this.$text.html(Utils.linkify(this.chart.definition.description || "")); | ||
this.$el.show(); | ||
} else { | ||
this.$el.hide(); | ||
} | ||
}, | ||
_template: function() { | ||
return ( | ||
'<div class="charts-description">' + | ||
"<table>" + | ||
"<tr>" + | ||
'<td class="charts-description-image-td">' + | ||
'<img class="charts-description-image"/>' + | ||
"</td>" + | ||
"<td>" + | ||
'<div class="charts-description-title ui-form-info"/>' + | ||
'<div class="charts-description-text ui-form-info"/>' + | ||
"</td>" + | ||
"</tr>" + | ||
"</table>" + | ||
"</div>" | ||
); | ||
} | ||
}); |
Oops, something went wrong.