1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/4eaa644dd478/
changeset: 4eaa644dd478
user: carlfeberhard
date: 2012-11-28 16:45:01
summary: scatterplot: add header discovery from first dataset line; fix animation;
better hover info; fix column selection; pack scripts
affected #: 15 files
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa lib/galaxy/webapps/galaxy/api/datasets.py
--- a/lib/galaxy/webapps/galaxy/api/datasets.py
+++ b/lib/galaxy/webapps/galaxy/api/datasets.py
@@ -187,7 +187,6 @@
when the dataset is not yet indexed and hence using data would
be slow because indexes need to be created.
"""
-
# Dataset check.
msg = self.check_dataset_state( trans, dataset )
if msg:
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -1322,4 +1322,3 @@
def get_item( self, trans, id ):
return self.get_history( trans, id )
-
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa
lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -793,9 +793,23 @@
hda = self.get_dataset( trans, dataset_id, check_ownership=False,
check_accessible=True )
hda_dict = hda.get_api_value()
hda_dict[ 'id' ] = dataset_id
- if( hda_dict[ 'metadata_column_names' ] == None
- and hasattr( hda.datatype, 'column_names' ) ):
- hda_dict[ 'metadata_column_names' ] = hda.datatype.column_names
+
+ if( ( hda_dict[ 'metadata_column_names' ] == None )
+ and ( hasattr( hda.datatype, 'column_names' ) ) ):
+ hda_dict[ 'metadata_column_names' ] = hda.datatype.column_names
+
+ # try to get the first line (assuming it's a header)
+ #TODO: doesn't belong here
+ try:
+ with open( hda.file_name ) as infile:
+ for index, line in enumerate( infile ):
+ if 'comment_lines' not in hda_dict:
+ hda_dict[ 'comment_lines' ] = []
+ hda_dict[ 'comment_lines' ].append( line )
+ if index >= 3:
+ break
+ except Exception, exc:
+ log.error( str( exc ) )
history_id = trans.security.encode_id( hda.history.id )
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa
static/scripts/mvc/visualizations/scatterplotControlForm.js
--- a/static/scripts/mvc/visualizations/scatterplotControlForm.js
+++ b/static/scripts/mvc/visualizations/scatterplotControlForm.js
@@ -67,8 +67,9 @@
//logger : console,
className : 'scatterplot-control-form',
- dataLoadDelay : 500,
- dataLoadSize : 3001,
+ //NOTE: should include time needed to render
+ dataLoadDelay : 4000,
+ dataLoadSize : 5000,
loadingIndicatorImage : 'loading_small_white_bg.gif',
fetchMsg : 'Fetching data...',
@@ -107,6 +108,16 @@
}
this.log( '\t dataset:', this.dataset );
+ // attempt to get possible headers from the data's first line
+ if( this.dataset.comment_lines && this.dataset.comment_lines.length ){
+ //TODO:??
+ var firstLine = this.dataset.comment_lines[0],
+ possibleHeaders = firstLine.split( '\t' );
+ if( possibleHeaders.length === this.dataset.metadata_column_types.length ){
+ this.possibleHeaders = possibleHeaders;
+ }
+ }
+
// passed from mako helper
//TODO: integrate to galaxyPaths
//TODO: ?? seems like data loader section would be better
@@ -194,16 +205,24 @@
// controls for which columns are used to plot datapoints (and ids/additional
info to attach if desired)
var view = this,
allColumns = [],
- numericColumns = [];
-
+ numericColumns = [],
+ usePossibleHeaders = ( this.possibleHeaders && this.$dataControl )?
+ ( this.$dataControl.find( '#first-line-header-checkbox' ).is(
':checked' ) ):( false );
+
// gather column indeces (from metadata_column_types) and names (from
metadata_columnnames)
_.each( this.dataset.metadata_column_types, function( type, index ){
// use a 1 based index in names/values within the form (will be dec. when
parsed out)
var oneBasedIndex = index + 1,
- // label with the name if available (fall back on 'column
<index>')
+ // default name is 'column <index>'...
name = 'column ' + oneBasedIndex;
+
+ // ...but label with the name if available...
if( view.dataset.metadata_column_names ){
name = view.dataset.metadata_column_names[ index ];
+
+ // ...or, use the first line as headers if the user wants
+ } else if( usePossibleHeaders ){
+ name = view.possibleHeaders[ index ];
}
// cache all columns here
@@ -218,11 +237,17 @@
// render the html
var $dataControl = this.$el.find( '.tab-pane#data-control' );
- $dataControl.append( ScatterplotControlForm.templates.dataControl({
+ $dataControl.html( ScatterplotControlForm.templates.dataControl({
allColumns : allColumns,
- numericColumns : numericColumns
+ numericColumns : numericColumns,
+ possibleHeaders : ( this.possibleHeaders )?( this.possibleHeaders.join(
', ' ) ):( '' ),
+ usePossibleHeaders : usePossibleHeaders
}));
+ if( !this.dataset.metadata_column_names && this.possibleHeaders ){
+ $dataControl.find( '#first-line-header' ).show();
+ }
+
// preset to column selectors if they were passed in the config in the query
string
$dataControl.find( '#X-select' ).val( this.chartConfig.xColumn );
$dataControl.find( '#Y-select' ).val( this.chartConfig.yColumn );
@@ -288,6 +313,7 @@
// ------------------------------------------------------------------------- EVENTS
events : {
'change #include-id-checkbox' :
'toggleThirdColumnSelector',
+ 'change #first-line-header-checkbox' : 'rerenderDataControl',
'click #data-control #render-button' : 'renderChart',
'click #chart-control #render-button' : 'changeChartSettings'
},
@@ -296,6 +322,10 @@
// show/hide the id selector on the data settings panel
this.$el.find( 'select[name="ID"]' ).parent().toggle();
},
+
+ rerenderDataControl : function(){
+ this.$dataControl = this._render_dataControl();
+ },
showLoadingIndicator : function( message, callback ){
// display the loading indicator over the tab panels if hidden, update message
(if passed)
@@ -577,10 +607,8 @@
settings.yLabel = ( chartSettingsYLabel === 'Y' )?
( colSelections.Y.colName ):( chartSettingsYLabel );
- settings.animDuration = 10;
- if( this.$chartControl.find( '#animDuration.checkbox-input' ).is(
':checked' ) ){
- settings.animDuration = 500;
- }
+ settings.animDuration = ( this.$chartControl.find( '#animate-chart' ).is(
':checked' ) )?
+ ( this.chart.defaults.animDuration ):( 0 );
this.log( '\t chartSettings:', settings );
return settings;
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa
static/scripts/packed/mvc/visualizations/scatterplotControlForm.js
--- a/static/scripts/packed/mvc/visualizations/scatterplotControlForm.js
+++ b/static/scripts/packed/mvc/visualizations/scatterplotControlForm.js
@@ -1,1 +1,1 @@
-var
ScatterplotControlForm=BaseView.extend(LoggableMixin).extend({className:"scatterplot-control-form",dataLoadDelay:500,dataLoadSize:3001,loadingIndicatorImage:"loading_small_white_bg.gif",fetchMsg:"Fetching
data...",renderMsg:"Rendering...",initialize:function(a){this.log(this+".initialize,
attributes:",a);this.dataset=null;this.chartConfig=null;this.chart=null;this.loader=null;this.$dataControl=null;this.$chartControl=null;this.$statsDisplay=null;this.$chartDisplay=null;this.dataFetch=null;this.initializeFromAttributes(a);this.initializeChart(a);this.initializeDataLoader(a)},initializeFromAttributes:function(a){if(!a||!a.dataset){throw
("ScatterplotView requires a
dataset")}else{this.dataset=a.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(",
")}this.log("\t dataset:",this.dataset);if(!a.apiDatasetsURL){throw
("ScatterplotView requires a
apiDatasetsURL")}else{this.dataURL=a.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("\t
dataURL:",this.dataURL)},initializeChart:function(a){this.chartConfig=a.chartConfig||{};this.log("\t
initial chartConfig:",this.chartConfig);this.chart=new
TwoVarScatterplot(this.chartConfig);this.chartConfig=this.chart.config},initializeDataLoader:function(b){var
a=this;this.loader=new
LazyDataLoader({url:null,start:b.start||0,total:b.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(d,c){return
this.url+"&"+jQuery.param({start_val:d,max_vals:c})}});$(this.loader).bind("error",function(e,c,d){a.log("ERROR:",c,d);alert("ERROR
fetching
data:\n"+c+"\n"+d);a.hideLoadingIndicator()})},render:function(){this.log(this+".render");this.$el.append(ScatterplotControlForm.templates.mainLayout({loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage,message:""}));this.$dataControl=this._render_dataControl();this.$chartControl=this._render_chartControl();this.$statsDisplay=this.$el.find(".tab-pane#stats-display");this.$chartDisplay=this._render_chartDisplay();if(this.chartConfig.xColumn&&this.chartConfig.yColumn){this.renderChart()}this.$el.find(".tooltip").tooltip();return
this},_render_dataControl:function(){var
b=this,a=[],d=[];_.each(this.dataset.metadata_column_types,function(h,f){var
g=f+1,e="column
"+g;if(b.dataset.metadata_column_names){e=b.dataset.metadata_column_names[f]}a.push({index:g,name:e});if(h==="int"||h==="float"){d.push({index:g,name:e})}});var
c=this.$el.find(".tab-pane#data-control");c.append(ScatterplotControlForm.templates.dataControl({allColumns:a,numericColumns:d}));c.find("#X-select").val(this.chartConfig.xColumn);c.find("#Y-select").val(this.chartConfig.yColumn);if(this.chartConfig.idColumn!==undefined){c.find("#include-id-checkbox").attr("checked",true).trigger("change");c.find("#ID-select").val(this.chartConfig.idColumn)}return
c},_render_chartControl:function(){var
a=this,b=this.$el.find(".tab-pane#chart-control"),c={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};b.append(ScatterplotControlForm.templates.chartControl(this.chartConfig));b.find(".numeric-slider-input").each(function(){var
f=$(this),e=f.find(".slider-output"),g=f.find(".slider"),h=f.attr("id");function
d(){var
j=$(this),i=j.slider("value");e.text(i)}g.slider(_.extend(c[h],{value:a.chartConfig[h],change:d,slide:d}))});return
b},_render_chartDisplay:function(){var
a=this.$el.find(".tab-pane#chart-display");a.append(ScatterplotControlForm.templates.chartDisplay(this.chartConfig));return
a},events:{"change
#include-id-checkbox":"toggleThirdColumnSelector","click #data-control
#render-button":"renderChart","click #chart-control
#render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},showLoadingIndicator:function(b,c){b=b||"";var
a=this.$el.find("div#loading-indicator");messageBox=a.find(".loading-message");if(a.is(":visible")){if(b){messageBox.fadeOut("fast",function(){messageBox.text(b);messageBox.fadeIn("fast",c)})}else{c()}}else{if(b){messageBox.text(b)}a.fadeIn("fast",c)}},hideLoadingIndicator:function(a){this.$el.find("div#loading-indicator").fadeOut("fast",a)},renderChart:function(){this.log(this+".renderChart");this.data=null;this.meta=null;_.extend(this.chartConfig,this.getChartSettings());this.log("\t
chartConfig:",this.chartConfig);this.chart.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("\t
loader: total lines:",this.loader.total," url:",this.loader.url);var
a=this;$(this.loader).bind("loaded.new",function(c,b){a.log(a+"
loaded.new",b);a.postProcessDataFetchResponse(b);a.log("\t postprocessed
data:",a.data);a.log("\t postprocessed
meta:",a.meta);a.showLoadingIndicator(a.renderMsg,function(){a.chart.render(a.data,a.meta);a.renderStats(a.data,a.meta);a.hideLoadingIndicator()})});$(this.loader).bind("complete",function(b,c){a.log(a+"
complete",c);$(a.loader).unbind()});a.showLoadingIndicator(a.fetchMsg,function(){a.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show");a.loader.load()})},renderStats:function(){this.log(this+".renderStats");this.$statsDisplay.html(ScatterplotControlForm.templates.statsDisplay({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var
a=this;newChartSettings=this.getChartSettings();_.extend(this.chartConfig,newChartSettings);this.log("this.chartConfig:",this.chartConfig);this.chart.updateConfig(this.chartConfig,false);if(a.data&&a.meta){a.showLoadingIndicator(a.renderMsg,function(){a.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show");a.chart.render(a.data,a.meta);a.hideLoadingIndicator()})}else{this.renderChart()}},postProcessDataFetchResponse:function(a){this.postProcessData(a.data);this.postProcessMeta(a.meta)},postProcessData:function(b){var
a=this;if(a.data){_.each(b,function(d,c){a.data[c]=a.data[c].concat(d)})}else{a.data=b}},postProcessMeta:function(c){var
a=this,b=this.dataset.metadata_column_types;if(a.meta){_.each(c,function(e,d){var
i=a.meta[d],g=b[d];i.count+=(e.count)?(e.count):(0);if((g==="int")||(g==="float")){i.min=Math.min(e.min,i.min);i.max=Math.max(e.max,i.max);i.sum=e.sum+i.sum;i.mean=(i.count)?(i.sum/i.count):(null);var
f=a.data[d].slice().sort(),h=Math.floor(f.length/2);if(f.length%2===0){i.median=((f[h]+f[(h+1)])/2)}else{i.median=f[h]}}})}else{a.meta=c}},getDataSettings:function(){var
b=this.getColumnSelections(),a=[];this.log("\t
columnSelections:",b);a=[b.X.colIndex-1,b.Y.colIndex-1];if(this.$dataControl.find("#include-id-checkbox").attr("checked")){a.push(b.ID.colIndex-1)}var
c={data_type:"raw_data",columns:"["+a+"]"};this.log("\t
data settings (url params):",c);return c},getColumnSelections:function(){var
a={};this.$dataControl.find("div.column-select select").each(function(){var
b=$(this),c=b.val();a[b.attr("name")]={colIndex:c,colName:b.children('[value="'+c+'"]').text()}});return
a},getChartSettings:function(){var
c={},d=this.getColumnSelections();c.datapointSize=this.$chartControl.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");c.width=this.$chartControl.find("#width.numeric-slider-input").find(".slider").slider("value");c.height=this.$chartControl.find("#height.numeric-slider-input").find(".slider").slider("value");var
b=this.$chartControl.find("input#X-axis-label").val(),a=this.$chartControl.find("input#Y-axis-label").val();c.xLabel=(b==="X")?(d.X.colName):(b);c.yLabel=(a==="Y")?(d.Y.colName):(a);c.animDuration=10;if(this.$chartControl.find("#animDuration.checkbox-input").is(":checked")){c.animDuration=500}this.log("\t
chartSettings:",c);return
c},toString:function(){return"ScatterplotControlForm("+((this.dataset)?(this.dataset.id):(""))+")"}});ScatterplotControlForm.templates={mainLayout:Handlebars.templates["template-visualization-scatterplotControlForm"],dataControl:Handlebars.templates["template-visualization-dataControl"],chartControl:Handlebars.templates["template-visualization-chartControl"],statsDisplay:Handlebars.templates["template-visualization-statsDisplay"],chartDisplay:Handlebars.templates["template-visualization-chartDisplay"]};
\ No newline at end of file
+var
ScatterplotControlForm=BaseView.extend(LoggableMixin).extend({className:"scatterplot-control-form",dataLoadDelay:4000,dataLoadSize:5000,loadingIndicatorImage:"loading_small_white_bg.gif",fetchMsg:"Fetching
data...",renderMsg:"Rendering...",initialize:function(a){this.log(this+".initialize,
attributes:",a);this.dataset=null;this.chartConfig=null;this.chart=null;this.loader=null;this.$dataControl=null;this.$chartControl=null;this.$statsDisplay=null;this.$chartDisplay=null;this.dataFetch=null;this.initializeFromAttributes(a);this.initializeChart(a);this.initializeDataLoader(a)},initializeFromAttributes:function(a){if(!a||!a.dataset){throw
("ScatterplotView requires a
dataset")}else{this.dataset=a.dataset}if(jQuery.type(this.dataset.metadata_column_types)==="string"){this.dataset.metadata_column_types=this.dataset.metadata_column_types.split(",
")}this.log("\t
dataset:",this.dataset);if(this.dataset.comment_lines&&this.dataset.comment_lines.length){var
b=this.dataset.comment_lines[0],c=b.split("\t");if(c.length===this.dataset.metadata_column_types.length){this.possibleHeaders=c}}if(!a.apiDatasetsURL){throw
("ScatterplotView requires a
apiDatasetsURL")}else{this.dataURL=a.apiDatasetsURL+"/"+this.dataset.id+"?"}this.log("\t
dataURL:",this.dataURL)},initializeChart:function(a){this.chartConfig=a.chartConfig||{};this.log("\t
initial chartConfig:",this.chartConfig);this.chart=new
TwoVarScatterplot(this.chartConfig);this.chartConfig=this.chart.config},initializeDataLoader:function(b){var
a=this;this.loader=new
LazyDataLoader({url:null,start:b.start||0,total:b.total||this.dataset.metadata_data_lines,delay:this.dataLoadDelay,size:this.dataLoadSize,buildUrl:function(d,c){return
this.url+"&"+jQuery.param({start_val:d,max_vals:c})}});$(this.loader).bind("error",function(e,c,d){a.log("ERROR:",c,d);alert("ERROR
fetching
data:\n"+c+"\n"+d);a.hideLoadingIndicator()})},render:function(){this.log(this+".render");this.$el.append(ScatterplotControlForm.templates.mainLayout({loadingIndicatorImagePath:galaxy_paths.get("image_path")+"/"+this.loadingIndicatorImage,message:""}));this.$dataControl=this._render_dataControl();this.$chartControl=this._render_chartControl();this.$statsDisplay=this.$el.find(".tab-pane#stats-display");this.$chartDisplay=this._render_chartDisplay();if(this.chartConfig.xColumn&&this.chartConfig.yColumn){this.renderChart()}this.$el.find(".tooltip").tooltip();return
this},_render_dataControl:function(){var
b=this,a=[],e=[],c=(this.possibleHeaders&&this.$dataControl)?(this.$dataControl.find("#first-line-header-checkbox").is(":checked")):(false);_.each(this.dataset.metadata_column_types,function(i,g){var
h=g+1,f="column
"+h;if(b.dataset.metadata_column_names){f=b.dataset.metadata_column_names[g]}else{if(c){f=b.possibleHeaders[g]}}a.push({index:h,name:f});if(i==="int"||i==="float"){e.push({index:h,name:f})}});var
d=this.$el.find(".tab-pane#data-control");d.html(ScatterplotControlForm.templates.dataControl({allColumns:a,numericColumns:e,possibleHeaders:(this.possibleHeaders)?(this.possibleHeaders.join(",
")):(""),usePossibleHeaders:c}));if(!this.dataset.metadata_column_names&&this.possibleHeaders){d.find("#first-line-header").show()}d.find("#X-select").val(this.chartConfig.xColumn);d.find("#Y-select").val(this.chartConfig.yColumn);if(this.chartConfig.idColumn!==undefined){d.find("#include-id-checkbox").attr("checked",true).trigger("change");d.find("#ID-select").val(this.chartConfig.idColumn)}return
d},_render_chartControl:function(){var
a=this,b=this.$el.find(".tab-pane#chart-control"),c={datapointSize:{min:2,max:10,step:1},width:{min:200,max:800,step:20},height:{min:200,max:800,step:20}};b.append(ScatterplotControlForm.templates.chartControl(this.chartConfig));b.find(".numeric-slider-input").each(function(){var
f=$(this),e=f.find(".slider-output"),g=f.find(".slider"),h=f.attr("id");function
d(){var
j=$(this),i=j.slider("value");e.text(i)}g.slider(_.extend(c[h],{value:a.chartConfig[h],change:d,slide:d}))});return
b},_render_chartDisplay:function(){var
a=this.$el.find(".tab-pane#chart-display");a.append(ScatterplotControlForm.templates.chartDisplay(this.chartConfig));return
a},events:{"change
#include-id-checkbox":"toggleThirdColumnSelector","change
#first-line-header-checkbox":"rerenderDataControl","click
#data-control #render-button":"renderChart","click #chart-control
#render-button":"changeChartSettings"},toggleThirdColumnSelector:function(){this.$el.find('select[name="ID"]').parent().toggle()},rerenderDataControl:function(){this.$dataControl=this._render_dataControl()},showLoadingIndicator:function(b,c){b=b||"";var
a=this.$el.find("div#loading-indicator");messageBox=a.find(".loading-message");if(a.is(":visible")){if(b){messageBox.fadeOut("fast",function(){messageBox.text(b);messageBox.fadeIn("fast",c)})}else{c()}}else{if(b){messageBox.text(b)}a.fadeIn("fast",c)}},hideLoadingIndicator:function(a){this.$el.find("div#loading-indicator").fadeOut("fast",a)},renderChart:function(){this.log(this+".renderChart");this.data=null;this.meta=null;_.extend(this.chartConfig,this.getChartSettings());this.log("\t
chartConfig:",this.chartConfig);this.chart.updateConfig(this.chartConfig,false);this.loader.url=this.dataURL+"&"+jQuery.param(this.getDataSettings());this.log("\t
loader: total lines:",this.loader.total," url:",this.loader.url);var
a=this;$(this.loader).bind("loaded.new",function(c,b){a.log(a+"
loaded.new",b);a.postProcessDataFetchResponse(b);a.log("\t postprocessed
data:",a.data);a.log("\t postprocessed
meta:",a.meta);a.showLoadingIndicator(a.renderMsg,function(){a.chart.render(a.data,a.meta);a.renderStats(a.data,a.meta);a.hideLoadingIndicator()})});$(this.loader).bind("complete",function(b,c){a.log(a+"
complete",c);$(a.loader).unbind()});a.showLoadingIndicator(a.fetchMsg,function(){a.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show");a.loader.load()})},renderStats:function(){this.log(this+".renderStats");this.$statsDisplay.html(ScatterplotControlForm.templates.statsDisplay({stats:[{name:"Count",xval:this.meta[0].count,yval:this.meta[1].count},{name:"Min",xval:this.meta[0].min,yval:this.meta[1].min},{name:"Max",xval:this.meta[0].max,yval:this.meta[1].max},{name:"Sum",xval:this.meta[0].sum,yval:this.meta[1].sum},{name:"Mean",xval:this.meta[0].mean,yval:this.meta[1].mean},{name:"Median",xval:this.meta[0].median,yval:this.meta[1].median}]}))},changeChartSettings:function(){var
a=this;newChartSettings=this.getChartSettings();_.extend(this.chartConfig,newChartSettings);this.log("this.chartConfig:",this.chartConfig);this.chart.updateConfig(this.chartConfig,false);if(a.data&&a.meta){a.showLoadingIndicator(a.renderMsg,function(){a.$el.find("ul.nav").find('a[href="#chart-display"]').tab("show");a.chart.render(a.data,a.meta);a.hideLoadingIndicator()})}else{this.renderChart()}},postProcessDataFetchResponse:function(a){this.postProcessData(a.data);this.postProcessMeta(a.meta)},postProcessData:function(b){var
a=this;if(a.data){_.each(b,function(d,c){a.data[c]=a.data[c].concat(d)})}else{a.data=b}},postProcessMeta:function(c){var
a=this,b=this.dataset.metadata_column_types;if(a.meta){_.each(c,function(e,d){var
i=a.meta[d],g=b[d];i.count+=(e.count)?(e.count):(0);if((g==="int")||(g==="float")){i.min=Math.min(e.min,i.min);i.max=Math.max(e.max,i.max);i.sum=e.sum+i.sum;i.mean=(i.count)?(i.sum/i.count):(null);var
f=a.data[d].slice().sort(),h=Math.floor(f.length/2);if(f.length%2===0){i.median=((f[h]+f[(h+1)])/2)}else{i.median=f[h]}}})}else{a.meta=c}},getDataSettings:function(){var
b=this.getColumnSelections(),a=[];this.log("\t
columnSelections:",b);a=[b.X.colIndex-1,b.Y.colIndex-1];if(this.$dataControl.find("#include-id-checkbox").attr("checked")){a.push(b.ID.colIndex-1)}var
c={data_type:"raw_data",columns:"["+a+"]"};this.log("\t
data settings (url params):",c);return c},getColumnSelections:function(){var
a={};this.$dataControl.find("div.column-select select").each(function(){var
b=$(this),c=b.val();a[b.attr("name")]={colIndex:c,colName:b.children('[value="'+c+'"]').text()}});return
a},getChartSettings:function(){var
c={},d=this.getColumnSelections();c.datapointSize=this.$chartControl.find("#datapointSize.numeric-slider-input").find(".slider").slider("value");c.width=this.$chartControl.find("#width.numeric-slider-input").find(".slider").slider("value");c.height=this.$chartControl.find("#height.numeric-slider-input").find(".slider").slider("value");var
b=this.$chartControl.find("input#X-axis-label").val(),a=this.$chartControl.find("input#Y-axis-label").val();c.xLabel=(b==="X")?(d.X.colName):(b);c.yLabel=(a==="Y")?(d.Y.colName):(a);c.animDuration=(this.$chartControl.find("#animate-chart").is(":checked"))?(this.chart.defaults.animDuration):(0);this.log("\t
chartSettings:",c);return
c},toString:function(){return"ScatterplotControlForm("+((this.dataset)?(this.dataset.id):(""))+")"}});ScatterplotControlForm.templates={mainLayout:Handlebars.templates["template-visualization-scatterplotControlForm"],dataControl:Handlebars.templates["template-visualization-dataControl"],chartControl:Handlebars.templates["template-visualization-chartControl"],statsDisplay:Handlebars.templates["template-visualization-statsDisplay"],chartDisplay:Handlebars.templates["template-visualization-chartDisplay"]};
\ No newline at end of file
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa
static/scripts/packed/templates/compiled/template-visualization-chartControl.js
--- a/static/scripts/packed/templates/compiled/template-visualization-chartControl.js
+++ b/static/scripts/packed/templates/compiled/template-visualization-chartControl.js
@@ -1,1 +1,1 @@
-(function(){var
b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-chartControl"]=b(function(f,m,e,l,k){e=e||f.helpers;var
i="",c,h,g="function",j=this.escapeExpression,n=this;function
d(p,o){return' checked="true"'}i+='<p
class="help-text">\n Use the following controls to how the chart is
displayed.\n The slide controls can be moved by the mouse or, if the
\'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus
between controls by using the tab or shift+tab keys on your keyboard.\n Use the
\'Draw\' button to render (or re-render) the chart with the current settings.\n
</p>\n\n <div id="datapointSize" class="form-input
numeric-slider-input">\n <label for="datapointSize">Size of
data point: </label>\n <div
class="slider-output">';h=e.datapointSize;if(h){c=h.call(m,{hash:{}})}else{c=m.datapointSize;c=typeof
c===g?c():c}i+=j(c)+'</div>\n <div
class="slider"></div>\n <p class="form-help
help-text-small">\n Size of the graphic representation of each data
point\n </p>\n </div>\n\n <div id="animDuration"
class="form-input checkbox-input">\n <label
for="animated">Animate graph transitions?: </label>\n <input
type="checkbox" id="animated"\n class="checkbox
control"';c=m.animDuration;c=e["if"].call(m,c,{hash:{},inverse:n.noop,fn:n.program(1,d,k)});if(c||c===0){i+=c}i+='
/>\n <p class="form-help help-text-small">\n Uncheck
this to disable the animations used on the graph\n </p>\n </div>\n\n
<div id="width" class="form-input numeric-slider-input">\n
<label for="width">Graph width: </label>\n <div
class="slider-output">';h=e.width;if(h){c=h.call(m,{hash:{}})}else{c=m.width;c=typeof
c===g?c():c}i+=j(c)+'</div>\n <div
class="slider"></div>\n <p class="form-help
help-text-small">\n (not including graph margins and axes)\n
</p>\n </div>\n\n <div id="height" class="form-input
numeric-slider-input">\n <label for="height">Graph height:
</label>\n <div
class="slider-output">';h=e.height;if(h){c=h.call(m,{hash:{}})}else{c=m.height;c=typeof
c===g?c():c}i+=j(c)+'</div>\n <div
class="slider"></div>\n <p class="form-help
help-text-small">\n (not including graph margins and axes)\n
</p>\n </div>\n\n <div
id="X-axis-label"class="text-input form-input">\n <label
for="X-axis-label">Re-label the X axis: </label>\n <input
type="text" name="X-axis-label" id="X-axis-label"
value="';h=e.xLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.xLabel;c=typeof
c===g?c():c}i+=j(c)+'" />\n <p class="form-help
help-text-small"></p>\n </div>\n\n <div
id="Y-axis-label" class="text-input form-input">\n <label
for="Y-axis-label">Re-label the Y axis: </label>\n <input
type="text" name="Y-axis-label" id="Y-axis-label"
value="';h=e.yLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.yLabel;c=typeof
c===g?c():c}i+=j(c)+'" />\n <p class="form-help
help-text-small"></p>\n </div>\n\n <input
id="render-button" type="button" value="Draw"
/>';return i})})();
\ No newline at end of file
+(function(){var
b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-chartControl"]=b(function(f,m,e,l,k){e=e||f.helpers;var
i="",c,h,g="function",j=this.escapeExpression,n=this;function
d(p,o){return' checked="true"'}i+='<p
class="help-text">\n Use the following controls to how the chart is
displayed.\n The slide controls can be moved by the mouse or, if the
\'handle\' is in focus, your keyboard\'s arrow keys.\n Move the focus
between controls by using the tab or shift+tab keys on your keyboard.\n Use the
\'Draw\' button to render (or re-render) the chart with the current settings.\n
</p>\n\n <div id="datapointSize" class="form-input
numeric-slider-input">\n <label for="datapointSize">Size of
data point: </label>\n <div
class="slider-output">';h=e.datapointSize;if(h){c=h.call(m,{hash:{}})}else{c=m.datapointSize;c=typeof
c===g?c():c}i+=j(c)+'</div>\n <div
class="slider"></div>\n <p class="form-help
help-text-small">\n Size of the graphic representation of each data
point\n </p>\n </div>\n\n <div id="animDuration"
class="form-input checkbox-input">\n <label
for="animate-chart">Animate chart transitions?: </label>\n
<input type="checkbox" id="animate-chart"\n
class="checkbox
control"';c=m.animDuration;c=e["if"].call(m,c,{hash:{},inverse:n.noop,fn:n.program(1,d,k)});if(c||c===0){i+=c}i+='
/>\n <p class="form-help help-text-small">\n Uncheck
this to disable the animations used on the chart\n </p>\n </div>\n\n
<div id="width" class="form-input numeric-slider-input">\n
<label for="width">Chart width: </label>\n <div
class="slider-output">';h=e.width;if(h){c=h.call(m,{hash:{}})}else{c=m.width;c=typeof
c===g?c():c}i+=j(c)+'</div>\n <div
class="slider"></div>\n <p class="form-help
help-text-small">\n (not including chart margins and axes)\n
</p>\n </div>\n\n <div id="height" class="form-input
numeric-slider-input">\n <label for="height">Chart height:
</label>\n <div
class="slider-output">';h=e.height;if(h){c=h.call(m,{hash:{}})}else{c=m.height;c=typeof
c===g?c():c}i+=j(c)+'</div>\n <div
class="slider"></div>\n <p class="form-help
help-text-small">\n (not including chart margins and axes)\n
</p>\n </div>\n\n <div
id="X-axis-label"class="text-input form-input">\n <label
for="X-axis-label">Re-label the X axis: </label>\n <input
type="text" name="X-axis-label" id="X-axis-label"
value="';h=e.xLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.xLabel;c=typeof
c===g?c():c}i+=j(c)+'" />\n <p class="form-help
help-text-small"></p>\n </div>\n\n <div
id="Y-axis-label" class="text-input form-input">\n <label
for="Y-axis-label">Re-label the Y axis: </label>\n <input
type="text" name="Y-axis-label" id="Y-axis-label"
value="';h=e.yLabel;if(h){c=h.call(m,{hash:{}})}else{c=m.yLabel;c=typeof
c===g?c():c}i+=j(c)+'" />\n <p class="form-help
help-text-small"></p>\n </div>\n\n <input
id="render-button" type="button" value="Draw"
/>';return i})})();
\ No newline at end of file
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa
static/scripts/packed/templates/compiled/template-visualization-dataControl.js
--- a/static/scripts/packed/templates/compiled/template-visualization-dataControl.js
+++ b/static/scripts/packed/templates/compiled/template-visualization-dataControl.js
@@ -1,1 +1,1 @@
-(function(){var
b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-dataControl"]=b(function(g,m,f,l,k){f=f||g.helpers;var
i="",d,h="function",j=this.escapeExpression,o=this;function e(t,s){var
q="",r,p;q+='\n <option
value="';p=f.index;if(p){r=p.call(t,{hash:{}})}else{r=t.index;r=typeof
r===h?r():r}q+=j(r)+'">';p=f.name;if(p){r=p.call(t,{hash:{}})}else{r=t.name;r=typeof
r===h?r():r}q+=j(r)+"</option>\n ";return q}function c(t,s){var
q="",r,p;q+='\n <option
value="';p=f.index;if(p){r=p.call(t,{hash:{}})}else{r=t.index;r=typeof
r===h?r():r}q+=j(r)+'">';p=f.name;if(p){r=p.call(t,{hash:{}})}else{r=t.name;r=typeof
r===h?r():r}q+=j(r)+"</option>\n ";return q}function n(t,s){var
q="",r,p;q+='\n <option
value="';p=f.index;if(p){r=p.call(t,{hash:{}})}else{r=t.index;r=typeof
r===h?r():r}q+=j(r)+'">';p=f.name;if(p){r=p.call(t,{hash:{}})}else{r=t.name;r=typeof
r===h?r():r}q+=j(r)+"</option>\n ";return q}i+="<p
class=\"help-text\">\n Use the following controls to change the data
used by the chart.\n Use the 'Draw' button to render (or re-render) the
chart with the current settings.\n </p>\n\n ";i+='\n <div
class="column-select">\n <label for="X-select">Data
column for X: </label>\n <select name="X"
id="X-select">\n
';d=m.numericColumns;d=f.each.call(m,d,{hash:{},inverse:o.noop,fn:o.program(1,e,k)});if(d||d===0){i+=d}i+='\n
</select>\n </div>\n <div
class="column-select">\n <label for="Y-select">Data
column for Y: </label>\n <select name="Y"
id="Y-select">\n
';d=m.numericColumns;d=f.each.call(m,d,{hash:{},inverse:o.noop,fn:o.program(3,c,k)});if(d||d===0){i+=d}i+="\n
</select>\n </div>\n\n ";i+='\n <div
id="include-id">\n <label
for="include-id-checkbox">Include a third column as data point
IDs?</label>\n <input type="checkbox"
name="include-id" id="include-id-checkbox" />\n <p
class="help-text-small">\n These will be displayed (along with the
x and y values) when you hover over\n a data point.\n </p>\n
</div>\n <div class="column-select" style="display:
none">\n <label for="ID-select">Data column for IDs:
</label>\n <select name="ID" id="ID-select">\n
';d=m.allColumns;d=f.each.call(m,d,{hash:{},inverse:o.noop,fn:o.program(5,n,k)});if(d||d===0){i+=d}i+='\n
</select>\n </div>\n\n <input id="render-button"
type="button" value="Draw" />\n <div
class="clear"></div>';return i})})();
\ No newline at end of file
+(function(){var
b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-dataControl"]=b(function(g,n,f,m,l){f=f||g.helpers;var
j="",d,i,h="function",k=this.escapeExpression,q=this;function
e(v,u){var s="",t,r;s+='\n <option
value="';r=f.index;if(r){t=r.call(v,{hash:{}})}else{t=v.index;t=typeof
t===h?t():t}s+=k(t)+'">';r=f.name;if(r){t=r.call(v,{hash:{}})}else{t=v.name;t=typeof
t===h?t():t}s+=k(t)+"</option>\n ";return s}function c(v,u){var
s="",t,r;s+='\n <option
value="';r=f.index;if(r){t=r.call(v,{hash:{}})}else{t=v.index;t=typeof
t===h?t():t}s+=k(t)+'">';r=f.name;if(r){t=r.call(v,{hash:{}})}else{t=v.name;t=typeof
t===h?t():t}s+=k(t)+"</option>\n ";return s}function p(v,u){var
s="",t,r;s+='\n <option
value="';r=f.index;if(r){t=r.call(v,{hash:{}})}else{t=v.index;t=typeof
t===h?t():t}s+=k(t)+'">';r=f.name;if(r){t=r.call(v,{hash:{}})}else{t=v.name;t=typeof
t===h?t():t}s+=k(t)+"</option>\n ";return s}function
o(s,r){return'checked="true"'}j+="<p
class=\"help-text\">\n Use the following controls to change the data
used by the chart.\n Use the 'Draw' button to render (or re-render) the
chart with the current settings.\n </p>\n\n ";j+='\n <div
class="column-select">\n <label for="X-select">Data
column for X: </label>\n <select name="X"
id="X-select">\n
';d=n.numericColumns;d=f.each.call(n,d,{hash:{},inverse:q.noop,fn:q.program(1,e,l)});if(d||d===0){j+=d}j+='\n
</select>\n </div>\n <div
class="column-select">\n <label for="Y-select">Data
column for Y: </label>\n <select name="Y"
id="Y-select">\n
';d=n.numericColumns;d=f.each.call(n,d,{hash:{},inverse:q.noop,fn:q.program(3,c,l)});if(d||d===0){j+=d}j+="\n
</select>\n </div>\n\n ";j+='\n <div
id="include-id">\n <label
for="include-id-checkbox">Include a third column as data point
IDs?</label>\n <input type="checkbox"
name="include-id" id="include-id-checkbox" />\n <p
class="help-text-small">\n These will be displayed (along with the
x and y values) when you hover over\n a data point.\n </p>\n
</div>\n <div class="column-select" style="display:
none">\n <label for="ID-select">Data column for IDs:
</label>\n <select name="ID" id="ID-select">\n
';d=n.allColumns;d=f.each.call(n,d,{hash:{},inverse:q.noop,fn:q.program(5,p,l)});if(d||d===0){j+=d}j+="\n
</select>\n </div>\n\n ";j+='\n <div
id="first-line-header" style="display: none;">\n
<p>Possible headers:
';i=f.possibleHeaders;if(i){d=i.call(n,{hash:{}})}else{d=n.possibleHeaders;d=typeof
d===h?d():d}j+=k(d)+'\n </p>\n <label
for="first-line-header-checkbox">Use the above as column
headers?</label>\n <input type="checkbox"
name="include-id" id="first-line-header-checkbox"\n
';d=n.usePossibleHeaders;d=f["if"].call(n,d,{hash:{},inverse:q.noop,fn:q.program(7,o,l)});if(d||d===0){j+=d}j+='/>\n
<p class="help-text-small">\n It looks like Galaxy
couldn\'t get proper column headers for this data.\n Would you like to use
the column headers above as column names to select columns?\n </p>\n
</div>\n\n <input id="render-button" type="button"
value="Draw" />\n <div
class="clear"></div>';return j})})();
\ No newline at end of file
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa static/scripts/packed/utils/LazyDataLoader.js
--- a/static/scripts/packed/utils/LazyDataLoader.js
+++ b/static/scripts/packed/utils/LazyDataLoader.js
@@ -1,1 +1,1 @@
-function LazyDataLoader(c){var
a=this,d="loaded.new",b="complete";ERROR_EVENT="error";jQuery.extend(a,LoggableMixin);jQuery.extend(a,{total:undefined,url:undefined,currentIntervalId:undefined,data:[],delay:500,start:0,size:1000,initialize:function(e){jQuery.extend(a,e);if(e.hasOwnProperty("initialize")){e.initialize.call(a,e)}this.log(this+"
initialized:",a)},buildUrl:function(f,e){return
this.url+"&"+jQuery.param({start_val:f,max_vals:e})},ajaxErrorFn:function(g,e,f){},load:function(h){this.log(this+".load");if(!a.url){throw
(a+" requires a url")}if(this.total===null){this.log("\t total is null
(will load all)")}else{this.log("\t total:",this.total)}var
g=a.size;if((a.total!==null)&&(a.total<a.size)){g=a.total}a.log(a+"\t
beginning recursion");f(a.start,g);function f(k,j){a.log(a+".loadHelper,
start:",k,"size:",j);var i=a.buildUrl(k,j);a.log("\t
url:",i);jQuery.ajax({url:a.buildUrl(k,j),dataType:"json",error:function(n,l,m){a.log("\t
ajax error,
status:",l,"error:",m);if(a.currentIntervalId){clearInterval(a.currentIntervalId)}$(a).trigger(ERROR_EVENT,[l,m]);a.ajaxErrorFn(n,l,m)},success:function(l){a.log("\t
ajax success,
response:",l,"next:",m,"remainder:",n);if(l!==null){a.data.push(l);$(a).trigger(d,[l,k,j]);var
m=k+j,n=a.size;if(a.total!==null){n=Math.min(a.total-m,a.size)}a.log("\t next
recursion,
start:",m,"size:",n);if(a.total===null||n>0){a.currentIntervalId=setTimeout(function(){f(m,n)},a.delay);a.log("\t
currentIntervalId:",a.currentIntervalId)}else{e()}}else{e()}}})}function
e(){a.log(a+".loadHelper, has
finished:",a.data);$(a).trigger(b,[a.data,a.total]);if(h){h(a.data)}}},toString:function(){return"LazyDataLoader"}});a.initialize(c);return
a};
\ No newline at end of file
+function LazyDataLoader(c){var
a=this,d="loaded.new",b="complete";ERROR_EVENT="error";jQuery.extend(a,LoggableMixin);jQuery.extend(a,{total:undefined,url:undefined,currentIntervalId:undefined,data:[],delay:4000,start:0,size:4000,initialize:function(e){jQuery.extend(a,e);if(e.hasOwnProperty("initialize")){e.initialize.call(a,e)}this.log(this+"
initialized:",a)},buildUrl:function(f,e){return
this.url+"&"+jQuery.param({start_val:f,max_vals:e})},ajaxErrorFn:function(g,e,f){},load:function(h){this.log(this+".load");if(!a.url){throw
(a+" requires a url")}if(this.total===null){this.log("\t total is null
(will load all)")}else{this.log("\t total:",this.total)}var
g=a.size;if((a.total!==null)&&(a.total<a.size)){g=a.total}a.log(a+"\t
beginning recursion");f(a.start,g);function f(k,j){a.log(a+".loadHelper,
start:",k,"size:",j);var i=a.buildUrl(k,j);a.log("\t
url:",i);jQuery.ajax({url:a.buildUrl(k,j),dataType:"json",error:function(n,l,m){a.log("\t
ajax error,
status:",l,"error:",m);if(a.currentIntervalId){clearInterval(a.currentIntervalId)}$(a).trigger(ERROR_EVENT,[l,m]);a.ajaxErrorFn(n,l,m)},success:function(l){a.log("\t
ajax success,
response:",l,"next:",m,"remainder:",n);if(l!==null){a.data.push(l);$(a).trigger(d,[l,k,j]);var
m=k+j,n=a.size;if(a.total!==null){n=Math.min(a.total-m,a.size)}a.log("\t next
recursion,
start:",m,"size:",n);if(a.total===null||n>0){a.currentIntervalId=setTimeout(function(){f(m,n)},a.delay);a.log("\t
currentIntervalId:",a.currentIntervalId)}else{e()}}else{e()}}})}function
e(){a.log(a+".loadHelper, has
finished:",a.data);$(a).trigger(b,[a.data,a.total]);if(h){h(a.data)}}},toString:function(){return"LazyDataLoader"}});a.initialize(c);return
a};
\ No newline at end of file
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa static/scripts/packed/viz/scatterplot.js
--- a/static/scripts/packed/viz/scatterplot.js
+++ b/static/scripts/packed/viz/scatterplot.js
@@ -1,1 +1,1 @@
-function TwoVarScatterplot(d){var
b=10,f=7,e=10,c=8,a=5;this.log=function(){if(this.debugging&&console&&console.debug){var
g=Array.prototype.slice.call(arguments);g.unshift(this.toString());console.debug.apply(console,g)}};this.log("new
TwoVarScatterplot:",d);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-35,width:400,height:400,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,d);this.log("intial
config:",this.config);this.updateConfig=function(g,h){_.extend(this.config,g);this.log(this+".updateConfig:",this.config)};this.toString=function(){return
this.config.id};this.translateStr=function(g,h){return"translate("+g+","+h+")"};this.rotateStr=function(h,g,i){return"rotate("+h+","+g+","+i+")"};this.adjustChartDimensions=function(j,h,g,i){j=j||0;h=h||0;g=g||0;i=i||0;this.svg.attr("width",this.config.width+(this.config.marginRight+h)+(this.config.marginLeft+i)).attr("height",this.config.height+(this.config.marginTop+j)+(this.config.marginBottom+g)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+i,this.config.marginTop+j))};this.preprocessData=function(i,h,g){return(i.length>this.config.maxDataPoints)?(i.slice(0,this.config.maxDataPoints)):(i)};this.findMinMaxes=function(g,i,h){this.xMin=this.config.xMin||(h)?(h[0].min):(d3.min(g));this.xMax=this.config.xMax||(h)?(h[0].max):(d3.max(g));this.yMin=this.config.yMin||(h)?(h[1].min):(d3.min(i));this.yMax=this.config.yMax||(h)?(h[1].max):(d3.max(i))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);var
g=d3.max(_.map([this.xMin,this.xMax],function(h){return(String(h)).length}));if(g>=a){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.log("this.config.xLabel:",this.config.xLabel);this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel);this.log("xAxisLabel:",this.xAxisLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var
g=this.yAxis.selectAll("text").filter(function(k,j){return
j!==0});this.log("yTickLabels:",g);this.yLongestLabel=d3.max(g[0].map(function(k,j){return(d3.select(k).text()).length}))||0;var
h=b+(this.yLongestLabel*f)+c+e;this.config.yAxisLabelBumpX=-(h-e);if(this.config.marginLeft<h){var
i=(h)-this.config.marginLeft;i=(i<0)?(0):(i);this.adjustChartDimensions(0,0,0,i)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line
v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line
h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.glyphEnterState=function(g){};this.glyphFinalState=function(g){};this.glyphExitState=function(g){};this.renderDatapoints=function(g,j,h){this.log(this+".renderDatapoints",arguments);var
i=0;this.datapoints=this.addDatapoints(g,j,h,".glyph");this.datapoints.exit().each(function(){i+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(i,"
glyphs
removed")};this.addDatapoints=function(k,i,g,j){this.log(this+".addDatapoints",arguments);var
n=this,m=0,o=function(q,p){return n.xScale(k[p])},h=function(q,p){return
n.yScale(i[p])};var l=this.content.selectAll(j);this.log("existing
datapoints:",l);l=l.data(k);m=0;l.enter().append("svg:circle").each(function(){m+=1}).classed("glyph",true).attr("cx",o).attr("cy",h).attr("r",0);this.log(m,"
new glyphs
created");m=0;l.transition().duration(this.config.animDuration).each(function(){m+=1}).attr("cx",o).attr("cy",h).attr("r",n.config.datapointSize);this.log(m,"
existing glyphs
transitioned");if(g){l.attr("data",function(q,p){return(g[p])})}l.attr("svg:title",function(q,p){return((g)?(g[p]+":
"):(""))+k[p]+",
"+i[p]});l.on("mouseover",function(r,p){var
q=d3.select(this);q.style("fill","red").style("fill-opacity",1);n.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",q.attr("cx")).attr("y1",q.attr("cy")).attr("x2",0).attr("y2",q.attr("cy")).classed("hoverline",true);n.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",q.attr("cx")).attr("y1",q.attr("cy")).attr("x2",q.attr("cx")).attr("y2",n.config.height).classed("hoverline",true)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);d3.selectAll(".hoverline").remove()});return
l};this.render=function(i,j){this.log(this+".render",arguments);this.log("\t
config:",this.config);var
g=i[0],k=i[1],h=(i.length>2)?(i[2]):(undefined);g=this.preprocessData(g);k=this.preprocessData(k);this.log("xCol
len",g.length,"yCol
len",k.length);this.findMinMaxes(g,k,j);this.setUpScales();if(!this.svg){this.svg=d3.select("svg").attr("class","chart")}if(!this.content){this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id)}this.adjustChartDimensions();if(!this.xAxis){this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis")}if(!this.xAxisLabel){this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label")}if(!this.yAxis){this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis")}if(!this.yAxisLabel){this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label")}this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(g,k,h)}};
\ No newline at end of file
+function TwoVarScatterplot(d){var
b=10,f=7,e=10,c=8,a=5;this.log=function(){if(this.debugging&&console&&console.debug){var
g=Array.prototype.slice.call(arguments);g.unshift(this.toString());console.debug.apply(console,g)}};this.log("new
TwoVarScatterplot:",d);this.defaults={id:"TwoVarScatterplot",containerSelector:"body",maxDataPoints:30000,datapointSize:4,animDuration:500,xNumTicks:10,yNumTicks:10,xAxisLabelBumpY:40,yAxisLabelBumpX:-40,width:400,height:400,marginTop:50,marginRight:50,marginBottom:50,marginLeft:50,xMin:null,xMax:null,yMin:null,yMax:null,xLabel:"X",yLabel:"Y"};this.config=_.extend({},this.defaults,d);this.log("intial
config:",this.config);this.updateConfig=function(g,h){_.extend(this.config,g);this.log(this+".updateConfig:",this.config)};this.toString=function(){return
this.config.id};this.translateStr=function(g,h){return"translate("+g+","+h+")"};this.rotateStr=function(h,g,i){return"rotate("+h+","+g+","+i+")"};this.adjustChartDimensions=function(j,h,g,i){j=j||0;h=h||0;g=g||0;i=i||0;this.svg.attr("width",this.config.width+(this.config.marginRight+h)+(this.config.marginLeft+i)).attr("height",this.config.height+(this.config.marginTop+j)+(this.config.marginBottom+g)).style("display","block");this.content=this.svg.select("g.content").attr("transform",this.translateStr(this.config.marginLeft+i,this.config.marginTop+j))};this.preprocessData=function(i,h,g){return(i.length>this.config.maxDataPoints)?(i.slice(0,this.config.maxDataPoints)):(i)};this.findMinMaxes=function(g,i,h){this.xMin=this.config.xMin||(h)?(h[0].min):(d3.min(g));this.xMax=this.config.xMax||(h)?(h[0].max):(d3.max(g));this.yMin=this.config.yMin||(h)?(h[1].min):(d3.min(i));this.yMax=this.config.yMax||(h)?(h[1].max):(d3.max(i))};this.setUpScales=function(){this.xScale=d3.scale.linear().domain([this.xMin,this.xMax]).range([0,this.config.width]),this.yScale=d3.scale.linear().domain([this.yMin,this.yMax]).range([this.config.height,0])};this.setUpXAxis=function(){this.xAxisFn=d3.svg.axis().scale(this.xScale).ticks(this.config.xNumTicks).orient("bottom");this.xAxis.attr("transform",this.translateStr(0,this.config.height)).call(this.xAxisFn);var
g=d3.max(_.map([this.xMin,this.xMax],function(h){return(String(h)).length}));if(g>=a){this.xAxis.selectAll("g").filter(":nth-child(odd)").style("display","none")}this.log("this.config.xLabel:",this.config.xLabel);this.xAxisLabel.attr("x",this.config.width/2).attr("y",this.config.xAxisLabelBumpY).attr("text-anchor","middle").text(this.config.xLabel);this.log("xAxisLabel:",this.xAxisLabel)};this.setUpYAxis=function(){this.yAxisFn=d3.svg.axis().scale(this.yScale).ticks(this.config.yNumTicks).orient("left");this.yAxis.call(this.yAxisFn);var
g=this.yAxis.selectAll("text").filter(function(k,j){return
j!==0});this.log("yTickLabels:",g);this.yLongestLabel=d3.max(g[0].map(function(k,j){return(d3.select(k).text()).length}))||0;var
h=b+(this.yLongestLabel*f)+c+e;this.config.yAxisLabelBumpX=-(h-e);if(this.config.marginLeft<h){var
i=(h)-this.config.marginLeft;i=(i<0)?(0):(i);this.adjustChartDimensions(0,0,0,i)}this.yAxisLabel.attr("x",this.config.yAxisLabelBumpX).attr("y",this.config.height/2).attr("text-anchor","middle").attr("transform",this.rotateStr(-90,this.config.yAxisLabelBumpX,this.config.height/2)).text(this.config.yLabel)};this.renderGrid=function(){this.vGridLines=this.content.selectAll("line.v-grid-line").data(this.xScale.ticks(this.xAxisFn.ticks()[0]));this.vGridLines.enter().append("svg:line").classed("grid-line
v-grid-line",true);this.vGridLines.attr("x1",this.xScale).attr("y1",0).attr("x2",this.xScale).attr("y2",this.config.height);this.vGridLines.exit().remove();this.hGridLines=this.content.selectAll("line.h-grid-line").data(this.yScale.ticks(this.yAxisFn.ticks()[0]));this.hGridLines.enter().append("svg:line").classed("grid-line
h-grid-line",true);this.hGridLines.attr("x1",0).attr("y1",this.yScale).attr("x2",this.config.width).attr("y2",this.yScale);this.hGridLines.exit().remove()};this.renderDatapoints=function(g,n,j){this.log(this+".renderDatapoints",arguments);var
k=0,m=this,i=function(p,o){return m.xScale(g[o])},h=function(p,o){return
m.yScale(n[o])};var
l=this.content.selectAll(".glyph").data(g);k=0;l.enter().append("svg:circle").each(function(){k+=1}).classed("glyph",true).attr("cx",0).attr("cy",this.config.height).attr("r",0);this.log(k,"
new glyphs
created");k=0;l.transition().duration(this.config.animDuration).each(function(){k+=1}).attr("cx",i).attr("cy",h).attr("r",m.config.datapointSize);this.log(k,"
existing glyphs
transitioned");l.exit().each(function(){k+=1}).transition().duration(this.config.animDuration).attr("cy",this.config.height).attr("r",0).remove();this.log(k,"
glyphs
removed");this._addDatapointEventhandlers(l,g,n,j)};this._addDatapointEventhandlers=function(j,g,k,h){var
i=this;j.on("mouseover",function(o,l){var
n=d3.select(this);n.style("fill","red").style("fill-opacity",1);i.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",n.attr("cx")-i.config.datapointSize).attr("y1",n.attr("cy")).attr("x2",0).attr("y2",n.attr("cy")).classed("hoverline",true);if(n.attr("cy")<i.config.height){i.content.append("line").attr("stroke","red").attr("stroke-width",1).attr("x1",n.attr("cx")).attr("y1",n.attr("cy")+i.config.datapointSize).attr("x2",n.attr("cx")).attr("y2",i.config.height).classed("hoverline",true)}var
m=$(this).offset();i.datapointInfoBox=i.infoBox(m.top,m.left,i.infoHtml(g[l],k[l],(h)?(h[l]):(undefined)));$("body").append(i.datapointInfoBox)}).on("mouseout",function(){d3.select(this).style("fill","black").style("fill-opacity",0.2);i.content.selectAll(".hoverline").remove();if(i.datapointInfoBox){i.datapointInfoBox.remove()}})},this.render=function(i,j){this.log(this+".render",arguments);this.log("\t
config:",this.config);var
g=i[0],k=i[1],h=(i.length>2)?(i[2]):(undefined);g=this.preprocessData(g);k=this.preprocessData(k);this.log("xCol
len",g.length,"yCol
len",k.length);this.findMinMaxes(g,k,j);this.setUpScales();if(!this.svg){this.svg=d3.select("svg").attr("class","chart")}if(!this.content){this.content=this.svg.append("svg:g").attr("class","content").attr("id",this.config.id)}this.adjustChartDimensions();if(!this.xAxis){this.xAxis=this.content.append("g").attr("class","axis").attr("id","x-axis")}if(!this.xAxisLabel){this.xAxisLabel=this.xAxis.append("text").attr("class","axis-label").attr("id","x-axis-label")}if(!this.yAxis){this.yAxis=this.content.append("g").attr("class","axis").attr("id","y-axis")}if(!this.yAxisLabel){this.yAxisLabel=this.yAxis.append("text").attr("class","axis-label").attr("id","y-axis-label")}this.setUpXAxis();this.setUpYAxis();this.renderGrid();this.renderDatapoints(g,k,h)};this.infoHtml=function(g,j,i){var
h=$("<div/>");if(i){$("<div/>").text(i).css("font-weight","bold").appendTo(h)}$("<div/>").text(g).appendTo(h);$("<div/>").text(j).appendTo(h);return
h.html()};this.infoBox=function(l,k,i,h,g){h=h||0;g=g||20;var j=$("<div
/>").addClass("chart-info-box").css({position:"absolute",top:l+h,left:k+g});j.html(i);return
j}};
\ No newline at end of file
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa
static/scripts/templates/compiled/template-visualization-chartControl.js
--- a/static/scripts/templates/compiled/template-visualization-chartControl.js
+++ b/static/scripts/templates/compiled/template-visualization-chartControl.js
@@ -13,19 +13,19 @@
foundHelper = helpers.datapointSize;
if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
else { stack1 = depth0.datapointSize; stack1 = typeof stack1 === functionType ?
stack1() : stack1; }
- buffer += escapeExpression(stack1) + "</div>\n <div
class=\"slider\"></div>\n <p class=\"form-help
help-text-small\">\n Size of the graphic representation of each data
point\n </p>\n </div>\n\n <div id=\"animDuration\"
class=\"form-input checkbox-input\">\n <label
for=\"animated\">Animate graph transitions?: </label>\n
<input type=\"checkbox\" id=\"animated\"\n
class=\"checkbox control\"";
+ buffer += escapeExpression(stack1) + "</div>\n <div
class=\"slider\"></div>\n <p class=\"form-help
help-text-small\">\n Size of the graphic representation of each data
point\n </p>\n </div>\n\n <div id=\"animDuration\"
class=\"form-input checkbox-input\">\n <label
for=\"animate-chart\">Animate chart transitions?: </label>\n
<input type=\"checkbox\" id=\"animate-chart\"\n
class=\"checkbox control\"";
stack1 = depth0.animDuration;
stack1 = helpers['if'].call(depth0, stack1,
{hash:{},inverse:self.noop,fn:self.program(1, program1, data)});
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += " />\n <p class=\"form-help
help-text-small\">\n Uncheck this to disable the animations used on the
graph\n </p>\n </div>\n\n <div id=\"width\"
class=\"form-input numeric-slider-input\">\n <label
for=\"width\">Graph width: </label>\n <div
class=\"slider-output\">";
+ buffer += " />\n <p class=\"form-help
help-text-small\">\n Uncheck this to disable the animations used on the
chart\n </p>\n </div>\n\n <div id=\"width\"
class=\"form-input numeric-slider-input\">\n <label
for=\"width\">Chart width: </label>\n <div
class=\"slider-output\">";
foundHelper = helpers.width;
if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
else { stack1 = depth0.width; stack1 = typeof stack1 === functionType ? stack1() :
stack1; }
- buffer += escapeExpression(stack1) + "</div>\n <div
class=\"slider\"></div>\n <p class=\"form-help
help-text-small\">\n (not including graph margins and axes)\n
</p>\n </div>\n\n <div id=\"height\"
class=\"form-input numeric-slider-input\">\n <label
for=\"height\">Graph height: </label>\n <div
class=\"slider-output\">";
+ buffer += escapeExpression(stack1) + "</div>\n <div
class=\"slider\"></div>\n <p class=\"form-help
help-text-small\">\n (not including chart margins and axes)\n
</p>\n </div>\n\n <div id=\"height\"
class=\"form-input numeric-slider-input\">\n <label
for=\"height\">Chart height: </label>\n <div
class=\"slider-output\">";
foundHelper = helpers.height;
if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
else { stack1 = depth0.height; stack1 = typeof stack1 === functionType ? stack1() :
stack1; }
- buffer += escapeExpression(stack1) + "</div>\n <div
class=\"slider\"></div>\n <p class=\"form-help
help-text-small\">\n (not including graph margins and axes)\n
</p>\n </div>\n\n <div
id=\"X-axis-label\"class=\"text-input form-input\">\n
<label for=\"X-axis-label\">Re-label the X axis: </label>\n
<input type=\"text\" name=\"X-axis-label\"
id=\"X-axis-label\" value=\"";
+ buffer += escapeExpression(stack1) + "</div>\n <div
class=\"slider\"></div>\n <p class=\"form-help
help-text-small\">\n (not including chart margins and axes)\n
</p>\n </div>\n\n <div
id=\"X-axis-label\"class=\"text-input form-input\">\n
<label for=\"X-axis-label\">Re-label the X axis: </label>\n
<input type=\"text\" name=\"X-axis-label\"
id=\"X-axis-label\" value=\"";
foundHelper = helpers.xLabel;
if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
else { stack1 = depth0.xLabel; stack1 = typeof stack1 === functionType ? stack1() :
stack1; }
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa
static/scripts/templates/compiled/template-visualization-dataControl.js
--- a/static/scripts/templates/compiled/template-visualization-dataControl.js
+++ b/static/scripts/templates/compiled/template-visualization-dataControl.js
@@ -2,7 +2,7 @@
var template = Handlebars.template, templates = Handlebars.templates =
Handlebars.templates || {};
templates['template-visualization-dataControl'] = template(function
(Handlebars,depth0,helpers,partials,data) {
helpers = helpers || Handlebars.helpers;
- var buffer = "", stack1, functionType="function",
escapeExpression=this.escapeExpression, self=this;
+ var buffer = "", stack1, foundHelper, functionType="function",
escapeExpression=this.escapeExpression, self=this;
function program1(depth0,data) {
@@ -46,6 +46,11 @@
buffer += escapeExpression(stack1) + "</option>\n ";
return buffer;}
+function program7(depth0,data) {
+
+
+ return "checked=\"true\"";}
+
buffer += "<p class=\"help-text\">\n Use the following
controls to change the data used by the chart.\n Use the 'Draw' button to
render (or re-render) the chart with the current settings.\n </p>\n\n ";
buffer += "\n <div class=\"column-select\">\n <label
for=\"X-select\">Data column for X: </label>\n <select
name=\"X\" id=\"X-select\">\n ";
stack1 = depth0.numericColumns;
@@ -60,6 +65,15 @@
stack1 = depth0.allColumns;
stack1 = helpers.each.call(depth0, stack1,
{hash:{},inverse:self.noop,fn:self.program(5, program5, data)});
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\n </select>\n </div>\n\n <input
id=\"render-button\" type=\"button\" value=\"Draw\" />\n
<div class=\"clear\"></div>";
+ buffer += "\n </select>\n </div>\n\n ";
+ buffer += "\n <div id=\"first-line-header\" style=\"display:
none;\">\n <p>Possible headers: ";
+ foundHelper = helpers.possibleHeaders;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.possibleHeaders; stack1 = typeof stack1 === functionType ?
stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\n </p>\n <label
for=\"first-line-header-checkbox\">Use the above as column
headers?</label>\n <input type=\"checkbox\"
name=\"include-id\" id=\"first-line-header-checkbox\"\n
";
+ stack1 = depth0.usePossibleHeaders;
+ stack1 = helpers['if'].call(depth0, stack1,
{hash:{},inverse:self.noop,fn:self.program(7, program7, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "/>\n <p class=\"help-text-small\">\n
It looks like Galaxy couldn't get proper column headers for this data.\n
Would you like to use the column headers above as column names to select columns?\n
</p>\n </div>\n\n <input id=\"render-button\"
type=\"button\" value=\"Draw\" />\n <div
class=\"clear\"></div>";
return buffer;});
})();
\ No newline at end of file
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa
static/scripts/templates/visualization-templates.html
--- a/static/scripts/templates/visualization-templates.html
+++ b/static/scripts/templates/visualization-templates.html
@@ -90,6 +90,19 @@
</select></div>
+ {{! if we're using generic column selection names ('column 1') - allow
the user to use the first line }}
+ <div id="first-line-header" style="display: none;">
+ <p>Possible headers: {{ possibleHeaders }}
+ </p>
+ <label for="first-line-header-checkbox">Use the above as column
headers?</label>
+ <input type="checkbox" name="include-id"
id="first-line-header-checkbox"
+ {{#if usePossibleHeaders }}checked="true"{{/if}}/>
+ <p class="help-text-small">
+ It looks like Galaxy couldn't get proper column headers for this data.
+ Would you like to use the column headers above as column names to select
columns?
+ </p>
+ </div>
+
<input id="render-button" type="button" value="Draw"
/><div class="clear"></div></script>
@@ -112,29 +125,29 @@
</div><div id="animDuration" class="form-input
checkbox-input">
- <label for="animated">Animate graph transitions?: </label>
- <input type="checkbox" id="animated"
+ <label for="animate-chart">Animate chart transitions?:
</label>
+ <input type="checkbox" id="animate-chart"
class="checkbox control"{{#if animDuration}}
checked="true"{{/if}} /><p class="form-help
help-text-small">
- Uncheck this to disable the animations used on the graph
+ Uncheck this to disable the animations used on the chart
</p></div><div id="width" class="form-input
numeric-slider-input">
- <label for="width">Graph width: </label>
+ <label for="width">Chart width: </label><div
class="slider-output">{{width}}</div><div
class="slider"></div><p class="form-help
help-text-small">
- (not including graph margins and axes)
+ (not including chart margins and axes)
</p></div><div id="height" class="form-input
numeric-slider-input">
- <label for="height">Graph height: </label>
+ <label for="height">Chart height: </label><div
class="slider-output">{{height}}</div><div
class="slider"></div><p class="form-help
help-text-small">
- (not including graph margins and axes)
+ (not including chart margins and axes)
</p></div>
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa static/scripts/utils/LazyDataLoader.js
--- a/static/scripts/utils/LazyDataLoader.js
+++ b/static/scripts/utils/LazyDataLoader.js
@@ -81,11 +81,11 @@
// it's the responsibility of the code using this to combine them properly
data : [],
// ms btwn recursive loads
- delay : 500,
+ delay : 4000,
// starting line, element, whatever
start : 0,
// size to fetch per load
- size : 1000,
+ size : 4000,
// loader init func: extends loader with config and calls config.init if there
//@param {object} config : object containing variables to override (or
additional)
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa static/scripts/viz/scatterplot.js
--- a/static/scripts/viz/scatterplot.js
+++ b/static/scripts/viz/scatterplot.js
@@ -90,7 +90,7 @@
xNumTicks : 10,
yNumTicks : 10,
xAxisLabelBumpY : 40,
- yAxisLabelBumpX : -35,
+ yAxisLabelBumpX : -40,
width : 400,
height : 400,
//TODO: anyway to make this a sub-obj?
@@ -304,75 +304,37 @@
};
// ........................................................ data points
- //TODO: these to config ...somehow
- //TODO: use these in renderDatapoints ...somehow
- this.glyphEnterState = function( d3Elem ){
-
- };
- this.glyphFinalState = function( d3Elem ){
-
- };
- this.glyphExitState = function( d3Elem ){
-
- };
-
- // initial render or complete re-render (REPLACE datapoints)
this.renderDatapoints = function( xCol, yCol, ids ){
this.log( this + '.renderDatapoints', arguments );
- var count = 0;
-
- this.datapoints = this.addDatapoints( xCol, yCol, ids, ".glyph" );
-
- // glyphs that need to be removed: transition to from normal state to
'exit' state, remove from DOM
- this.datapoints.exit()
- .each( function(){ count += 1; } )
- .transition().duration( this.config.animDuration )
- .attr( "cy", this.config.height )
- .attr( "r", 0 )
- .remove();
- this.log( count, ' glyphs removed' );
-
- //this.log( this.datapoints.length, ' glyphs in the graph' );
- };
-
- // adding points to existing
- this.addDatapoints = function( newXCol, newYCol, ids, selectorForExisting ){
- this.log( this + '.addDatapoints', arguments );
- // ADD datapoints to plot that's already rendered
- // if selectorForExisting === undefined (as in not passed), addDatapoints
won't update existing
- // pass in the class ( '.glyph' ) to update exising datapoints
- var plot = this,
- count = 0,
+ var count = 0,
+ plot = this,
xPosFn = function( d, i ){
//if( d ){ this.log( 'x.data:', newXCol[ i ], 'plotted:',
plot.xScale( newXCol[ i ] ) ); }
- return plot.xScale( newXCol[ i ] );
+ return plot.xScale( xCol[ i ] );
},
yPosFn = function( d, i ){
//if( d ){ this.log( 'y.data:', newYCol[ i ], 'plotted:',
plot.yScale( newYCol[ i ] ) ); }
- return plot.yScale( newYCol[ i ] );
+ return plot.yScale( yCol[ i ] );
};
-
- // select all existing glyphs and compare to incoming data
- // enter() will yield those glyphs that need to be added
- var newDatapoints = this.content.selectAll( selectorForExisting );
- this.log( 'existing datapoints:', newDatapoints );
- newDatapoints = newDatapoints.data( newXCol );
-
- // enter - new data to be added as glyphs: give them a 'entry' position
and style
+
+ //this.datapoints = this.addDatapoints( xCol, yCol, ids, ".glyph" );
+ var datapoints = this.content.selectAll( '.glyph' ).data( xCol );
+
+ // enter - NEW data to be added as glyphs: give them a 'entry' position
and style
count = 0;
- newDatapoints.enter()
+ datapoints.enter()
.append( 'svg:circle' )
.each( function(){ count += 1; } )
.classed( "glyph", true )
- .attr( "cx", xPosFn )
- .attr( "cy", yPosFn )
+ .attr( "cx", 0 )
+ .attr( "cy", this.config.height )
// start all bubbles small...
.attr( "r", 0 );
this.log( count, ' new glyphs created' );
- // for all existing glyphs and those that need to be added: transition anim to
final state
+ // for all EXISTING glyphs and those that need to be added: transition anim to
final state
count = 0;
- newDatapoints
+ datapoints
// ...animate to final position
.transition().duration( this.config.animDuration )
.each( function(){ count += 1; } )
@@ -381,18 +343,22 @@
.attr( "r", plot.config.datapointSize );
this.log( count, ' existing glyphs transitioned' );
- // attach ids
- if( ids ){
- newDatapoints.attr( 'data', function( d, i ){ return ( ids[ i ] ); }
);
- }
+ // events
+ // glyphs that need to be removed: transition to from normal state to
'exit' state, remove from DOM
+ datapoints.exit()
+ .each( function(){ count += 1; } )
+ .transition().duration( this.config.animDuration )
+ .attr( "cy", this.config.height )
+ .attr( "r", 0 )
+ .remove();
+ this.log( count, ' glyphs removed' );
- // titles
- newDatapoints.attr( 'svg:title', function( d, i ){
- return (( ids )?( ids[ i ] + ': ' ):( '' )) + newXCol[ i ] +
', ' + newYCol[ i ];
- });
-
- // events
- newDatapoints
+ this._addDatapointEventhandlers( datapoints, xCol, yCol, ids );
+ };
+
+ this._addDatapointEventhandlers = function( datapoints, xCol, yCol, ids ){
+ var plot = this;
+ datapoints
//TODO: remove magic numbers
.on( 'mouseover', function( d, i ){
var datapoint = d3.select( this );
@@ -404,36 +370,42 @@
plot.content.append( 'line' )
.attr( 'stroke', 'red' )
.attr( 'stroke-width', 1 )
- .attr( 'x1', datapoint.attr( 'cx' ) ).attr(
'y1', datapoint.attr( 'cy' ) )
- .attr( 'x2', 0 ).attr( 'y2', datapoint.attr(
'cy' ) )
- .classed( 'hoverline', true );
- plot.content.append( 'line' )
- .attr( 'stroke', 'red' )
- .attr( 'stroke-width', 1 )
- .attr( 'x1', datapoint.attr( 'cx' ) ).attr(
'y1', datapoint.attr( 'cy' ) )
- .attr( 'x2', datapoint.attr( 'cx' ) ).attr(
'y2', plot.config.height )
+ // start not at center, but at the edge of the circle - to prevent
mouseover thrashing
+ .attr( 'x1', datapoint.attr( 'cx' ) -
plot.config.datapointSize )
+ .attr( 'y1', datapoint.attr( 'cy' ) )
+ .attr( 'x2', 0 )
+ .attr( 'y2', datapoint.attr( 'cy' ) )
.classed( 'hoverline', true );
- //var datapointWindowPos = $( this ).position();
- //var datapointWindowPos = $( this ).offset();
- //window.dot = this;
- ////this.popup = make_abs_box( datapointWindowPos.top,
datapointWindowPos.left + datapoint.attr( 'r' ),
- //this.popup = make_abs_box( datapointWindowPos.top,
datapointWindowPos.left,
- // newXCol[ i ], newYCol[ i ], ( ids )?( ids[ i
] ):( undefined ) );
- //$( 'body' ).append( this.popup );
+ // if the vertical hoverline
+ if( datapoint.attr( 'cy' ) < plot.config.height ){
+ plot.content.append( 'line' )
+ .attr( 'stroke', 'red' )
+ .attr( 'stroke-width', 1 )
+ .attr( 'x1', datapoint.attr( 'cx' ) )
+ .attr( 'y1', datapoint.attr( 'cy' ) +
plot.config.datapointSize )
+ .attr( 'x2', datapoint.attr( 'cx' ) )
+ .attr( 'y2', plot.config.height )
+ .classed( 'hoverline', true );
+ }
+
+ var datapointWindowPos = $( this ).offset();
+ plot.datapointInfoBox = plot.infoBox(
+ datapointWindowPos.top, datapointWindowPos.left,
+ plot.infoHtml( xCol[ i ], yCol[ i ], ( ids )?( ids[ i ] ):( undefined
) )
+ );
+ $( 'body' ).append( plot.datapointInfoBox );
})
.on( 'mouseout', function(){
d3.select( this )
.style( 'fill', 'black' )
.style( 'fill-opacity', 0.2 );
- d3.selectAll( '.hoverline' ).remove();
- //if( this.popup ){
- // this.popup.remove();
- //}
+ plot.content.selectAll( '.hoverline' ).remove();
+ if( plot.datapointInfoBox ){
+ plot.datapointInfoBox.remove();
+ }
});
-
- return newDatapoints;
- };
+ },
this.render = function( columnData, meta ){
this.log( this + '.render', arguments );
@@ -457,7 +429,7 @@
//this.log( 'xMin, xMax, yMin, yMax:', this.xMin, this.xMax, this.yMin,
this.yMax );
this.setUpScales();
- // build the svg dom infrastructure
+ // find (or build if it doesn't exist) the svg dom infrastructure
if( !this.svg ){ this.svg = d3.select( 'svg' ).attr( "class",
"chart" ); }
if( !this.content ){
this.content = this.svg.append( "svg:g" ).attr( "class",
"content" ).attr( 'id', this.config.id );
@@ -485,6 +457,32 @@
this.renderGrid();
this.renderDatapoints( xCol, yCol, ids );
};
+
+ this.infoHtml = function( x, y, id ){
+ var retDiv = $( '<div/>' );
+ if( id ){
+ $( '<div/>' ).text( id ).css( 'font-weight',
'bold' ).appendTo( retDiv );
+ }
+ $( '<div/>' ).text( x ).appendTo( retDiv );
+ $( '<div/>' ).text( y ).appendTo( retDiv );
+ return retDiv.html();
+ };
+
+ //TODO: html for now
+ this.infoBox = function( top, left, html, adjTop, adjLeft ){
+ adjTop = adjTop || 0;
+ adjLeft = adjLeft || 20;
+ var infoBox = $( '<div />' )
+ .addClass( 'chart-info-box' )
+ .css({
+ 'position' : 'absolute',
+ 'top' : top + adjTop,
+ 'left' : left + adjLeft
+ });
+ infoBox.html( html );
+ return infoBox;
+ };
+
}
//==============================================================================
diff -r 3c4696f6af0d9c6c7885568c1fee02df53849322 -r
4eaa644dd47877c40ee7090d56379998d7aecafa templates/visualization/scatterplot.mako
--- a/templates/visualization/scatterplot.mako
+++ b/templates/visualization/scatterplot.mako
@@ -26,6 +26,7 @@
padding : 8px;
background-color: #ebd9b2;
margin-bottom: 16px;
+ overflow: auto;
}
#chart-header .subtitle {
@@ -182,12 +183,11 @@
}
/* -------------------------------------------- info box */
-.zero-dimensions {
- width: 0;
- height: 0;
- border-top: 8px solid transparent;
- border-bottom: 8px solid transparent;
- border-right: 8px solid grey;
+.chart-info-box {
+ border-radius: 4px;
+ padding: 4px;
+ background-color: white;
+ border: 1px solid black;
}
</style>
@@ -255,63 +255,3 @@
</div><div id="scatterplot"
class="scatterplot-control-form"></div></%def>
-
-
-<script type="text/javascript">
-function make_abs_box( top, left, x, y, id ){
- var ARROW_SIZE = 8,
- ARROW_COLOR = 'grey',
- DIST_TO_POINT = 4,
- halfArrowSize = ARROW_SIZE / 2;
-
- var boxContainer = $( '<div />' )
- .attr( 'id', 'abs-box-container' )
- // top left arrow
- .css({
- 'position' : 'absolute',
- 'top' : top - halfArrowSize,
- 'left' : left + ARROW_SIZE + DIST_TO_POINT,
- 'background-color': 'transparent',
- });
- window.boxContainer = boxContainer;
-
- var arrowLeft = $( '<div />' )
- .attr( 'id', 'abs-box-arrow' )
- .addClass( 'zero-dimensions' )
- .css({
- 'border-top' : ARROW_SIZE + 'px solid transparent',
- 'border-bottom' : ARROW_SIZE + 'px solid transparent',
- 'border-right' : ARROW_SIZE + 'px solid ' + ARROW_COLOR,
- });
- boxContainer.append( arrowLeft );
- window.arrow = arrowLeft;
-
- console.debug( 'arrow height:', arrowLeft.height() );
- var boxInfo = $( '<div />' )
- .attr( 'id', 'abs-box' )
- .css({
- 'position' : 'relative',
- //TODO: 4 here is the border-radius
- 'top' : -( 2 * ARROW_SIZE + 6 ),
- 'left' : ARROW_SIZE,
- 'border' : '2px solid grey',
- 'border-radius' : '4px',
- 'padding' : '4px',
- 'background-color': 'white',
- 'box-shadow' : '4px 4px 4px black'
- });
-
- // remove
- if( id ){
- $( '<div />' ).addClass( 'abs-box-id' ).css(
'font-weight', 'bold' ).text( id ).appendTo( boxInfo );
- }
- $( '<div />' ).addClass( 'abs-box-x' ).text( x ).appendTo(
boxInfo );
- $( '<div />' ).addClass( 'abs-box-y' ).text( y ).appendTo(
boxInfo );
- boxContainer.append( boxInfo );
- boxContainer.append( '<div style="clear:both"></div>'
);
- window.boxInfo = boxContainer;
-
- //console.debug( boxContainer );
- return boxContainer;
-}
-</script>
Repository URL:
https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from
bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.