commit/galaxy-central: carlfeberhard: Remove scatterplot from legacy visualization framework (it will no longer appear if you haven't enabled visualization_plugins_directory in your universe_wsgi.ini); clean up; pack scripts
1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/044ead554358/ Changeset: 044ead554358 User: carlfeberhard Date: 2014-02-14 16:47:38 Summary: Remove scatterplot from legacy visualization framework (it will no longer appear if you haven't enabled visualization_plugins_directory in your universe_wsgi.ini); clean up; pack scripts Affected #: 21 files diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a lib/galaxy/datatypes/tabular.py --- a/lib/galaxy/datatypes/tabular.py +++ b/lib/galaxy/datatypes/tabular.py @@ -332,24 +332,6 @@ def as_ucsc_display_file( self, dataset, **kwd ): return open( dataset.file_name ) - def get_visualizations( self, dataset ): - """ - Returns a list of visualizations for datatype. - """ - # Can visualize tabular data as scatterplot if there are 2+ numerical - # columns. - num_numerical_cols = 0 - if dataset.metadata.column_types: - for col_type in dataset.metadata.column_types: - if col_type in [ 'int', 'float' ]: - num_numerical_cols += 1 - - vizs = super( Tabular, self ).get_visualizations( dataset ) - if num_numerical_cols >= 2: - vizs.append( 'scatterplot' ) - - return vizs - # ------------- Dataproviders @dataproviders.decorators.dataprovider_factory( 'column', dataproviders.column.ColumnarDataProvider.settings ) def column_dataprovider( self, dataset, **settings ): diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a lib/galaxy/webapps/galaxy/controllers/visualization.py --- a/lib/galaxy/webapps/galaxy/controllers/visualization.py +++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py @@ -964,16 +964,6 @@ return self.get_visualization( trans, id ) @web.expose - def scatterplot( self, trans, dataset_id, **kwargs ): - """ - Returns a page that controls and renders a scatteplot graph. - """ - hda = self.get_dataset( trans, dataset_id, check_ownership=False, check_accessible=True ) - return trans.fill_template_mako( "visualization/scatterplot.mako", - hda=hda, - query_args=kwargs ) - - @web.expose def phyloviz( self, trans, id=None, dataset_id=None, tree_index=0, **kwargs ): config = None data = None diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/mvc/dataset/hda-edit.js --- a/static/scripts/mvc/dataset/hda-edit.js +++ b/static/scripts/mvc/dataset/hda-edit.js @@ -197,23 +197,18 @@ // map a function to each visualization in the icon's attributes // create a popupmenu from that map - var hdaView = this; /** @inner */ function create_viz_action( visualization ) { - switch( visualization ){ - case 'trackster': - return create_trackster_action_fn( visualization_url, params, dbkey ); - case 'scatterplot': - return create_scatterplot_action_fn( visualization_url, params, hdaView.linkTarget ); - default: - return function(){ - Galaxy.frame.add({ - title : "Visualization", - type : "url", - content : visualization_url + '/' + visualization + '?' + $.param( params ) - }); - }; + if( visualization === 'trackster' ){ + return create_trackster_action_fn( visualization_url, params, dbkey ); } + return function(){ + Galaxy.frame.add({ + title : "Visualization", + type : "url", + content : visualization_url + '/' + visualization + '?' + $.param( params ) + }); + }; } function titleCase( string ){ @@ -412,29 +407,6 @@ //============================================================================== //TODO: these belong somewhere else - -/** Create scatterplot loading/set up function for use with the visualizations popupmenu. - * @param {String} url url (gen. 'visualizations') to which to append 'scatterplot' and params - * @param {Object} params parameters to convert to query string for splot page - * @returns function that loads the scatterplot - */ -//TODO: should be imported from scatterplot.js OR abstracted to 'load this in the galaxy_main frame' -function create_scatterplot_action_fn( url, params, target ){ - action = function() { - Galaxy.frame.add({ - title : "Scatterplot", - type : "url", - content : url + '/scatterplot?' + $.param(params), - target : target - }); - - //TODO: this needs to go away - $( 'div.popmenu-wrapper' ).remove(); - return false; - }; - return action; -} - // ----------------------------------------------------------------------------- /** Create trackster loading/set up function for use with the visualizations popupmenu. * Shows modal dialog for load old/create new. diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/galaxy.tools.js --- /dev/null +++ b/static/scripts/packed/galaxy.tools.js @@ -0,0 +1,1 @@ +define(["mvc/tools"],function(b){var a=function(d,c){$("input[name='"+d+"'][type='checkbox']").attr("checked",!!c)};$("div.checkUncheckAllPlaceholder").each(function(){var c=$(this).attr("checkbox_name");select_link=$("<a class='action-button'></a>").text("Select All").click(function(){a(c,true)});unselect_link=$("<a class='action-button'></a>").text("Unselect All").click(function(){a(c,false)});$(this).append(select_link).append(" ").append(unselect_link)})}); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/mvc/dataset/hda-edit.js --- a/static/scripts/packed/mvc/dataset/hda-edit.js +++ b/static/scripts/packed/mvc/dataset/hda-edit.js @@ -1,1 +1,1 @@ -define(["mvc/dataset/hda-model","mvc/dataset/hda-base"],function(d,a){var f=a.HDABaseView.extend(LoggableMixin).extend({initialize:function(g){a.HDABaseView.prototype.initialize.call(this,g);this.hasUser=g.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton];this.tagsEditorShown=g.tagsEditorShown||false;this.annotationEditorShown=g.annotationEditorShown||false},_render_titleButtons:function(){return a.HDABaseView.prototype._render_titleButtons.call(this).concat([this._render_editButton(),this._render_deleteButton()])},_render_editButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var i=this.model.get("purged"),g=this.model.get("deleted"),h={title:_l("Edit attributes"),href:this.urls.edit,target:this.linkTarget,classes:"dataset-edit"};if(g||i){h.disabled=true;if(i){h.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(g){h.title=_l("Undelete dataset to edit attributes")}}}else{if(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD){h.disabled=true;h.title=_l("This dataset must finish uploading before it can be edited")}}h.faIcon="fa-pencil";return faIconButton(h)},_render_deleteButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var g=this,h={title:_l("Delete"),classes:"dataset-delete",onclick:function(){g.$el.find(".icon-btn.dataset-delete").trigger("mouseout");g.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){h={title:_l("Dataset is already deleted"),disabled:true}}h.faIcon="fa-times";return faIconButton(h)},_render_errButton:function(){if(this.model.get("state")!==d.HistoryDatasetAssociation.STATES.ERROR){return null}return faIconButton({title:_l("View or report this error"),href:this.urls.report_error,classes:"dataset-report-error-btn",target:this.linkTarget,faIcon:"fa-bug"})},_render_rerunButton:function(){return faIconButton({title:_l("Run this job again"),href:this.urls.rerun,classes:"dataset-rerun-btn",target:this.linkTarget,faIcon:"fa-refresh"})},_render_visualizationsButton:function(){var n=this.model.get("visualizations");if((!this.hasUser)||(!this.model.hasData())||(_.isEmpty(n))){return null}if(_.isObject(n[0])){return this._render_visualizationsFrameworkButton(n)}if(!this.urls.visualization){return null}var k=this.model.get("dbkey"),g=this.urls.visualization,j={},h={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(k){h.dbkey=k}var l=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});var m=this;function i(p){switch(p){case"trackster":return b(g,h,k);case"scatterplot":return e(g,h,m.linkTarget);default:return function(){Galaxy.frame.add({title:"Visualization",type:"url",content:g+"/"+p+"?"+$.param(h)})}}}function o(p){return p.charAt(0).toUpperCase()+p.slice(1)}if(n.length===1){l.attr("data-original-title",_l("Visualize in ")+_l(o(n[0])));l.click(i(n[0]))}else{_.each(n,function(p){j[_l(o(p))]=i(p)});make_popupmenu(l,j)}return l},_render_visualizationsFrameworkButton:function(g){if(!(this.model.hasData())||!(g&&!_.isEmpty(g))){return null}var i=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});if(g.length===1){var h=g[0];i.attr("data-original-title",_l("Visualize in ")+h.html);i.attr("href",h.href)}else{var j=[];_.each(g,function(k){k.func=function(){if(Galaxy.frame.active){Galaxy.frame.add({title:"Visualization",type:"url",content:k.href});return false}return true};j.push(k);return false});PopupMenu.create(i,j)}return i},_buildNewRender:function(){var g=a.HDABaseView.prototype._buildNewRender.call(this);g.find(".dataset-deleted-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk'));g.find(".dataset-hidden-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it'));return g},_render_body_failed_metadata:function(){var h=$("<a/>").attr({href:this.urls.edit,target:this.linkTarget}).text(_l("set it manually or retry auto-detection")),g=$("<span/>").text(". "+_l("You may be able to")+" ").append(h),i=a.HDABaseView.prototype._render_body_failed_metadata.call(this);i.find(".warningmessagesmall strong").append(g);return i},_render_body_error:function(){var g=a.HDABaseView.prototype._render_body_error.call(this);g.find(".dataset-actions .left").prepend(this._render_errButton());return g},_render_body_ok:function(){var g=a.HDABaseView.prototype._render_body_ok.call(this);if(this.model.isDeletedOrPurged()){return g}this.makeDbkeyEditLink(g);if(this.hasUser){g.find(".dataset-actions .left").append(this._render_visualizationsButton());this._renderTags(g);this._renderAnnotation(g)}return g},_renderTags:function(g){var h=this;this.tagsEditor=new TagsEditor({model:this.model,el:g.find(".tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){h.tagsEditorShown=true},onhide:function(){h.tagsEditorShown=false},$activator:faIconButton({title:_l("Edit dataset tags"),classes:"dataset-tag-btn",faIcon:"fa-tags"}).appendTo(g.find(".dataset-actions .right"))});if(this.tagsEditorShown){this.tagsEditor.toggle(true)}},_renderAnnotation:function(g){var h=this;this.annotationEditor=new AnnotationEditor({model:this.model,el:g.find(".annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){h.annotationEditorShown=true},onhide:function(){h.annotationEditorShown=false},$activator:faIconButton({title:_l("Edit dataset annotation"),classes:"dataset-annotate-btn",faIcon:"fa-comment"}).appendTo(g.find(".dataset-actions .right"))});if(this.annotationEditorShown){this.annotationEditor.toggle(true)}},makeDbkeyEditLink:function(h){if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){var g=$('<a class="value">?</a>').attr("href",this.urls.edit).attr("target",this.linkTarget);h.find(".dataset-dbkey .value").replaceWith(g)}},events:_.extend(_.clone(a.HDABaseView.prototype.events),{"click .dataset-undelete":function(g){this.model.undelete();return false},"click .dataset-unhide":function(g){this.model.unhide();return false},"click .dataset-purge":"confirmPurge"}),confirmPurge:function c(g){this.model.purge();return false},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"HDAView("+g+")"}});function e(g,i,h){action=function(){Galaxy.frame.add({title:"Scatterplot",type:"url",content:g+"/scatterplot?"+$.param(i),target:h});$("div.popmenu-wrapper").remove();return false};return action}function b(g,i,h){return function(){var j={};if(h){j["f-dbkey"]=h}$.ajax({url:g+"/list_tracks?"+$.param(j),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(k){var l=window.parent;l.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){l.Galaxy.modal.hide()},"View in saved visualization":function(){l.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:k,buttons:{Cancel:function(){l.Galaxy.modal.hide()},"Add to visualization":function(){$(l.document).find("input[name=id]:checked").each(function(){l.Galaxy.modal.hide();var m=$(this).val();i.id=m;l.Galaxy.frame.add({title:"Trackster",type:"url",content:g+"/trackster?"+$.param(i)})})}}})},"View in new visualization":function(){l.Galaxy.modal.hide();var m=g+"/trackster?"+$.param(i);l.Galaxy.frame.add({title:"Trackster",type:"url",content:m})}}})}});return false}}return{HDAEditView:f}}); \ No newline at end of file +define(["mvc/dataset/hda-model","mvc/dataset/hda-base"],function(d,a){var e=a.HDABaseView.extend(LoggableMixin).extend({initialize:function(f){a.HDABaseView.prototype.initialize.call(this,f);this.hasUser=f.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton];this.tagsEditorShown=f.tagsEditorShown||false;this.annotationEditorShown=f.annotationEditorShown||false},_render_titleButtons:function(){return a.HDABaseView.prototype._render_titleButtons.call(this).concat([this._render_editButton(),this._render_deleteButton()])},_render_editButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var h=this.model.get("purged"),f=this.model.get("deleted"),g={title:_l("Edit attributes"),href:this.urls.edit,target:this.linkTarget,classes:"dataset-edit"};if(f||h){g.disabled=true;if(h){g.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(f){g.title=_l("Undelete dataset to edit attributes")}}}else{if(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD){g.disabled=true;g.title=_l("This dataset must finish uploading before it can be edited")}}g.faIcon="fa-pencil";return faIconButton(g)},_render_deleteButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var f=this,g={title:_l("Delete"),classes:"dataset-delete",onclick:function(){f.$el.find(".icon-btn.dataset-delete").trigger("mouseout");f.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){g={title:_l("Dataset is already deleted"),disabled:true}}g.faIcon="fa-times";return faIconButton(g)},_render_errButton:function(){if(this.model.get("state")!==d.HistoryDatasetAssociation.STATES.ERROR){return null}return faIconButton({title:_l("View or report this error"),href:this.urls.report_error,classes:"dataset-report-error-btn",target:this.linkTarget,faIcon:"fa-bug"})},_render_rerunButton:function(){return faIconButton({title:_l("Run this job again"),href:this.urls.rerun,classes:"dataset-rerun-btn",target:this.linkTarget,faIcon:"fa-refresh"})},_render_visualizationsButton:function(){var f=this.model.get("visualizations");if((!this.hasUser)||(!this.model.hasData())||(_.isEmpty(f))){return null}if(_.isObject(f[0])){return this._render_visualizationsFrameworkButton(f)}if(!this.urls.visualization){return null}var h=this.model.get("dbkey"),l=this.urls.visualization,i={},m={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(h){m.dbkey=h}var g=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});function j(n){if(n==="trackster"){return b(l,m,h)}return function(){Galaxy.frame.add({title:"Visualization",type:"url",content:l+"/"+n+"?"+$.param(m)})}}function k(n){return n.charAt(0).toUpperCase()+n.slice(1)}if(f.length===1){g.attr("data-original-title",_l("Visualize in ")+_l(k(f[0])));g.click(j(f[0]))}else{_.each(f,function(n){i[_l(k(n))]=j(n)});make_popupmenu(g,i)}return g},_render_visualizationsFrameworkButton:function(f){if(!(this.model.hasData())||!(f&&!_.isEmpty(f))){return null}var h=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});if(f.length===1){var g=f[0];h.attr("data-original-title",_l("Visualize in ")+g.html);h.attr("href",g.href)}else{var i=[];_.each(f,function(j){j.func=function(){if(Galaxy.frame.active){Galaxy.frame.add({title:"Visualization",type:"url",content:j.href});return false}return true};i.push(j);return false});PopupMenu.create(h,i)}return h},_buildNewRender:function(){var f=a.HDABaseView.prototype._buildNewRender.call(this);f.find(".dataset-deleted-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk'));f.find(".dataset-hidden-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it'));return f},_render_body_failed_metadata:function(){var g=$("<a/>").attr({href:this.urls.edit,target:this.linkTarget}).text(_l("set it manually or retry auto-detection")),f=$("<span/>").text(". "+_l("You may be able to")+" ").append(g),h=a.HDABaseView.prototype._render_body_failed_metadata.call(this);h.find(".warningmessagesmall strong").append(f);return h},_render_body_error:function(){var f=a.HDABaseView.prototype._render_body_error.call(this);f.find(".dataset-actions .left").prepend(this._render_errButton());return f},_render_body_ok:function(){var f=a.HDABaseView.prototype._render_body_ok.call(this);if(this.model.isDeletedOrPurged()){return f}this.makeDbkeyEditLink(f);if(this.hasUser){f.find(".dataset-actions .left").append(this._render_visualizationsButton());this._renderTags(f);this._renderAnnotation(f)}return f},_renderTags:function(f){var g=this;this.tagsEditor=new TagsEditor({model:this.model,el:f.find(".tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){g.tagsEditorShown=true},onhide:function(){g.tagsEditorShown=false},$activator:faIconButton({title:_l("Edit dataset tags"),classes:"dataset-tag-btn",faIcon:"fa-tags"}).appendTo(f.find(".dataset-actions .right"))});if(this.tagsEditorShown){this.tagsEditor.toggle(true)}},_renderAnnotation:function(f){var g=this;this.annotationEditor=new AnnotationEditor({model:this.model,el:f.find(".annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){g.annotationEditorShown=true},onhide:function(){g.annotationEditorShown=false},$activator:faIconButton({title:_l("Edit dataset annotation"),classes:"dataset-annotate-btn",faIcon:"fa-comment"}).appendTo(f.find(".dataset-actions .right"))});if(this.annotationEditorShown){this.annotationEditor.toggle(true)}},makeDbkeyEditLink:function(g){if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){var f=$('<a class="value">?</a>').attr("href",this.urls.edit).attr("target",this.linkTarget);g.find(".dataset-dbkey .value").replaceWith(f)}},events:_.extend(_.clone(a.HDABaseView.prototype.events),{"click .dataset-undelete":function(f){this.model.undelete();return false},"click .dataset-unhide":function(f){this.model.unhide();return false},"click .dataset-purge":"confirmPurge"}),confirmPurge:function c(f){this.model.purge();return false},toString:function(){var f=(this.model)?(this.model+""):("(no model)");return"HDAView("+f+")"}});function b(f,h,g){return function(){var i={};if(g){i["f-dbkey"]=g}$.ajax({url:f+"/list_tracks?"+$.param(i),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(j){var k=window.parent;k.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){k.Galaxy.modal.hide()},"View in saved visualization":function(){k.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:j,buttons:{Cancel:function(){k.Galaxy.modal.hide()},"Add to visualization":function(){$(k.document).find("input[name=id]:checked").each(function(){k.Galaxy.modal.hide();var l=$(this).val();h.id=l;k.Galaxy.frame.add({title:"Trackster",type:"url",content:f+"/trackster?"+$.param(h)})})}}})},"View in new visualization":function(){k.Galaxy.modal.hide();var l=f+"/trackster?"+$.param(h);k.Galaxy.frame.add({title:"Trackster",type:"url",content:l})}}})}});return false}}return{HDAEditView:e}}); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/mvc/ui.js --- a/static/scripts/packed/mvc/ui.js +++ b/static/scripts/packed/mvc/ui.js @@ -1,1 +1,1 @@ -var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function b(m,l){this.currModeIndex=0;return this.init(m,l)}b.prototype.DATA_KEY="mode-button";b.prototype.defaults={modes:[{mode:"default"}]};b.prototype.init=function f(m,l){l=l||{};this.$element=$(m);this.options=jQuery.extend(true,{},this.defaults,l);var o=this;this.$element.click(function n(p){o.callModeFn();o._incModeIndex();$(this).html(o.options.modes[o.currModeIndex].html)});this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this};b.prototype._getModeIndex=function j(l){for(var m=0;m<this.options.modes.length;m+=1){if(this.options.modes[m].mode===l){return m}}throw new Error("mode not found: "+l)};b.prototype.getCurrMode=function a(){return this.options.modes[this.currModeIndex]};b.prototype.getMode=function g(l){if(!l){return this.getCurrMode()}return this.options.modes[(this._getModeIndex(l))]};b.prototype.hasMode=function k(l){return !!this.getMode(l)};b.prototype.currentMode=function e(){return this.options.modes[this.currModeIndex]};b.prototype.setMode=function c(m){var l=this.getMode(m);this.$element.html(l.html||null);return this};b.prototype._incModeIndex=function d(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};b.prototype.callModeFn=function h(l){var m=this.getMode(l).onclick;if(m&&jQuery.type(m==="function")){return m.call(this)}return undefined};jQuery.fn.extend({modeButton:function i(m){var l=jQuery.makeArray(arguments).slice(1);return this.map(function(){var p=$(this),o=p.data("mode-button");if(jQuery.type(m)==="object"){o=new b(p,m);p.data("mode-button",o)}else{if(o&&jQuery.type(m)==="string"){var n=o[m];if(jQuery.type(n)==="function"){return n.apply(o,l)}}else{if(o){return o}}}return this})}})}());function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}()); \ No newline at end of file +var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function b(m,l){this.currModeIndex=0;return this.init(m,l)}b.prototype.DATA_KEY="mode-button";b.prototype.defaults={modes:[{mode:"default"}]};b.prototype.init=function f(m,l){l=l||{};this.$element=$(m);this.options=jQuery.extend(true,{},this.defaults,l);var o=this;this.$element.click(function n(p){o.callModeFn();o._incModeIndex();$(this).html(o.options.modes[o.currModeIndex].html)});this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this};b.prototype._getModeIndex=function j(l){for(var m=0;m<this.options.modes.length;m+=1){if(this.options.modes[m].mode===l){return m}}throw new Error("mode not found: "+l)};b.prototype.getCurrMode=function a(){return this.options.modes[this.currModeIndex]};b.prototype.getMode=function g(l){if(!l){return this.getCurrMode()}return this.options.modes[(this._getModeIndex(l))]};b.prototype.hasMode=function k(l){return !!this.getMode(l)};b.prototype.currentMode=function e(){return this.options.modes[this.currModeIndex]};b.prototype.setMode=function c(m){var l=this.getMode(m);this.$element.html(l.html||null);return this};b.prototype._incModeIndex=function d(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};b.prototype.callModeFn=function h(l){var m=this.getMode(l).onclick;if(m&&jQuery.type(m==="function")){return m.call(this)}return undefined};jQuery.fn.extend({modeButton:function i(m){var l=jQuery.makeArray(arguments).slice(1);return this.map(function(){var p=$(this),o=p.data("mode-button");if(jQuery.type(m)==="object"){o=new b(p,m);p.data("mode-button",o)}else{if(o&&jQuery.type(m)==="string"){var n=o[m];if(jQuery.type(n)==="function"){return n.apply(o,l)}}else{if(o){return o}}}return this})}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}()); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/templates/compiled/template-visualization-chartControl.js --- a/static/scripts/packed/templates/compiled/template-visualization-chartControl.js +++ /dev/null @@ -1,1 +0,0 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-chartControl"]=b(function(f,l,e,k,j){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,f.helpers);j=j||{};var h="",c,g="function",i=this.escapeExpression,m=this;function d(o,n){return' checked="true"'}h+='<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">';if(c=e.datapointSize){c=c.call(l,{hash:{},data:j})}else{c=l.datapointSize;c=typeof c===g?c.apply(l):c}h+=i(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=e["if"].call(l,l.animDuration,{hash:{},inverse:m.noop,fn:m.program(1,d,j),data:j});if(c||c===0){h+=c}h+=' />\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">';if(c=e.width){c=c.call(l,{hash:{},data:j})}else{c=l.width;c=typeof c===g?c.apply(l):c}h+=i(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">';if(c=e.height){c=c.call(l,{hash:{},data:j})}else{c=l.height;c=typeof c===g?c.apply(l):c}h+=i(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="';if(c=e.xLabel){c=c.call(l,{hash:{},data:j})}else{c=l.xLabel;c=typeof c===g?c.apply(l):c}h+=i(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="';if(c=e.yLabel){c=c.call(l,{hash:{},data:j})}else{c=l.yLabel;c=typeof c===g?c.apply(l):c}h+=i(c)+'" />\n <p class="form-help help-text-small"></p>\n </div>\n\n <input id="render-button" type="button" value="Draw" />';return h})})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/templates/compiled/template-visualization-chartDisplay.js --- a/static/scripts/packed/templates/compiled/template-visualization-chartDisplay.js +++ /dev/null @@ -1,1 +0,0 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-chartDisplay"]=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+='<svg width="';if(c=d.width){c=c.call(k,{hash:{},data:i})}else{c=k.width;c=typeof c===f?c.apply(k):c}g+=h(c)+'" height="';if(c=d.height){c=c.call(k,{hash:{},data:i})}else{c=k.height;c=typeof c===f?c.apply(k):c}g+=h(c)+'"></svg>';return g})})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/templates/compiled/template-visualization-dataControl.js --- a/static/scripts/packed/templates/compiled/template-visualization-dataControl.js +++ /dev/null @@ -1,1 +0,0 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-dataControl"]=b(function(g,m,f,l,k){this.compilerInfo=[4,">= 1.0.0"];f=this.merge(f,g.helpers);k=k||{};var i="",d,h="function",j=this.escapeExpression,n=this;function e(r,q){var o="",p;o+='\n <option value="';if(p=f.index){p=p.call(r,{hash:{},data:q})}else{p=r.index;p=typeof p===h?p.apply(r):p}o+=j(p)+'">';if(p=f.name){p=p.call(r,{hash:{},data:q})}else{p=r.name;p=typeof p===h?p.apply(r):p}o+=j(p)+"</option>\n ";return o}function c(p,o){return'checked="true"'}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 \n <div class="column-select">\n <label for="X-select">Data column for X: </label>\n <select name="X" id="X-select">\n ';d=f.each.call(m,m.numericColumns,{hash:{},inverse:n.noop,fn:n.program(1,e,k),data: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=f.each.call(m,m.numericColumns,{hash:{},inverse:n.noop,fn:n.program(1,e,k),data:k});if(d||d===0){i+=d}i+='\n </select>\n </div>\n\n \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=f.each.call(m,m.allColumns,{hash:{},inverse:n.noop,fn:n.program(1,e,k),data:k});if(d||d===0){i+=d}i+='\n </select>\n </div>\n\n \n <div id="first-line-header" style="display: none;">\n <p>Possible headers: ';if(d=f.possibleHeaders){d=d.call(m,{hash:{},data:k})}else{d=m.possibleHeaders;d=typeof d===h?d.apply(m):d}i+=j(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=f["if"].call(m,m.usePossibleHeaders,{hash:{},inverse:n.noop,fn:n.program(3,c,k),data:k});if(d||d===0){i+=d}i+='/>\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 i})})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/templates/compiled/template-visualization-scatterplotControlForm.js --- a/static/scripts/packed/templates/compiled/template-visualization-scatterplotControlForm.js +++ /dev/null @@ -1,1 +0,0 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-scatterplotControlForm"]=b(function(e,k,d,j,i){this.compilerInfo=[4,">= 1.0.0"];d=this.merge(d,e.helpers);i=i||{};var g="",c,f="function",h=this.escapeExpression;g+='\n\n<div class="scatterplot-container chart-container tabbable tabs-left">\n \n <ul class="nav nav-tabs">\n \n <li class="active"><a href="#data-control" data-toggle="tab"\n title="Use this tab to change which data are used">Data Controls</a></li>\n <li><a href="#chart-control" data-toggle="tab"\n title="Use this tab to change how the chart is drawn">Chart Controls</a></li>\n <li><a href="#stats-display" data-toggle="tab"\n title="This tab will display overall statistics for your data">Statistics</a></li>\n <li><a href="#chart-display" data-toggle="tab"\n title="This tab will display the chart">Chart</a>\n \n <div id="loading-indicator" style="display: none;">\n <img class="loading-img" src="';if(c=d.loadingIndicatorImagePath){c=c.call(k,{hash:{},data:i})}else{c=k.loadingIndicatorImagePath;c=typeof c===f?c.apply(k):c}g+=h(c)+'" />\n <span class="loading-message">';if(c=d.message){c=c.call(k,{hash:{},data:i})}else{c=k.message;c=typeof c===f?c.apply(k):c}g+=h(c)+'</span>\n </div>\n </li>\n </ul>\n\n \n <div class="tab-content">\n \n <div id="data-control" class="tab-pane active">\n \n </div>\n \n \n <div id="chart-control" class="tab-pane">\n \n </div>\n\n \n <div id="stats-display" class="tab-pane">\n \n </div>\n\n \n <div id="chart-display" class="tab-pane">\n \n </div>\n\n </div>\n</div>';return g})})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/templates/compiled/template-visualization-statsDisplay.js --- a/static/scripts/packed/templates/compiled/template-visualization-statsDisplay.js +++ /dev/null @@ -1,1 +0,0 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-visualization-statsDisplay"]=b(function(f,l,e,k,j){this.compilerInfo=[4,">= 1.0.0"];e=this.merge(e,f.helpers);j=j||{};var h="",c,g="function",i=this.escapeExpression,m=this;function d(q,p){var n="",o;n+="\n <tr><td>";if(o=e.name){o=o.call(q,{hash:{},data:p})}else{o=q.name;o=typeof o===g?o.apply(q):o}n+=i(o)+"</td><td>";if(o=e.xval){o=o.call(q,{hash:{},data:p})}else{o=q.xval;o=typeof o===g?o.apply(q):o}n+=i(o)+"</td><td>";if(o=e.yval){o=o.call(q,{hash:{},data:p})}else{o=q.yval;o=typeof o===g?o.apply(q):o}n+=i(o)+"</td></tr>\n </tr>\n ";return n}h+='<p class="help-text">By column:</p>\n <table id="chart-stats-table">\n <thead><th></th><th>X</th><th>Y</th></thead>\n ';c=e.each.call(l,l.stats,{hash:{},inverse:m.noop,fn:m.program(1,d,j),data:j});if(c||c===0){h+=c}h+="\n </table>";return h})})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/packed/viz/scatterplot.js --- a/static/scripts/packed/viz/scatterplot.js +++ /dev/null @@ -1,1 +0,0 @@ -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 b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/templates/compiled/template-visualization-chartControl.js --- a/static/scripts/templates/compiled/template-visualization-chartControl.js +++ /dev/null @@ -1,40 +0,0 @@ -(function() { - var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; -templates['template-visualization-chartControl'] = template(function (Handlebars,depth0,helpers,partials,data) { - this.compilerInfo = [4,'>= 1.0.0']; -helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; - var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression, self=this; - -function program1(depth0,data) { - - - return " checked=\"true\""; - } - - buffer += "<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\">"; - if (stack1 = helpers.datapointSize) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.datapointSize; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : 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=\"animate-chart\">Animate chart transitions?: </label>\n <input type=\"checkbox\" id=\"animate-chart\"\n class=\"checkbox control\""; - stack1 = helpers['if'].call(depth0, depth0.animDuration, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data: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 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\">"; - if (stack1 = helpers.width) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.width; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - 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\">"; - if (stack1 = helpers.height) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.height; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - 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=\""; - if (stack1 = helpers.xLabel) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.xLabel; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "\" />\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=\""; - if (stack1 = helpers.yLabel) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.yLabel; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "\" />\n <p class=\"form-help help-text-small\"></p>\n </div>\n\n <input id=\"render-button\" type=\"button\" value=\"Draw\" />"; - return buffer; - }); -})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/templates/compiled/template-visualization-chartDisplay.js --- a/static/scripts/templates/compiled/template-visualization-chartDisplay.js +++ /dev/null @@ -1,20 +0,0 @@ -(function() { - var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; -templates['template-visualization-chartDisplay'] = template(function (Handlebars,depth0,helpers,partials,data) { - this.compilerInfo = [4,'>= 1.0.0']; -helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; - var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression; - - - buffer += "<svg width=\""; - if (stack1 = helpers.width) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.width; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "\" height=\""; - if (stack1 = helpers.height) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.height; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "\"></svg>"; - return buffer; - }); -})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/templates/compiled/template-visualization-dataControl.js --- a/static/scripts/templates/compiled/template-visualization-dataControl.js +++ /dev/null @@ -1,51 +0,0 @@ -(function() { - var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; -templates['template-visualization-dataControl'] = template(function (Handlebars,depth0,helpers,partials,data) { - this.compilerInfo = [4,'>= 1.0.0']; -helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; - var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression, self=this; - -function program1(depth0,data) { - - var buffer = "", stack1; - buffer += "\n <option value=\""; - if (stack1 = helpers.index) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.index; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "\">"; - if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "</option>\n "; - return buffer; - } - -function program3(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 " - + "\n <div class=\"column-select\">\n <label for=\"X-select\">Data column for X: </label>\n <select name=\"X\" id=\"X-select\">\n "; - stack1 = helpers.each.call(depth0, depth0.numericColumns, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data}); - if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\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 "; - stack1 = helpers.each.call(depth0, depth0.numericColumns, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data}); - if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n </select>\n </div>\n\n " - + "\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 "; - stack1 = helpers.each.call(depth0, depth0.allColumns, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data}); - if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n </select>\n </div>\n\n " - + "\n <div id=\"first-line-header\" style=\"display: none;\">\n <p>Possible headers: "; - if (stack1 = helpers.possibleHeaders) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.possibleHeaders; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : 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 = helpers['if'].call(depth0, depth0.usePossibleHeaders, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data: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 b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/templates/compiled/template-visualization-scatterplotControlForm.js --- a/static/scripts/templates/compiled/template-visualization-scatterplotControlForm.js +++ /dev/null @@ -1,33 +0,0 @@ -(function() { - var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; -templates['template-visualization-scatterplotControlForm'] = template(function (Handlebars,depth0,helpers,partials,data) { - this.compilerInfo = [4,'>= 1.0.0']; -helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; - var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression; - - - buffer += "\n\n<div class=\"scatterplot-container chart-container tabbable tabs-left\">\n " - + "\n <ul class=\"nav nav-tabs\">\n " - + "\n <li class=\"active\"><a href=\"#data-control\" data-toggle=\"tab\"\n title=\"Use this tab to change which data are used\">Data Controls</a></li>\n <li><a href=\"#chart-control\" data-toggle=\"tab\"\n title=\"Use this tab to change how the chart is drawn\">Chart Controls</a></li>\n <li><a href=\"#stats-display\" data-toggle=\"tab\"\n title=\"This tab will display overall statistics for your data\">Statistics</a></li>\n <li><a href=\"#chart-display\" data-toggle=\"tab\"\n title=\"This tab will display the chart\">Chart</a>\n " - + "\n <div id=\"loading-indicator\" style=\"display: none;\">\n <img class=\"loading-img\" src=\""; - if (stack1 = helpers.loadingIndicatorImagePath) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.loadingIndicatorImagePath; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "\" />\n <span class=\"loading-message\">"; - if (stack1 = helpers.message) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.message; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "</span>\n </div>\n </li>\n </ul>\n\n " - + "\n <div class=\"tab-content\">\n " - + "\n <div id=\"data-control\" class=\"tab-pane active\">\n " - + "\n </div>\n \n " - + "\n <div id=\"chart-control\" class=\"tab-pane\">\n " - + "\n </div>\n\n " - + "\n <div id=\"stats-display\" class=\"tab-pane\">\n " - + "\n </div>\n\n " - + "\n <div id=\"chart-display\" class=\"tab-pane\">\n " - + "\n </div>\n\n </div>" - + "\n</div>"; - return buffer; - }); -})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/templates/compiled/template-visualization-statsDisplay.js --- a/static/scripts/templates/compiled/template-visualization-statsDisplay.js +++ /dev/null @@ -1,33 +0,0 @@ -(function() { - var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; -templates['template-visualization-statsDisplay'] = template(function (Handlebars,depth0,helpers,partials,data) { - this.compilerInfo = [4,'>= 1.0.0']; -helpers = this.merge(helpers, Handlebars.helpers); data = data || {}; - var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression, self=this; - -function program1(depth0,data) { - - var buffer = "", stack1; - buffer += "\n <tr><td>"; - if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "</td><td>"; - if (stack1 = helpers.xval) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.xval; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "</td><td>"; - if (stack1 = helpers.yval) { stack1 = stack1.call(depth0, {hash:{},data:data}); } - else { stack1 = depth0.yval; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; } - buffer += escapeExpression(stack1) - + "</td></tr>\n </tr>\n "; - return buffer; - } - - buffer += "<p class=\"help-text\">By column:</p>\n <table id=\"chart-stats-table\">\n <thead><th></th><th>X</th><th>Y</th></thead>\n "; - stack1 = helpers.each.call(depth0, depth0.stats, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data}); - if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n </table>"; - return buffer; - }); -})(); \ No newline at end of file diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/templates/visualization-templates.html --- a/static/scripts/templates/visualization-templates.html +++ /dev/null @@ -1,182 +0,0 @@ -<script type="text/template" class="template-visualization" id="template-visualization-scatterplotControlForm"> -{{! main layout }} - -<div class="scatterplot-container chart-container tabbable tabs-left"> - {{! tab buttons/headers using Bootstrap }} - <ul class="nav nav-tabs"> - {{! start with the data controls as the displayed tab }} - <li class="active"><a href="#data-control" data-toggle="tab" - title="Use this tab to change which data are used">Data Controls</a></li> - <li><a href="#chart-control" data-toggle="tab" - title="Use this tab to change how the chart is drawn">Chart Controls</a></li> - <li><a href="#stats-display" data-toggle="tab" - title="This tab will display overall statistics for your data">Statistics</a></li> - <li><a href="#chart-display" data-toggle="tab" - title="This tab will display the chart">Chart</a> - {{! loading indicator - initially hidden }} - <div id="loading-indicator" style="display: none;"> - <img class="loading-img" src="{{loadingIndicatorImagePath}}" /> - <span class="loading-message">{{message}}</span> - </div> - </li> - </ul> - - {{! data form, chart config form, stats, and chart all get their own tab }} - <div class="tab-content"> - {{! ---------------------------- tab for data settings form }} - <div id="data-control" class="tab-pane active"> - {{! rendered separately }} - </div> - - {{! ---------------------------- tab for chart graphics control form }} - <div id="chart-control" class="tab-pane"> - {{! rendered separately }} - </div> - - {{! ---------------------------- tab for data statistics }} - <div id="stats-display" class="tab-pane"> - {{! rendered separately }} - </div> - - {{! ---------------------------- tab for actual chart }} - <div id="chart-display" class="tab-pane"> - {{! chart rendered separately }} - </div> - - </div>{{! end .tab-content }} -</div>{{! end .chart-control }} -</script> - -<script type="text/template" class="template-visualization" id="template-visualization-dataControl"> - - <p class="help-text"> - Use the following controls to change the data used by the chart. - Use the 'Draw' button to render (or re-render) the chart with the current settings. - </p> - - {{! column selector containers }} - <div class="column-select"> - <label for="X-select">Data column for X: </label> - <select name="X" id="X-select"> - {{#each numericColumns}} - <option value="{{index}}">{{name}}</option> - {{/each}} - </select> - </div> - <div class="column-select"> - <label for="Y-select">Data column for Y: </label> - <select name="Y" id="Y-select"> - {{#each numericColumns}} - <option value="{{index}}">{{name}}</option> - {{/each}} - </select> - </div> - - {{! optional id column }} - <div id="include-id"> - <label for="include-id-checkbox">Include a third column as data point IDs?</label> - <input type="checkbox" name="include-id" id="include-id-checkbox" /> - <p class="help-text-small"> - These will be displayed (along with the x and y values) when you hover over - a data point. - </p> - </div> - <div class="column-select" style="display: none"> - <label for="ID-select">Data column for IDs: </label> - <select name="ID" id="ID-select"> - {{#each allColumns}} - <option value="{{index}}">{{name}}</option> - {{/each}} - </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> - -<script type="text/template" class="template-visualization" id="template-visualization-chartControl"> - <p class="help-text"> - Use the following controls to how the chart is displayed. - The slide controls can be moved by the mouse or, if the 'handle' is in focus, your keyboard's arrow keys. - Move the focus between controls by using the tab or shift+tab keys on your keyboard. - Use the 'Draw' button to render (or re-render) the chart with the current settings. - </p> - - <div id="datapointSize" class="form-input numeric-slider-input"> - <label for="datapointSize">Size of data point: </label> - <div class="slider-output">{{datapointSize}}</div> - <div class="slider"></div> - <p class="form-help help-text-small"> - Size of the graphic representation of each data point - </p> - </div> - - <div id="animDuration" class="form-input checkbox-input"> - <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 chart - </p> - </div> - - <div id="width" class="form-input numeric-slider-input"> - <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 chart margins and axes) - </p> - </div> - - <div id="height" class="form-input numeric-slider-input"> - <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 chart margins and axes) - </p> - </div> - - <div id="X-axis-label"class="text-input form-input"> - <label for="X-axis-label">Re-label the X axis: </label> - <input type="text" name="X-axis-label" id="X-axis-label" value="{{xLabel}}" /> - <p class="form-help help-text-small"></p> - </div> - - <div id="Y-axis-label" class="text-input form-input"> - <label for="Y-axis-label">Re-label the Y axis: </label> - <input type="text" name="Y-axis-label" id="Y-axis-label" value="{{yLabel}}" /> - <p class="form-help help-text-small"></p> - </div> - - <input id="render-button" type="button" value="Draw" /> -</script> - -<script type="text/template" class="template-visualization" id="template-visualization-statsDisplay"> - <p class="help-text">By column:</p> - <table id="chart-stats-table"> - <thead><th></th><th>X</th><th>Y</th></thead> - {{#each stats}} - <tr><td>{{name}}</td><td>{{xval}}</td><td>{{yval}}</td></tr> - </tr> - {{/each}} - </table> -</script> - -<script type="text/template" class="template-visualization" id="template-visualization-chartDisplay"> - <svg width="{{width}}" height="{{height}}"></svg> -</script> diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a static/scripts/viz/scatterplot.js --- a/static/scripts/viz/scatterplot.js +++ /dev/null @@ -1,488 +0,0 @@ -/* ============================================================================= -todo: - outside this: - BUG: setting width, height in plot controls doesn't re-interpolate data locations!! - BUG?: get metadata_column_names (from datatype if necessary) - BUG: single vis in popupmenu should have tooltip with that name NOT 'Visualizations' - - wire label setters, anim setter - - TwoVarScatterplot: - ??: maybe better to do this with a canvas... - save as visualization - to seperate file? - remove underscore dependencies - add interface to change values (seperate)? - download svg -> base64 encode - incorporate glyphs, glyph state renderers - - ScatterplotSettingsForm: - some css bug that lowers the width of settings form when plot-controls tab is open - causes chart to shift - what can be abstracted/reused for other graphs? - avoid direct manipulation of this.plot - allow option to put plot into seperate tab of interface (for small multiples) - - provide callback in view to load data incrementally - for large sets - paginate - handle rerender - use endpoint (here and on the server (fileptr)) - fetch (new?) data - handle rerender - use d3.TSV? - render warning on long data (> maxDataPoints) - adjust endpoint - - selectable list of preset column comparisons (rnaseq etc.) - how to know what sort of Tabular the data is? - smarter about headers - validate columns selection (here or server) - - set stats column names by selected columns - move chart into tabbed area... - - Scatterplot.mako: - multiple plots on one page (small multiples) - ?? ensure svg styles thru d3 or css? - d3: configable (easily) - css: standard - better maintenance - ? override at config - -============================================================================= */ -/** - * Two Variable scatterplot visualization using d3 - * Uses semi transparent circles to show density of data in x, y grid - * usage : - * var plot = new TwoVarScatterplot({ containerSelector : 'div#my-plot', ... }) - * plot.render( xColumnData, yColumnData ); - * - * depends on: d3, underscore - */ -function TwoVarScatterplot( config ){ - var TICK_LINE_AND_PADDING = 10, - GUESS_AT_SVG_CHAR_WIDTH = 7, - GUESS_AT_SVG_CHAR_HEIGHT = 10, - PADDING = 8, - X_LABEL_TOO_LONG_AT = 5; - - // set up logging - //this.debugging = true; - this.log = function(){ - if( this.debugging && console && console.debug ){ - var args = Array.prototype.slice.call( arguments ); - args.unshift( this.toString() ); - console.debug.apply( console, args ); - } - }; - this.log( 'new TwoVarScatterplot:', config ); - - // ........................................................ set up chart config - // config will default to these values when not passed in - //NOTE: called on new - this.defaults = { - id : 'TwoVarScatterplot', - containerSelector : 'body', - //TODO??: needed? - maxDataPoints : 30000, - datapointSize : 4, - animDuration : 500, - //TODO: variable effect (not always exactly # of ticks set to) - xNumTicks : 10, - yNumTicks : 10, - xAxisLabelBumpY : 40, - yAxisLabelBumpX : -40, - width : 400, - height : 400, - //TODO: anyway to make this a sub-obj? - 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, config ); - this.log( 'intial config:', this.config ); - - this.updateConfig = function( newConfig, rerender ){ - // setter for chart config - //TODO: validate here - _.extend( this.config, newConfig ); - this.log( this + '.updateConfig:', this.config ); - //TODO: implement rerender flag - }; - - // ........................................................ helpers - this.toString = function(){ - return this.config.id; - }; - // conv. methods for svg transforms - this.translateStr = function( x, y ){ - return 'translate(' + x + ',' + y + ')'; - }; - this.rotateStr = function( d, x, y ){ - return 'rotate(' + d + ',' + x + ',' + y + ')'; - }; - - // ........................................................ initial element creation - this.adjustChartDimensions = function( top, right, bottom, left ){ - //this.log( this + '.adjustChartDimensions', arguments ); - top = top || 0; - right = right || 0; - bottom = bottom || 0; - left = left || 0; - this.svg - .attr( "width", this.config.width + ( this.config.marginRight + right ) - + ( this.config.marginLeft + left ) ) - .attr( "height", this.config.height + ( this.config.marginTop + top ) - + ( this.config.marginBottom + bottom ) ) - // initial is hidden - show it - .style( 'display', 'block' ); - - // move content group away from margins - //TODO: allow top, right axis - this.content = this.svg.select( "g.content" ) - .attr( "transform", this.translateStr( this.config.marginLeft + left, this.config.marginTop + top ) ); - }; - - // ........................................................ data and scales - this.preprocessData = function( data, min, max ){ - //this.log( this + '.preprocessData', arguments ); - //TODO: filter by min, max if set - - // set a cap on the data, limit to first n points - return ( data.length > this.config.maxDataPoints )? ( data.slice( 0, this.config.maxDataPoints ) ): ( data ); - }; - - this.findMinMaxes = function( xCol, yCol, meta ){ - //this.log( this + '.findMinMaxes', arguments ); - // configuration takes priority, otherwise meta (from the server) if passed, last-resort: compute it here - this.xMin = this.config.xMin || ( meta )?( meta[0].min ):( d3.min( xCol ) ); - this.xMax = this.config.xMax || ( meta )?( meta[0].max ):( d3.max( xCol ) ); - this.yMin = this.config.yMin || ( meta )?( meta[1].min ):( d3.min( yCol ) ); - this.yMax = this.config.yMax || ( meta )?( meta[1].max ):( d3.max( yCol ) ); - }; - - this.setUpScales = function(){ - //this.log( this + '.setUpScales', arguments ); - // Interpolation for x, y based on data domains - 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 ]); - }; - - // ........................................................ axis and ticks - this.setUpXAxis = function(){ - //this.log( this + '.setUpXAxis', arguments ); - // origin: bottom, left - //TODO: incoporate top, right - this.xAxisFn = d3.svg.axis() - .scale( this.xScale ) - .ticks( this.config.xNumTicks ) - .orient( 'bottom' ); - this.xAxis// = content.select( 'g#x-axis' ) - .attr( 'transform', this.translateStr( 0, this.config.height ) ) - .call( this.xAxisFn ); - //this.log( 'xAxis:', this.xAxis ); - - //TODO: adjust ticks when tick labels are long - move odds down and extend tick line - // (for now) hide them - var xLongestTickLabel = d3.max( _.map( [ this.xMin, this.xMax ], - function( number ){ return ( String( number ) ).length; } ) ); - //this.log( 'xLongestTickLabel:', xLongestTickLabel ); - if( xLongestTickLabel >= X_LABEL_TOO_LONG_AT ){ - this.xAxis.selectAll( 'g' ).filter( ':nth-child(odd)' ).style( 'display', 'none' ); - } - - this.log( 'this.config.xLabel:', this.config.xLabel ); - this.xAxisLabel// = xAxis.select( 'text#x-axis-label' ) - .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.log( this + '.setUpYAxis', arguments ); - this.yAxisFn = d3.svg.axis() - .scale( this.yScale ) - .ticks( this.config.yNumTicks ) - .orient( 'left' ); - this.yAxis// = content.select( 'g#y-axis' ) - .call( this.yAxisFn ); - //this.log( 'yAxis:', this.yAxis ); - - // a too complicated section for increasing the left margin when tick labels are long - // get the tick labels for the y axis - var yTickLabels = this.yAxis.selectAll( 'text' ).filter( function( e, i ){ return i !== 0; } ); - this.log( 'yTickLabels:', yTickLabels ); - - // get the longest label length (or 0 if no labels) - this.yLongestLabel = d3.max( - //NOTE: d3 returns an nested array - use the plain array inside ([0]) - yTickLabels[0].map( function( e, i ){ - return ( d3.select( e ).text() ).length; - }) - ) || 0; - //this.log( 'yLongestLabel:', this.yLongestLabel ); - //TODO: lose the guessing if possible - var neededY = TICK_LINE_AND_PADDING + ( this.yLongestLabel * GUESS_AT_SVG_CHAR_WIDTH ) - + PADDING + GUESS_AT_SVG_CHAR_HEIGHT; - //this.log( 'neededY:', neededY ); - - // increase width for yLongerStr, increase margin for y - //TODO??: (or transform each number: 2k) - this.config.yAxisLabelBumpX = -( neededY - GUESS_AT_SVG_CHAR_HEIGHT ); - if( this.config.marginLeft < neededY ){ - var adjusting = ( neededY ) - this.config.marginLeft; - adjusting = ( adjusting < 0 )?( 0 ):( adjusting ); - //this.log( 'adjusting:', adjusting ); - - // update dimensions, translations - this.adjustChartDimensions( 0, 0, 0, adjusting ); - } - //this.log( 'this.config.yAxisLableBumpx, this.config.marginLeft:', - // this.config.yAxisLabelBumpX, this.config.marginLeft ); - - this.yAxisLabel// = yAxis.select( 'text#y-axis-label' ) - .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.log( 'yAxisLabel:', this.yAxisLabel ); - }; - - // ........................................................ grid lines - this.renderGrid = function(){ - //this.log( this + '.renderGrid', arguments ); - // VERTICAL - // select existing - this.vGridLines = this.content.selectAll( 'line.v-grid-line' ) - .data( this.xScale.ticks( this.xAxisFn.ticks()[0] ) ); - - // append any extra lines needed (more ticks) - this.vGridLines.enter().append( 'svg:line' ) - .classed( 'grid-line v-grid-line', true ); - - // update the attributes of existing and appended - this.vGridLines - .attr( 'x1', this.xScale ) - .attr( 'y1', 0 ) - .attr( 'x2', this.xScale ) - .attr( 'y2', this.config.height ); - - // remove unneeded (less ticks) - this.vGridLines.exit().remove(); - //this.log( 'vGridLines:', this.vGridLines ); - - // HORIZONTAL - 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.log( 'hGridLines:', this.hGridLines ); - }; - - // ........................................................ data points - this.renderDatapoints = function( xCol, yCol, ids ){ - this.log( this + '.renderDatapoints', arguments ); - 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( xCol[ i ] ); - }, - yPosFn = function( d, i ){ - //if( d ){ this.log( 'y.data:', newYCol[ i ], 'plotted:', plot.yScale( newYCol[ i ] ) ); } - return plot.yScale( yCol[ i ] ); - }; - - //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; - datapoints.enter() - .append( 'svg:circle' ) - .each( function(){ count += 1; } ) - .classed( "glyph", true ) - .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 - count = 0; - datapoints - // ...animate to final position - .transition().duration( this.config.animDuration ) - .each( function(){ count += 1; } ) - .attr( "cx", xPosFn ) - .attr( "cy", yPosFn ) - .attr( "r", plot.config.datapointSize ); - this.log( count, ' existing glyphs transitioned' ); - - // 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' ); - - 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 ); - datapoint - .style( 'fill', 'red' ) - .style( 'fill-opacity', 1 ); - - // create horiz, vert lines to axis - plot.content.append( 'line' ) - .attr( 'stroke', 'red' ) - .attr( 'stroke-width', 1 ) - // 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 ); - - // 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 ); - plot.content.selectAll( '.hoverline' ).remove(); - if( plot.datapointInfoBox ){ - plot.datapointInfoBox.remove(); - } - }); - }, - - this.render = function( columnData, meta ){ - this.log( this + '.render', arguments ); - this.log( '\t config:', this.config ); - - // prepare the data - //pre: columns passed are numeric - //pre: at least two columns are passed - //assume: first column is x, second column is y, any remaining aren't used - var xCol = columnData[0], - yCol = columnData[1], - ids = ( columnData.length > 2 )?( columnData[2] ):( undefined ); - //this.log( this + '.render', xCol.length, yCol.length, this.config ); - - //pre: xCol.len == yCol.len - xCol = this.preprocessData( xCol ); - yCol = this.preprocessData( yCol ); - this.log( 'xCol len', xCol.length, 'yCol len', yCol.length ); - - this.findMinMaxes( xCol, yCol, meta ); - //this.log( 'xMin, xMax, yMin, yMax:', this.xMin, this.xMax, this.yMin, this.yMax ); - this.setUpScales(); - - // 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 ); - } - //this.log( 'svg:', this.svg ); - //this.log( 'content:', this.content ); - - 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' ); - } - //this.log( 'xAxis:', this.xAxis, 'xAxisLabel:', this.xAxisLabel ); - - 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.log( 'yAxis:', this.yAxis, 'yAxisLabel:', this.yAxisLabel ); - - this.setUpXAxis(); - this.setUpYAxis(); - - 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 b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a templates/webapps/galaxy/visualization/scatterplot.mako --- a/templates/webapps/galaxy/visualization/scatterplot.mako +++ /dev/null @@ -1,256 +0,0 @@ -<%inherit file="/base.mako"/> - -<%def name="stylesheets()"> -${parent.stylesheets()} -${h.css( - "base", - "autocomplete_tagging", - "jquery-ui/smoothness/jquery-ui" -)} - -<style type="text/css"> -/*TODO: use/move into base.less*/ -* { margin: 0px; padding: 0px; } - -/* -------------------------------------------- general layout */ -div.tab-pane { - padding: 8px; -} - -/* -------------------------------------------- header */ -.header { - margin-bottom: 8px; -} - -#chart-header { - padding : 8px; - background-color: #ebd9b2; - margin-bottom: 16px; - overflow: auto; -} - -#chart-header .subtitle { - margin: -4px 0px 0px 4px; - padding : 0; - color: white; - font-size: small; -} - -/* -------------------------------------------- main layout */ -#scatterplot { - /*from width + margin of chart?*/ -} - -.scatterplot-container .tab-pane { -} - -/* -------------------------------------------- all controls */ - -#scatterplot input[type=button], -#scatterplot select { - width: 100%; - max-width: 256px; - margin-bottom: 8px; -} - -#scatterplot .help-text, -#scatterplot .help-text-small { - color: grey; -} - -#scatterplot .help-text { - padding-bottom: 16px; -} - -#scatterplot .help-text-small { - padding: 4px; - font-size: smaller; -} - -#scatterplot > * { -} - -#scatterplot input[value=Draw] { - display: block; - margin-top: 16px; -} - -#scatterplot .numeric-slider-input { - max-width: 70%; -} - -/* -------------------------------------------- data controls */ - -/* -------------------------------------------- chart controls */ -#chart-control .form-input { - /*display: table-row;*/ -} - -#chart-control label { - /*text-align: right;*/ - margin-bottom: 8px; - /*display: table-cell;*/ -} - -#chart-control .slider { - /*display: table-cell;*/ - height: 8px; - display: block; - margin: 8px 0px 0px 8px; -} - -#chart-control .slider-output { - /*display: table-cell;*/ - float: right; -} - -#chart-control input[type="text"] { - border: 1px solid lightgrey; -} - - -/* -------------------------------------------- statistics */ -#stats-display table#chart-stats-table { - width: 100%; -} - -#stats-display #chart-stats-table th { - width: 30%; - padding: 4px; - font-weight: bold; - color: grey; -} - -#stats-display #chart-stats-table td { - border: solid lightgrey; - border-width: 1px 0px 0px 1px; - padding: 4px; -} - -#stats-display #chart-stats-table td:nth-child(1) { - border-width: 1px 0px 0px 0px; - padding-right: 1em; - text-align: right; - font-weight: bold; - color: grey; -} - -/* -------------------------------------------- load indicators */ -#loading-indicator { - margin: 12px 0px 0px 8px; -} - -#scatterplot #loading-indicator .loading-message { - font-style: italic; - font-size: smaller; - color: grey; -} - -/* -------------------------------------------- chart area */ -#chart-holder { - overflow: auto; - margin-left: 8px; -} - -svg .grid-line { - fill: none; - stroke: lightgrey; - stroke-opacity: 0.5; - shape-rendering: crispEdges; - stroke-dasharray: 3, 3; -} - -svg .axis path, svg .axis line { - fill: none; - stroke: black; - shape-rendering: crispEdges; -} - -svg .axis text { - font-family: monospace; - font-size: 12px; -} - -svg #x-axis-label, svg #y-axis-label { - font-family: sans-serif; - font-size: 10px; -} - -svg .glyph { - stroke: none; - fill: black; - fill-opacity: 0.2; -} - -/* -------------------------------------------- info box */ -.chart-info-box { - border-radius: 4px; - padding: 4px; - background-color: white; - border: 1px solid black; -} - -</style> - -</%def> - -<%def name="javascripts()"> -${parent.javascripts()} -${h.js( - - "libs/underscore", - "libs/jquery/jquery-ui", - "libs/d3", - - "mvc/base-mvc", - "utils/LazyDataLoader", - "viz/scatterplot" -)} - -${h.templates( - "../../templates/compiled/template-visualization-scatterplotControlForm", - "../../templates/compiled/template-visualization-dataControl", - "../../templates/compiled/template-visualization-chartControl", - "../../templates/compiled/template-visualization-chartDisplay", - "../../templates/compiled/template-visualization-statsDisplay" -)} - -${h.js( - "mvc/visualization/scatterplotControlForm", -)} - -<script type="text/javascript"> -$(function(){ - - var hda = ${h.to_json_string( trans.security.encode_dict_ids( hda.to_dict() ) )}, - querySettings = ${h.to_json_string( query_args )}, - chartConfig = _.extend( querySettings, { - containerSelector : '#chart', - //TODO: move to ScatterplotControlForm.initialize - marginTop : ( querySettings.marginTop > 20 )?( querySettings.marginTop ):( 20 ), - - xColumn : querySettings.xColumn, - yColumn : querySettings.yColumn, - idColumn : querySettings.idColumn - }); - //console.debug( querySettings ); - - var settingsForm = new ScatterplotControlForm({ - dataset : hda, - apiDatasetsURL : "${h.url_for( controller='/api/datasets', action='index' )}", - el : $( '#scatterplot' ), - chartConfig : chartConfig - }).render(); - -}); -</script> -</%def> - -<%def name="body()"> - <!--dataset info--> - <div id="chart-header" class="header"> - <h2 class="title">Scatterplot of '${hda.name}'</h2> - <p class="subtitle">${hda.info}</p> - </div> - <div id="scatterplot" class="scatterplot-control-form"></div> -</%def> diff -r b71c9af7c17c48e8ed1c45918a459f5b2c0167e4 -r 044ead55435801561acdf72fe225209239202a5a templates/webapps/galaxy/visualization/v_fwork_test.mako --- a/templates/webapps/galaxy/visualization/v_fwork_test.mako +++ /dev/null @@ -1,132 +0,0 @@ -<%inherit file="/base.mako"/> -<%def name="title()"> -${visualization_name} -</%def> - - -<%def name="stylesheets()"> -${parent.stylesheets()} -${h.css( - "base", -)} - -<style type="text/css"> -/*TODO: use/move into base.less*/ -* { margin: 0px; padding: 0px; } -</style> - -</%def> - -<%def name="process_hda( hda )"> -<% - hda_dict = hda.to_dict() - hda_dict[ 'id' ] = trans.security.encode_id( hda_dict[ 'id' ] ) - hda_dict[ 'history_id' ] = trans.security.encode_id( hda_dict[ 'history_id' ] ) - del hda_dict[ 'peek' ] - return hda_dict -%> -</%def> - -<%def name="javascripts()"> -${parent.javascripts()} -<script type="text/javascript"> -$(function(){ - -//var data = { -// title : 'shared with user visualization', -// type : 'test', -// slug : 'shared', -// annotation : 'a visualization shared with a specific user', -// config : { -// x : 10, -// y : 10 -// } -// }; - -//var creationPromise = jQuery.ajax( '/api/visualizations', { -// type : 'POST', -// contentType : 'application/json', -// data : JSON.stringify( data ) -// }); -//creationPromise.success(function(){ -// console.debug( 'success' ); -//}); -//creationPromise.error(function(){ -// console.debug( 'error' ); -//}); - - -}); -</script> -</%def> - -<%def name="print_var( name, var )"> -%if var is not None: - <% t = str( type( var ) )[1:-1] %> - <p>${name}: ${t}, ${var}</p> -%else: - <p>No ${name}</p> -%endif -</%def> - -<%def name="body()"> - <% - import pprint - print self - print self.context - pprint.pprint( self.context.kwargs, indent=4 ) - %> - <% - vars_to_print = [ - ( 'default', default ), - ( 'string', string ), - ( 'boolean', boolean ), - ( 'integer', integer ), - ( 'float', float ), - ( 'json', json ), - ] - %> - %for name, var in vars_to_print: - ${print_var( name, var )} - %endfor - - %if visualization: - <h1>${visualization.title}</h1> - <p>id: ${trans.security.encode_id( visualization.id )}</p> - <p>dbkey: ${visualization.dbkey}</p> - <p>config: - <pre>${h.to_json_string( visualization.latest_revision.config, sort_keys=True, indent=( 4 * ' ' ) )}</pre> - </p> - %endif - - %if dataset: - <h1>${dataset.name}</h1> - <p>id: ${trans.security.encode_id( dataset.id )}</p> - <p>history id: ${trans.security.encode_id( dataset.history.id )}</p> - <pre> - ${h.to_json_string( process_hda( dataset ), sort_keys=True, indent=( 4 * ' ' ) )} - </pre> - %endif - - %if dataset_instance: - <h1>${dataset_instance.name}</h1> - <p>id: ${trans.security.encode_id( dataset_instance.id )}</p> - %if hda_ldda == 'hda': - <p>history id: ${trans.security.encode_id( dataset_instance.history.id )}</p> - <pre> - ${h.to_json_string( process_hda( dataset_instance ), sort_keys=True, indent=( 4 * ' ' ) )} - </pre> - %else: - <p>(LibraryDatasetDatasetAssociation)</p> - %endif - %endif - - %if query_args: - <ul> - %for key, val in query_args.items(): - <li>${key} : ${val}</li> - %endfor - </ul> - %endif - -</%def> 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.
participants (1)
-
commits-noreply@bitbucket.org