diff --git a/lib/galaxy/visualization/data_providers/phyloviz/__init__.py b/lib/galaxy/visualization/data_providers/phyloviz/__init__.py
index 71e5bbe05a9..85745da88ce 100644
--- a/lib/galaxy/visualization/data_providers/phyloviz/__init__.py
+++ b/lib/galaxy/visualization/data_providers/phyloviz/__init__.py
@@ -1,3 +1,4 @@
+
""" Data providers code for PhyloViz """
from galaxy.visualization.data_providers.basic import BaseDataProvider
@@ -40,4 +41,3 @@ class PhylovizDataProvider( BaseDataProvider ):
rval[ "msg"] = parseMsg
return rval
-
diff --git a/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py b/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py
index 0d832830eea..fa6e272c2e9 100644
--- a/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py
+++ b/lib/galaxy/visualization/data_providers/phyloviz/newickparser.py
@@ -77,8 +77,6 @@ class Newick_Parser(Base_Parser):
childrenNodes += [node]
return childrenNodes
-
-
def _mapName(self, newickString, nameMap):
"""
Necessary to replace names of terms inside nexus representation
@@ -108,9 +106,9 @@ class Newick_Parser(Base_Parser):
newString += newickString[start:]
return newString
-
def parseNode(self, string, depth):
- """ Recursive method for parsing newick string, works by stripping down the string into substring
+ """
+ Recursive method for parsing newick string, works by stripping down the string into substring
of newick contained with brackers, which is used to call itself.
Eg ... ( A, B, (D, E)C, F, G ) ...
diff --git a/lib/galaxy/visualization/data_providers/registry.py b/lib/galaxy/visualization/data_providers/registry.py
index 185ee3ecf03..ff30ec8ef4d 100644
--- a/lib/galaxy/visualization/data_providers/registry.py
+++ b/lib/galaxy/visualization/data_providers/registry.py
@@ -53,7 +53,7 @@ class DataProviderRegistry( object ):
elif isinstance( original_dataset.datatype, Tabular ):
data_provider_class = ColumnDataProvider
elif isinstance( original_dataset.datatype, ( Nexus, Newick, Phyloxml ) ):
- data_provider_class = genome.PhylovizDataProvider
+ data_provider_class = PhylovizDataProvider
data_provider = data_provider_class( original_dataset=original_dataset )
diff --git a/static/scripts/packed/viz/phyloviz.js b/static/scripts/packed/viz/phyloviz.js
index 99bb242b702..18c051899b8 100644
--- a/static/scripts/packed/viz/phyloviz.js
+++ b/static/scripts/packed/viz/phyloviz.js
@@ -1 +1 @@
-define(["libs/d3","viz/visualization","mvc/data"],function(m,f,g){var l=Backbone.View.extend({className:"UserMenuBase",isAcceptableValue:function(r,p,n){var o=this,s=r.val(),t=r.attr("displayLabel")||r.attr("id").replace("phyloViz","");function q(u){return !isNaN(parseFloat(u))&&isFinite(u)}if(!q(s)){alert(t+" is not a number!");return false}if(s>n){alert(t+" is too large.");return false}else{if(s
360){return w}else{v=x;return w}};w.separation=function(x){if(typeof x==="undefined"){return s}else{s=x;return w}};w.links=function(x){return m.layout.tree().links(x)};w.nodes=function(A,y){var z=r.call(w,A,y),x=[],C=0,B=0;z.forEach(function(D){var E=D.data;E.depth=D.depth;C=E.depth>C?E.depth:C;x.push(E)});x.forEach(function(D){if(!D.children){B+=1;D.depth=C}});u=q==="Circular"?v/B:u;t=0;o(x[0],C,u,null);return x};function o(B,D,A,z){var y=B.children,x=0;var C=B.dist||p;C=C>1?1:C;B.dist=C;if(z!==null){B.y0=z.y0+C*s}else{B.y0=n}if(!y){B.x0=t++*A}else{y.forEach(function(E){E.parent=B;x+=o(E,D,A,B)});B.x0=x/y.length}B.x=B.x0;B.y=B.y0;return B.x0}return w}var b=f.Visualization.extend({defaults:{layout:"Linear",separation:250,leafHeight:18,type:"phyloviz",title:"Title",scaleFactor:1,translate:[0,0],fontSize:12,selectedNode:null,nodeAttrChangedTime:0},initialize:function(n){this.set("dataset",new g.Dataset({id:n.dataset_id}))},root:{},toggle:function(n){if(typeof n==="undefined"){return}if(n.children){n._children=n.children;n.children=null}else{n.children=n._children;n._children=null}},toggleAll:function(n){if(n.children&&n.children.length!==0){n.children.forEach(this.toggleAll);toggle(n)}},getData:function(){return this.root},save:function(){var n=this.root;o(n);this.set("root",n);function o(q){delete q.parent;if(q._selected){delete q._selected}if(q.children){q.children.forEach(o)}if(q._children){q._children.forEach(o)}}var p=jQuery.extend(true,{},this.attributes);p.selectedNode=null;show_message("Saving to Galaxy","progress");return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(p)},success:function(q){var r=q.url.split("id=")[1].split("&")[0],s="/visualization?id="+r;window.history.pushState({},"",s+window.location.hash);hide_modal()}})}});var d=Backbone.View.extend({defaults:{nodeRadius:4.5},stdInit:function(o){var n=this;n.model.on("change:separation change:leafHeight change:fontSize change:nodeAttrChangedTime",n.updateAndRender,n);n.vis=o.vis;n.i=0;n.maxDepth=-1;n.width=o.width;n.height=o.height},updateAndRender:function(p){var o=m.select(".vis"),n=this;p=p||n.model.root;n.renderNodes(p);n.renderLinks(p);n.addTooltips()},renderLinks:function(n){var w=this;var o=w.diagonal;var p=w.duration;var r=w.layoutMode;var t=w.vis.selectAll("g.completeLink").data(w.tree.links(w.nodes),function(x){return x.target.id});var v=function(x){x.pos0=x.source.y0+" "+x.source.x0;x.pos1=x.source.y0+" "+x.target.x0;x.pos2=x.target.y0+" "+x.target.x0};var u=t.enter().insert("svg:g","g.node").attr("class","completeLink");u.append("svg:path").attr("class","link").attr("d",function(x){v(x);return"M "+x.pos0+" L "+x.pos1});var s=t.transition().duration(500);s.select("path.link").attr("d",function(x){v(x);return"M "+x.pos0+" L "+x.pos1+" L "+x.pos2});var q=t.exit().remove()},selectNode:function(o){var n=this;m.selectAll("g.node").classed("selectedHighlight",function(p){if(o.id===p.id){if(o._selected){delete o._selected;return false}else{o._selected=true;return true}}return false});n.model.set("selectedNode",o);$("#phyloVizSelectedNodeName").val(o.name);$("#phyloVizSelectedNodeDist").val(o.dist);$("#phyloVizSelectedNodeAnnotation").val(o.annotation||"")},addTooltips:function(){$(".bs-tooltip").remove();$(".node").attr("data-original-title",function(){var o=this.__data__,n=o.annotation||"None";return o?(o.name?o.name+" ":"")+"Dist: "+o.dist+" Annotation: "+n:""}).tooltip({placement:"top",trigger:"hover"})}});var a=d.extend({initialize:function(o){var n=this;n.margins=o.margins;n.layoutMode="Linear";n.stdInit(o);n.layout();n.updateAndRender(n.model.root)},layout:function(){var n=this;n.tree=new h().layoutMode("Linear");n.diagonal=m.svg.diagonal().projection(function(o){return[o.y,o.x]})},renderNodes:function(n){var u=this,v=u.model.get("fontSize")+"px";u.tree.separation(u.model.get("separation")).leafHeight(u.model.get("leafHeight"));var q=500,o=u.tree.separation(u.model.get("separation")).nodes(u.model.root);var p=u.vis.selectAll("g.node").data(o,function(w){return w.name+w.id||(w.id=++u.i)});u.nodes=o;u.duration=q;var r=p.enter().append("svg:g").attr("class","node").on("dblclick",function(){m.event.stopPropagation()}).on("click",function(w){if(m.event.altKey){u.selectNode(w)}else{if(w.children&&w.children.length===0){return}u.model.toggle(w);u.updateAndRender(w)}});r.attr("transform",function(w){return"translate("+n.y0+","+n.x0+")"});r.append("svg:circle").attr("r",0.000001).style("fill",function(w){return w._children?"lightsteelblue":"#fff"});r.append("svg:text").attr("class","nodeLabel").attr("x",function(w){return w.children||w._children?-10:10}).attr("dy",".35em").attr("text-anchor",function(w){return w.children||w._children?"end":"start"}).style("fill-opacity",0.000001);var s=p.transition().duration(q);s.attr("transform",function(w){return"translate("+w.y+","+w.x+")"});s.select("circle").attr("r",u.defaults.nodeRadius).style("fill",function(w){return w._children?"lightsteelblue":"#fff"});s.select("text").style("fill-opacity",1).style("font-size",v).text(function(w){return w.name});var t=p.exit().transition().duration(q).remove();t.select("circle").attr("r",0.000001);t.select("text").style("fill-opacity",0.000001);o.forEach(function(w){w.x0=w.x;w.y0=w.y})}});var j=Backbone.View.extend({className:"phyloviz",initialize:function(o){var n=this;n.MIN_SCALE=0.05;n.MAX_SCALE=5;n.MAX_DISPLACEMENT=500;n.margins=[10,60,10,80];n.width=$("#PhyloViz").width();n.height=$("#PhyloViz").height();n.radius=n.width;n.data=o.data;$(window).resize(function(){n.width=$("#PhyloViz").width();n.height=$("#PhyloViz").height();n.render()});n.phyloTree=new b(o.config);n.phyloTree.root=n.data;n.zoomFunc=m.behavior.zoom().scaleExtent([n.MIN_SCALE,n.MAX_SCALE]);n.zoomFunc.translate(n.phyloTree.get("translate"));n.zoomFunc.scale(n.phyloTree.get("scaleFactor"));n.navMenu=new c(n);n.settingsMenu=new i({phyloTree:n.phyloTree});n.nodeSelectionView=new e({phyloTree:n.phyloTree});n.search=new k();setTimeout(function(){n.zoomAndPan()},1000)},render:function(){var o=this;$("#PhyloViz").empty();o.mainSVG=m.select("#PhyloViz").append("svg:svg").attr("width",o.width).attr("height",o.height).attr("pointer-events","all").call(o.zoomFunc.on("zoom",function(){o.zoomAndPan()}));o.boundingRect=o.mainSVG.append("svg:rect").attr("class","boundingRect").attr("width",o.width).attr("height",o.height).attr("stroke","black").attr("fill","white");o.vis=o.mainSVG.append("svg:g").attr("class","vis");o.layoutOptions={model:o.phyloTree,width:o.width,height:o.height,vis:o.vis,margins:o.margins};$("#title").text("Phylogenetic Tree from "+o.phyloTree.get("title")+":");var n=new a(o.layoutOptions)},zoomAndPan:function(n){var t,p;if(typeof n!=="undefined"){t=n.zoom;p=n.translate}var w=this,r=w.zoomFunc.scale(),v=w.zoomFunc.translate(),s="",u="";switch(t){case"reset":r=1;v=[0,0];break;case"+":r*=1.1;break;case"-":r*=0.9;break;default:if(typeof t==="number"){r=t}else{if(m.event!==null){r=m.event.scale}}}if(rw.MAX_SCALE){return}w.zoomFunc.scale(r);s="translate("+w.margins[3]+","+w.margins[0]+") scale("+r+")";if(m.event!==null){u="translate("+m.event.translate+")"}else{if(typeof p!=="undefined"){var q=p.split(",")[0];var o=p.split(",")[1];if(!isNaN(q)&&!isNaN(o)){v=[v[0]+parseFloat(q),v[1]+parseFloat(o)]}}w.zoomFunc.translate(v);u="translate("+v+")"}w.phyloTree.set("scaleFactor",r);w.phyloTree.set("translate",v);w.vis.attr("transform",u+s)},reloadViz:function(){var n=this,o=$("#phylovizNexSelector :selected").val();$.getJSON(n.phyloTree.get("dataset").url(),{tree_index:o,data_type:"raw_data"},function(p){n.data=p.data;n.config=p;n.render()})}});var c=Backbone.View.extend({initialize:function(o){var n=this;n.phylovizView=o;$("#panelHeaderRightBtns").empty();$("#phyloVizNavBtns").empty();$("#phylovizNexSelector").off();n.initNavBtns();n.initRightHeaderBtns();$("#phylovizNexSelector").off().on("change",function(){n.phylovizView.reloadViz()})},initRightHeaderBtns:function(){var n=this;rightMenu=create_icon_buttons_menu([{icon_class:"gear",title:"PhyloViz Settings",on_click:function(){$("#SettingsMenu").show();n.settingsMenu.updateUI()}},{icon_class:"disk",title:"Save visualization",on_click:function(){var o=$("#phylovizNexSelector option:selected").text();if(o){n.phylovizView.phyloTree.set("title",o)}n.phylovizView.phyloTree.save()}},{icon_class:"chevron-expand",title:"Search / Edit Nodes",on_click:function(){$("#nodeSelectionView").show()}},{icon_class:"information",title:"Phyloviz Help",on_click:function(){window.open("http://wiki.g2.bx.psu.edu/Learn/Visualization/PhylogeneticTree")}}],{tooltip_config:{placement:"bottom"}});$("#panelHeaderRightBtns").append(rightMenu.$el)},initNavBtns:function(){var n=this,o=create_icon_buttons_menu([{icon_class:"zoom-in",title:"Zoom in",on_click:function(){n.phylovizView.zoomAndPan({zoom:"+"})}},{icon_class:"zoom-out",title:"Zoom out",on_click:function(){n.phylovizView.zoomAndPan({zoom:"-"})}},{icon_class:"arrow-circle",title:"Reset Zoom/Pan",on_click:function(){n.phylovizView.zoomAndPan({zoom:"reset"})}}],{tooltip_config:{placement:"bottom"}});$("#phyloVizNavBtns").append(o.$el)}});var i=l.extend({className:"Settings",initialize:function(o){var n=this;n.phyloTree=o.phyloTree;n.el=$("#SettingsMenu");n.inputs={separation:$("#phyloVizTreeSeparation"),leafHeight:$("#phyloVizTreeLeafHeight"),fontSize:$("#phyloVizTreeFontSize")};$("#settingsCloseBtn").off().on("click",function(){n.el.hide()});$("#phylovizResetSettingsBtn").off().on("click",function(){n.resetToDefaults()});$("#phylovizApplySettingsBtn").off().on("click",function(){n.apply()})},apply:function(){var n=this;if(!n.isAcceptableValue(n.inputs.separation,50,2500)||!n.isAcceptableValue(n.inputs.leafHeight,5,30)||!n.isAcceptableValue(n.inputs.fontSize,5,20)){return}$.each(n.inputs,function(o,p){n.phyloTree.set(o,p.val())})},updateUI:function(){var n=this;$.each(n.inputs,function(o,p){p.val(n.phyloTree.get(o))})},resetToDefaults:function(){$(".bs-tooltip").remove();var n=this;$.each(n.phyloTree.defaults,function(o,p){n.phyloTree.set(o,p)});n.updateUI()},render:function(){}});var e=l.extend({className:"Settings",initialize:function(o){var n=this;n.el=$("#nodeSelectionView");n.phyloTree=o.phyloTree;n.UI={enableEdit:$("#phylovizEditNodesCheck"),saveChanges:$("#phylovizNodeSaveChanges"),cancelChanges:$("#phylovizNodeCancelChanges"),name:$("#phyloVizSelectedNodeName"),dist:$("#phyloVizSelectedNodeDist"),annotation:$("#phyloVizSelectedNodeAnnotation")};n.valuesOfConcern={name:null,dist:null,annotation:null};$("#nodeSelCloseBtn").off().on("click",function(){n.el.hide()});n.UI.saveChanges.off().on("click",function(){n.updateNodes()});n.UI.cancelChanges.off().on("click",function(){n.cancelChanges()});(function(p){p.fn.enable=function(q){return p(this).each(function(){if(q){p(this).removeAttr("disabled")}else{p(this).attr("disabled","disabled")}})}})(jQuery);n.UI.enableEdit.off().on("click",function(){n.toggleUI()})},toggleUI:function(){var n=this,o=n.UI.enableEdit.is(":checked");if(!o){n.cancelChanges()}$.each(n.valuesOfConcern,function(p,q){n.UI[p].enable(o)});if(o){n.UI.saveChanges.show();n.UI.cancelChanges.show()}else{n.UI.saveChanges.hide();n.UI.cancelChanges.hide()}},cancelChanges:function(){var n=this,o=n.phyloTree.get("selectedNode");if(o){$.each(n.valuesOfConcern,function(p,q){n.UI[p].val(o[p])})}},updateNodes:function(){var n=this,o=n.phyloTree.get("selectedNode");if(o){if(!n.isAcceptableValue(n.UI.dist,0,1)||n.hasIllegalJsonCharacters(n.UI.name)||n.hasIllegalJsonCharacters(n.UI.annotation)){return}$.each(n.valuesOfConcern,function(p,q){(o[p])=n.UI[p].val()});n.phyloTree.set("nodeAttrChangedTime",new Date())}else{alert("No node selected")}}});var k=l.extend({initialize:function(){var n=this;$("#phyloVizSearchBtn").on("click",function(){var p=$("#phyloVizSearchTerm"),q=$("#phyloVizSearchCondition").val().split("-"),o=q[0],r=q[1];n.hasIllegalJsonCharacters(p);if(o==="dist"){n.isAcceptableValue(p,0,1)}n.searchTree(o,r,p.val())})},searchTree:function(n,p,o){m.selectAll("g.node").classed("searchHighlight",function(r){var q=r[n];if(typeof q!=="undefined"&&q!==null){if(n==="dist"){switch(p){case"greaterEqual":return q>=+o;case"lesserEqual":return q<=+o;default:return}}else{if(n==="name"||n==="annotation"){return q.toLowerCase().indexOf(o.toLowerCase())!==-1}}}})}});return{PhylovizView:j}});
\ No newline at end of file
+define(["libs/d3","viz/visualization","mvc/data"],function(m,f,g){var l=Backbone.View.extend({className:"UserMenuBase",isAcceptableValue:function(q,o,n){var r=q.val(),s=q.attr("displayLabel")||q.attr("id").replace("phyloViz","");function p(t){return !isNaN(parseFloat(t))&&isFinite(t)}if(!p(r)){alert(s+" is not a number!");return false}if(r>n){alert(s+" is too large.");return false}else{if(r360){return w}else{v=x;return w}};w.separation=function(x){if(typeof x==="undefined"){return s}else{s=x;return w}};w.links=function(x){return m.layout.tree().links(x)};w.nodes=function(A,y){if(toString.call(A)==="[object Array]"){A=A[0]}var z=r.call(w,A,y),x=[],C=0,B=0;window._d=A;window._nodes=z;z.forEach(function(D){C=D.depth>C?D.depth:C;x.push(D)});x.forEach(function(D){if(!D.children){B+=1;D.depth=C}});u=q==="Circular"?v/B:u;t=0;o(x[0],C,u,null);return x};function o(B,D,A,z){var y=B.children,x=0;var C=B.dist||p;C=C>1?1:C;B.dist=C;if(z!==null){B.y0=z.y0+C*s}else{B.y0=n}if(!y){B.x0=t*A;t+=1}else{y.forEach(function(E){E.parent=B;x+=o(E,D,A,B)});B.x0=x/y.length}B.x=B.x0;B.y=B.y0;return B.x0}return w}var b=f.Visualization.extend({defaults:{layout:"Linear",separation:250,leafHeight:18,type:"phyloviz",title:"Title",scaleFactor:1,translate:[0,0],fontSize:12,selectedNode:null,nodeAttrChangedTime:0},initialize:function(n){this.set("dataset",new g.Dataset({id:n.dataset_id}))},root:{},toggle:function(n){if(typeof n==="undefined"){return}if(n.children){n._children=n.children;n.children=null}else{n.children=n._children;n._children=null}},toggleAll:function(n){if(n.children&&n.children.length!==0){n.children.forEach(this.toggleAll);toggle(n)}},getData:function(){return this.root},save:function(){var n=this.root;o(n);this.set("root",n);function o(q){delete q.parent;if(q._selected){delete q._selected}if(q.children){q.children.forEach(o)}if(q._children){q._children.forEach(o)}}var p=jQuery.extend(true,{},this.attributes);p.selectedNode=null;show_message("Saving to Galaxy","progress");return $.ajax({url:this.url(),type:"POST",dataType:"json",data:{vis_json:JSON.stringify(p)},success:function(q){var r=q.url.split("id=")[1].split("&")[0],s="/visualization?id="+r;window.history.pushState({},"",s+window.location.hash);hide_modal()}})}});var d=Backbone.View.extend({defaults:{nodeRadius:4.5},stdInit:function(o){var n=this;n.model.on("change:separation change:leafHeight change:fontSize change:nodeAttrChangedTime",n.updateAndRender,n);n.vis=o.vis;n.i=0;n.maxDepth=-1;n.width=o.width;n.height=o.height},updateAndRender:function(p){var o=m.select(".vis"),n=this;p=p||n.model.root;n.renderNodes(p);n.renderLinks(p);n.addTooltips()},renderLinks:function(n){var w=this;var o=w.diagonal;var p=w.duration;var r=w.layoutMode;var t=w.vis.selectAll("g.completeLink").data(w.tree.links(w.nodes),function(x){return x.target.id});var v=function(x){x.pos0=x.source.y0+" "+x.source.x0;x.pos1=x.source.y0+" "+x.target.x0;x.pos2=x.target.y0+" "+x.target.x0};var u=t.enter().insert("svg:g","g.node").attr("class","completeLink");u.append("svg:path").attr("class","link").attr("d",function(x){v(x);return"M "+x.pos0+" L "+x.pos1});var s=t.transition().duration(500);s.select("path.link").attr("d",function(x){v(x);return"M "+x.pos0+" L "+x.pos1+" L "+x.pos2});var q=t.exit().remove()},selectNode:function(o){var n=this;m.selectAll("g.node").classed("selectedHighlight",function(p){if(o.id===p.id){if(o._selected){delete o._selected;return false}else{o._selected=true;return true}}return false});n.model.set("selectedNode",o);$("#phyloVizSelectedNodeName").val(o.name);$("#phyloVizSelectedNodeDist").val(o.dist);$("#phyloVizSelectedNodeAnnotation").val(o.annotation||"")},addTooltips:function(){$(".bs-tooltip").remove();$(".node").attr("data-original-title",function(){var o=this.__data__,n=o.annotation||"None";return o?(o.name?o.name+" ":"")+"Dist: "+o.dist+" Annotation: "+n:""}).tooltip({placement:"top",trigger:"hover"})}});var a=d.extend({initialize:function(o){var n=this;n.margins=o.margins;n.layoutMode="Linear";n.stdInit(o);n.layout();n.updateAndRender(n.model.root)},layout:function(){var n=this;n.tree=new h().layoutMode("Linear");n.diagonal=m.svg.diagonal().projection(function(o){return[o.y,o.x]})},renderNodes:function(n){var u=this,v=u.model.get("fontSize")+"px";u.tree.separation(u.model.get("separation")).leafHeight(u.model.get("leafHeight"));var q=500,o=u.tree.separation(u.model.get("separation")).nodes(u.model.root);var p=u.vis.selectAll("g.node").data(o,function(w){return w.name+w.id||(w.id=++u.i)});u.nodes=o;u.duration=q;var r=p.enter().append("svg:g").attr("class","node").on("dblclick",function(){m.event.stopPropagation()}).on("click",function(w){if(m.event.altKey){u.selectNode(w)}else{if(w.children&&w.children.length===0){return}u.model.toggle(w);u.updateAndRender(w)}});console.debug("source:",n);if(toString.call(n)==="[object Array]"){n=n[0]}r.attr("transform",function(w){return"translate("+n.y0+","+n.x0+")"});r.append("svg:circle").attr("r",0.000001).style("fill",function(w){return w._children?"lightsteelblue":"#fff"});r.append("svg:text").attr("class","nodeLabel").attr("x",function(w){return w.children||w._children?-10:10}).attr("dy",".35em").attr("text-anchor",function(w){return w.children||w._children?"end":"start"}).style("fill-opacity",0.000001);var s=p.transition().duration(q);s.attr("transform",function(w){return"translate("+w.y+","+w.x+")"});s.select("circle").attr("r",u.defaults.nodeRadius).style("fill",function(w){return w._children?"lightsteelblue":"#fff"});s.select("text").style("fill-opacity",1).style("font-size",v).text(function(w){return w.name});var t=p.exit().transition().duration(q).remove();t.select("circle").attr("r",0.000001);t.select("text").style("fill-opacity",0.000001);o.forEach(function(w){w.x0=w.x;w.y0=w.y})}});var j=Backbone.View.extend({className:"phyloviz",initialize:function(o){var n=this;n.MIN_SCALE=0.05;n.MAX_SCALE=5;n.MAX_DISPLACEMENT=500;n.margins=[10,60,10,80];n.width=$("#PhyloViz").width();n.height=$("#PhyloViz").height();n.radius=n.width;n.data=o.data;$(window).resize(function(){n.width=$("#PhyloViz").width();n.height=$("#PhyloViz").height();n.render()});n.phyloTree=new b(o.config);n.phyloTree.root=n.data;n.zoomFunc=m.behavior.zoom().scaleExtent([n.MIN_SCALE,n.MAX_SCALE]);n.zoomFunc.translate(n.phyloTree.get("translate"));n.zoomFunc.scale(n.phyloTree.get("scaleFactor"));n.navMenu=new c(n);n.settingsMenu=new i({phyloTree:n.phyloTree});n.nodeSelectionView=new e({phyloTree:n.phyloTree});n.search=new k();setTimeout(function(){n.zoomAndPan()},1000)},render:function(){var o=this;$("#PhyloViz").empty();o.mainSVG=m.select("#PhyloViz").append("svg:svg").attr("width",o.width).attr("height",o.height).attr("pointer-events","all").call(o.zoomFunc.on("zoom",function(){o.zoomAndPan()}));o.boundingRect=o.mainSVG.append("svg:rect").attr("class","boundingRect").attr("width",o.width).attr("height",o.height).attr("stroke","black").attr("fill","white");o.vis=o.mainSVG.append("svg:g").attr("class","vis");o.layoutOptions={model:o.phyloTree,width:o.width,height:o.height,vis:o.vis,margins:o.margins};$("#title").text("Phylogenetic Tree from "+o.phyloTree.get("title")+":");var n=new a(o.layoutOptions)},zoomAndPan:function(n){var t,p;if(typeof n!=="undefined"){t=n.zoom;p=n.translate}var w=this,r=w.zoomFunc.scale(),v=w.zoomFunc.translate(),s="",u="";switch(t){case"reset":r=1;v=[0,0];break;case"+":r*=1.1;break;case"-":r*=0.9;break;default:if(typeof t==="number"){r=t}else{if(m.event!==null){r=m.event.scale}}}if(rw.MAX_SCALE){return}w.zoomFunc.scale(r);s="translate("+w.margins[3]+","+w.margins[0]+") scale("+r+")";if(m.event!==null){u="translate("+m.event.translate+")"}else{if(typeof p!=="undefined"){var q=p.split(",")[0];var o=p.split(",")[1];if(!isNaN(q)&&!isNaN(o)){v=[v[0]+parseFloat(q),v[1]+parseFloat(o)]}}w.zoomFunc.translate(v);u="translate("+v+")"}w.phyloTree.set("scaleFactor",r);w.phyloTree.set("translate",v);w.vis.attr("transform",u+s)},reloadViz:function(){var n=this,o=$("#phylovizNexSelector :selected").val();$.getJSON(n.phyloTree.get("dataset").url(),{tree_index:o,data_type:"raw_data"},function(p){n.data=p.data;n.config=p;n.render()})}});var c=Backbone.View.extend({initialize:function(o){var n=this;n.phylovizView=o;$("#panelHeaderRightBtns").empty();$("#phyloVizNavBtns").empty();$("#phylovizNexSelector").off();n.initNavBtns();n.initRightHeaderBtns();$("#phylovizNexSelector").off().on("change",function(){n.phylovizView.reloadViz()})},initRightHeaderBtns:function(){var n=this;rightMenu=create_icon_buttons_menu([{icon_class:"gear",title:"PhyloViz Settings",on_click:function(){$("#SettingsMenu").show();n.settingsMenu.updateUI()}},{icon_class:"disk",title:"Save visualization",on_click:function(){var o=$("#phylovizNexSelector option:selected").text();if(o){n.phylovizView.phyloTree.set("title",o)}n.phylovizView.phyloTree.save()}},{icon_class:"chevron-expand",title:"Search / Edit Nodes",on_click:function(){$("#nodeSelectionView").show()}},{icon_class:"information",title:"Phyloviz Help",on_click:function(){window.open("http://wiki.g2.bx.psu.edu/Learn/Visualization/PhylogeneticTree")}}],{tooltip_config:{placement:"bottom"}});$("#panelHeaderRightBtns").append(rightMenu.$el)},initNavBtns:function(){var n=this,o=create_icon_buttons_menu([{icon_class:"zoom-in",title:"Zoom in",on_click:function(){n.phylovizView.zoomAndPan({zoom:"+"})}},{icon_class:"zoom-out",title:"Zoom out",on_click:function(){n.phylovizView.zoomAndPan({zoom:"-"})}},{icon_class:"arrow-circle",title:"Reset Zoom/Pan",on_click:function(){n.phylovizView.zoomAndPan({zoom:"reset"})}}],{tooltip_config:{placement:"bottom"}});$("#phyloVizNavBtns").append(o.$el)}});var i=l.extend({className:"Settings",initialize:function(o){var n=this;n.phyloTree=o.phyloTree;n.el=$("#SettingsMenu");n.inputs={separation:$("#phyloVizTreeSeparation"),leafHeight:$("#phyloVizTreeLeafHeight"),fontSize:$("#phyloVizTreeFontSize")};$("#settingsCloseBtn").off().on("click",function(){n.el.hide()});$("#phylovizResetSettingsBtn").off().on("click",function(){n.resetToDefaults()});$("#phylovizApplySettingsBtn").off().on("click",function(){n.apply()})},apply:function(){var n=this;if(!n.isAcceptableValue(n.inputs.separation,50,2500)||!n.isAcceptableValue(n.inputs.leafHeight,5,30)||!n.isAcceptableValue(n.inputs.fontSize,5,20)){return}$.each(n.inputs,function(o,p){n.phyloTree.set(o,p.val())})},updateUI:function(){var n=this;$.each(n.inputs,function(o,p){p.val(n.phyloTree.get(o))})},resetToDefaults:function(){$(".bs-tooltip").remove();var n=this;$.each(n.phyloTree.defaults,function(o,p){n.phyloTree.set(o,p)});n.updateUI()},render:function(){}});var e=l.extend({className:"Settings",initialize:function(o){var n=this;n.el=$("#nodeSelectionView");n.phyloTree=o.phyloTree;n.UI={enableEdit:$("#phylovizEditNodesCheck"),saveChanges:$("#phylovizNodeSaveChanges"),cancelChanges:$("#phylovizNodeCancelChanges"),name:$("#phyloVizSelectedNodeName"),dist:$("#phyloVizSelectedNodeDist"),annotation:$("#phyloVizSelectedNodeAnnotation")};n.valuesOfConcern={name:null,dist:null,annotation:null};$("#nodeSelCloseBtn").off().on("click",function(){n.el.hide()});n.UI.saveChanges.off().on("click",function(){n.updateNodes()});n.UI.cancelChanges.off().on("click",function(){n.cancelChanges()});(function(p){p.fn.enable=function(q){return p(this).each(function(){if(q){p(this).removeAttr("disabled")}else{p(this).attr("disabled","disabled")}})}})(jQuery);n.UI.enableEdit.off().on("click",function(){n.toggleUI()})},toggleUI:function(){var n=this,o=n.UI.enableEdit.is(":checked");if(!o){n.cancelChanges()}$.each(n.valuesOfConcern,function(p,q){n.UI[p].enable(o)});if(o){n.UI.saveChanges.show();n.UI.cancelChanges.show()}else{n.UI.saveChanges.hide();n.UI.cancelChanges.hide()}},cancelChanges:function(){var n=this,o=n.phyloTree.get("selectedNode");if(o){$.each(n.valuesOfConcern,function(p,q){n.UI[p].val(o[p])})}},updateNodes:function(){var n=this,o=n.phyloTree.get("selectedNode");if(o){if(!n.isAcceptableValue(n.UI.dist,0,1)||n.hasIllegalJsonCharacters(n.UI.name)||n.hasIllegalJsonCharacters(n.UI.annotation)){return}$.each(n.valuesOfConcern,function(p,q){(o[p])=n.UI[p].val()});n.phyloTree.set("nodeAttrChangedTime",new Date())}else{alert("No node selected")}}});var k=l.extend({initialize:function(){var n=this;$("#phyloVizSearchBtn").on("click",function(){var p=$("#phyloVizSearchTerm"),q=$("#phyloVizSearchCondition").val().split("-"),o=q[0],r=q[1];n.hasIllegalJsonCharacters(p);if(o==="dist"){n.isAcceptableValue(p,0,1)}n.searchTree(o,r,p.val())})},searchTree:function(n,p,o){m.selectAll("g.node").classed("searchHighlight",function(r){var q=r[n];if(typeof q!=="undefined"&&q!==null){if(n==="dist"){switch(p){case"greaterEqual":return q>=+o;case"lesserEqual":return q<=+o;default:return}}else{if(n==="name"||n==="annotation"){return q.toLowerCase().indexOf(o.toLowerCase())!==-1}}}})}});return{PhylovizView:j}});
\ No newline at end of file
diff --git a/static/scripts/viz/phyloviz.js b/static/scripts/viz/phyloviz.js
index 19e9ea61613..d9ea843ff29 100644
--- a/static/scripts/viz/phyloviz.js
+++ b/static/scripts/viz/phyloviz.js
@@ -1,18 +1,18 @@
define(['libs/d3', 'viz/visualization', 'mvc/data'], function(d3, visualization_mod, data_mod) {
+/**
+ * Base class of any menus that takes in user interaction. Contains checking methods.
+ */
var UserMenuBase = Backbone.View.extend({
- /**
- * Base class of any menus that takes in user interaction. Contains checking methods.
- */
className: 'UserMenuBase',
+ /**
+ * Check if an input value is a number and falls within max min.
+ */
isAcceptableValue : function ($inputKey, min, max) {
- /**
- * Check if an input value is a number and falls within max min.
- */
- var self = this,
- value = $inputKey.val(),
+ //TODO: use better feedback than alert
+ var value = $inputKey.val(),
fieldName = $inputKey.attr("displayLabel") || $inputKey.attr("id").replace("phyloViz", "");
function isNumeric(n) {
@@ -34,12 +34,13 @@ var UserMenuBase = Backbone.View.extend({
return true;
},
+ /**
+ * Check if any user string inputs has illegal characters that json cannot accept
+ */
hasIllegalJsonCharacters : function($inputKey) {
- /**
- * Check if any user string inputs has illegal characters that json cannot accept
- */
if ($inputKey.val().search(/"|'|\\/) !== -1){
- alert("Named fields cannot contain these illegal characters: double quote(\"), single guote(\'), or back slash(\\). ");
+ alert("Named fields cannot contain these illegal characters: "
+ + "double quote(\"), single guote(\'), or back slash(\\). ");
return true;
}
return false;
@@ -47,12 +48,12 @@ var UserMenuBase = Backbone.View.extend({
});
+/**
+ * -- Custom Layout call for phyloViz to suit the needs of a phylogenetic tree.
+ * -- Specifically: 1) Nodes have a display display of (= evo dist X depth separation) from their parent
+ * 2) Nodes must appear in other after they have expand and contracted
+ */
function PhyloTreeLayout() {
- /**
- * -- Custom Layout call for phyloViz to suit the needs of a phylogenetic tree.
- * -- Specifically: 1) Nodes have a display display of (= evo dist X depth separation) from their parent
- * 2) Nodes must appear in other after they have expand and contracted
- */
var self = this,
hierarchy = d3.layout.hierarchy().sort(null).value(null),
@@ -75,9 +76,11 @@ function PhyloTreeLayout() {
else { layoutMode = mode; return self;}
};
- self.layoutAngle = function(angle) { // changes the layout angle of the display, which is really changing the height
+ // changes the layout angle of the display, which is really changing the height
+ self.layoutAngle = function(angle) {
if (typeof angle === "undefined"){ return height; }
- if (isNaN(angle) || angle < 0 || angle > 360) { return self; } // to use default if the user puts in strange values
+ // to use default if the user puts in strange values
+ if (isNaN(angle) || angle < 0 || angle > 360) { return self; }
else { height = angle; return self;}
};
@@ -92,19 +95,28 @@ function PhyloTreeLayout() {
// -- Custom method for laying out phylogeny tree in a linear fashion
self.nodes = function (d, i) {
- var _nodes = hierarchy.call(self, d, i), // self is to find the depth of all the nodes, assumes root is passed in
+ //TODO: newick and phyloxml return arrays. where should this go (client (here, else), server)?
+ if( toString.call( d ) === '[object Array]' ){
+ // if d is an array, replate with the first object (newick, phyloxml)
+ d = d[0];
+ }
+ // self is to find the depth of all the nodes, assumes root is passed in
+ var _nodes = hierarchy.call(self, d, i),
nodes = [],
maxDepth = 0,
numLeaves = 0;
+ //console.debug( JSON.stringify( _nodes, null, 2 ) )
+ window._d = d;
+ window._nodes = _nodes;
+ //TODO: remove dbl-touch loop
// changing from hierarchy's custom format for data to usable format
- _nodes.forEach(function (_node){
- var node = _node.data;
- node.depth = _node.depth;
+ _nodes.forEach(function (node){
maxDepth = node.depth > maxDepth ? node.depth : maxDepth; //finding max depth of tree
nodes.push(node);
});
- // counting the number of leaf nodes and assigning max depth to nodes that do not have children to flush all the leave nodes
+ // counting the number of leaf nodes and assigning max depth
+ // to nodes that do not have children to flush all the leave nodes
nodes.forEach(function(node){
if ( !node.children ) { //&& !node._children
numLeaves += 1;
@@ -120,15 +132,16 @@ function PhyloTreeLayout() {
};
+ /**
+ * -- Function with side effect of adding x0, y0 to all child; take in the root as starting point
+ * assuming that the leave nodes would be sorted in presented order
+ * horizontal(y0) is calculated according to (= evo dist X depth separation) from their parent
+ * vertical (x0) - if leave node: find its order in all of the leave node === node.id,
+ * then multiply by verticalSeparation
+ * - if parent node: is place in the mid point all of its children nodes
+ * -- The layout will first calculate the y0 field going towards the leaves, and x0 when returning
+ */
function layout (node, maxDepth, vertSeparation, parent) {
- /**
- * -- Function with side effect of adding x0, y0 to all child; take in the root as starting point
- * assuming that the leave nodes would be sorted in presented order
- * horizontal(y0) is calculated according to (= evo dist X depth separation) from their parent
- * vertical (x0) - if leave node: find its order in all of the leave node === node.id, then multiply by verticalSeparation
- * - if parent node: is place in the mid point all of its children nodes
- * -- The layout will first calculate the y0 field going towards the leaves, and x0 when returning
- */
var children = node.children,
sumChildVertSeparation = 0;
@@ -145,7 +158,8 @@ function PhyloTreeLayout() {
// if a node have no children, we will treat it as a leaf and start laying it out first
if (!children) {
- node.x0 = leafIndex++ * vertSeparation;
+ node.x0 = leafIndex * vertSeparation;
+ leafIndex += 1;
} else {
// if it has children, we will visit all its children and calculate its position from its children
children.forEach( function (child) {
@@ -189,12 +203,12 @@ var PhyloTree = visualization_mod.Visualization.extend({
root : {}, // Root has to be its own independent object because it is not part of the viz_config
+ /**
+ * Mechanism to expand or contract a single node. Expanded nodes have a children list, while for
+ * contracted nodes the list is stored in _children. Nodes with their children data stored in _children will not
+ * have their children rendered.
+ */
toggle : function (d) {
- /**
- * Mechanism to expand or contract a single node. Expanded nodes have a children list, while for
- * contracted nodes the list is stored in _children. Nodes with their children data stored in _children will not have their
- * children rendered.
- */
if(typeof d === "undefined") {return ;}
if (d.children ) {
d._children = d.children;
@@ -205,29 +219,29 @@ var PhyloTree = visualization_mod.Visualization.extend({
}
},
+ /**
+ * Contracts the phylotree to a single node by repeatedly calling itself to place all the list
+ * of children under _children.
+ */
toggleAll : function(d) {
- /**
- * Contracts the phylotree to a single node by repeatedly calling itself to place all the list
- * of children under _children.
- */
if (d.children && d.children.length !== 0) {
d.children.forEach(this.toggleAll);
toggle(d);
}
},
+ /**
+ * Return the data of the tree. Used for preserving state.
+ */
getData : function (){
- /**
- * Return the data of the tree. Used for preserving state.
- */
return this.root;
},
+ /**
+ * Overriding the default save mechanism to do some clean of circular reference of the
+ * phyloTree and to include phyloTree in the saved json
+ */
save: function() {
- /**
- * Overriding the default save mechanism to do some clean of circular reference of the
- * phyloTree and to include phyloTree in the saved json
- */
var root = this.root;
cleanTree(root);
this.set("root", root);
@@ -240,7 +254,7 @@ var PhyloTree = visualization_mod.Visualization.extend({
if (node._selected){ delete node._selected;}
if (node.children) {
- node.children.forEach(cleanTree);
+ node.children.forEach(cleanTree);
}
if (node._children) {
node._children.forEach(cleanTree);
@@ -270,26 +284,24 @@ var PhyloTree = visualization_mod.Visualization.extend({
});
-
+// -- Views --
/**
- * -- Views --
+ * Stores the default variable for setting up the visualization
*/
var PhylovizLayoutBase = Backbone.View.extend({
- /**
- * Stores the default variable for setting up the visualization
- */
defaults : {
nodeRadius : 4.5 // radius of each node in the diagram
},
+ /**
+ * Common initialization in layouts
+ */
stdInit : function (options) {
- /**
- * Common initialization in layouts
- */
var self = this;
- self.model.on("change:separation change:leafHeight change:fontSize change:nodeAttrChangedTime", self.updateAndRender, self);
+ self.model.on("change:separation change:leafHeight change:fontSize change:nodeAttrChangedTime",
+ self.updateAndRender, self);
self.vis = options.vis;
self.i = 0;
@@ -300,11 +312,11 @@ var PhylovizLayoutBase = Backbone.View.extend({
},
+ /**
+ * Updates the visualization whenever there are changes in the expansion and contraction of nodes
+ * AND possibly when the tree is edited.
+ */
updateAndRender : function(source) {
- /**
- * Updates the visualization whenever there are changes in the expansion and contraction of nodes
- * AND possibly when the tree is edited.
- */
var vis = d3.select(".vis"),
self = this;
source = source || self.model.root;
@@ -315,10 +327,10 @@ var PhylovizLayoutBase = Backbone.View.extend({
},
+ /**
+ * Renders the links for the visualization.
+ */
renderLinks : function(source) {
- /**
- * Renders the links for the visualization.
- */
var self = this;
var diagonal = self.diagonal;
var duration = self.duration;
@@ -327,15 +339,17 @@ var PhylovizLayoutBase = Backbone.View.extend({
.data(self.tree.links(self.nodes), function(d) { return d.target.id; });
var calcalateLinePos = function(d) {
- d.pos0 = d.source.y0 + " " + d.source.x0; // position of the source node <=> starting location of the line drawn
- d.pos1 = d.source.y0 + " " + d.target.x0; // position where the line makes a right angle bend
- d.pos2 = d.target.y0 + " " + d.target.x0; // point where the horizontal line becomes a dotted line
+ // position of the source node <=> starting location of the line drawn
+ d.pos0 = d.source.y0 + " " + d.source.x0;
+ // position where the line makes a right angle bend
+ d.pos1 = d.source.y0 + " " + d.target.x0;
+ // point where the horizontal line becomes a dotted line
+ d.pos2 = d.target.y0 + " " + d.target.x0;
};
var linkEnter = link.enter().insert("svg:g","g.node")
.attr("class", "completeLink");
-
linkEnter.append("svg:path")
.attr("class", "link")
.attr("d", function(d) {
@@ -357,10 +371,10 @@ var PhylovizLayoutBase = Backbone.View.extend({
// User Interaction methods below
+ /**
+ * Displays the information for editing
+ */
selectNode : function(node){
- /**
- * Displays the information for editting
- */
var self = this;
d3.selectAll("g.node")
.classed("selectedHighlight", function(d){
@@ -382,11 +396,11 @@ var PhylovizLayoutBase = Backbone.View.extend({
$("#phyloVizSelectedNodeAnnotation").val(node.annotation || "");
},
+ /**
+ * Creates bootstrap tooltip for the visualization. Has to be called repeatedly due to newly generated
+ * enterNodes
+ */
addTooltips : function (){
- /**
- * Creates bootstrap tooltip for the visualization. Has to be called repeatedly due to newly generated
- * enterNodes
- */
$(".bs-tooltip").remove(); //clean up tooltip, just in case its listeners are removed by d3
$(".node")
.attr("data-original-title", function(){
@@ -400,13 +414,11 @@ var PhylovizLayoutBase = Backbone.View.extend({
});
-
-
+/**
+ * Linea layout class of Phyloviz, is responsible for rendering the nodes
+ * calls PhyloTreeLayout to determine the positions of the nodes
+ */
var PhylovizLinearView = PhylovizLayoutBase.extend({
- /**
- * Linea layout class of Phyloviz, is responsible for rendering the nodes
- * calls PhyloTreeLayout to determine the positions of the nodes
- */
initialize : function(options){
// Default values of linear layout
var self = this;
@@ -419,23 +431,21 @@ var PhylovizLinearView = PhylovizLayoutBase.extend({
self.updateAndRender(self.model.root);
},
+ /**
+ * Creates the basic layout of a linear tree by precalculating fixed values.
+ * One of calculations are also made here
+ */
layout : function() {
- /**
- * Creates the basic layout of a linear tree by precalculating fixed values.
- * One of calculations are also made here
- */
-
var self = this;
-
self.tree = new PhyloTreeLayout().layoutMode("Linear");
self.diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x ]; });
},
+ /**
+ * Renders the nodes base on Linear layout.
+ */
renderNodes : function (source) {
- /**
- * Renders the nodes base on Linear layout.
- */
var self = this,
fontSize = self.model.get("fontSize") + "px";
@@ -446,7 +456,9 @@ var PhylovizLinearView = PhylovizLayoutBase.extend({
nodes = self.tree.separation(self.model.get("separation")).nodes(self.model.root);
var node = self.vis.selectAll("g.node")
- .data(nodes, function(d) { return d.name + d.id || (d.id = ++self.i); });
+ .data(nodes, function(d) {
+ return d.name + d.id || (d.id = ++self.i);
+ });
// These variables has to be passed into update links which are in the base methods
self.nodes = nodes;
@@ -466,7 +478,12 @@ var PhylovizLinearView = PhylovizLayoutBase.extend({
self.updateAndRender(d); // re-render the tree
}
});
-
+ console.debug( 'source:', source )
+ //TODO: newick and phyloxml return arrays. where should this go (client (here, else), server)?
+ if( toString.call( source ) === '[object Array]' ){
+ // if d is an array, replate with the first object (newick, phyloxml)
+ source = source[0];
+ }
nodeEnter.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; });
nodeEnter.append("svg:circle")
@@ -557,8 +574,8 @@ var PhylovizView = Backbone.View.extend({
self.nodeSelectionView = new NodeSelectionView({phyloTree : self.phyloTree});
self.search = new PhyloVizSearch();
-
- setTimeout(function(){ // using settimeout to call the zoomAndPan function according to the stored attributes in viz_config
+ // using settimeout to call the zoomAndPan function according to the stored attributes in viz_config
+ setTimeout(function(){
self.zoomAndPan();
}, 1000);
},
@@ -603,11 +620,11 @@ var PhylovizView = Backbone.View.extend({
var linearView = new PhylovizLinearView(self.layoutOptions);
},
+ /**
+ * Function to zoom and pan the svg element which the entire tree is contained within
+ * Uses d3.zoom events, and extend them to allow manual updates and keeping states in model
+ */
zoomAndPan : function(event){
- /**
- * Function to zoom and pan the svg element which the entire tree is contained within
- * Uses d3.zoom events, and extend them to allow manual updates and keeping states in model
- */
var zoomParams,
translateParams;
if (typeof event !== "undefined") {
@@ -659,21 +676,26 @@ var PhylovizView = Backbone.View.extend({
self.phyloTree.set("scaleFactor", scaleFactor);
self.phyloTree.set("translate", translationCoor);
- self.vis.attr("transform", translateStatement + zoomStatement); //refers to the view that we are actually zooming
+ //refers to the view that we are actually zooming
+ self.vis.attr("transform", translateStatement + zoomStatement);
},
+ /**
+ * Primes the Ajax URL to load another Nexus tree
+ */
reloadViz : function() {
- /**
- * Primes the Ajax URL to load another Nexus tree
- */
var self = this,
treeIndex = $("#phylovizNexSelector :selected").val();
- $.getJSON(self.phyloTree.get("dataset").url(), { tree_index: treeIndex, data_type: 'raw_data' }, function(packedJson){
- self.data = packedJson.data;
- self.config = packedJson;
- self.render();
- });
+ $.getJSON(self.phyloTree.get("dataset").url(), {
+ tree_index: treeIndex,
+ data_type: 'raw_data'
+ },
+ function(packedJson){
+ self.data = packedJson.data;
+ self.config = packedJson;
+ self.render();
+ });
}
});
@@ -768,10 +790,10 @@ var SettingsMenu = UserMenuBase.extend({
$("#phylovizApplySettingsBtn").off().on("click", function() { self.apply(); });
},
+ /**
+ * Applying user values to phylotree model.
+ */
apply : function(){
- /**
- * Applying user values to phylotree model.
- */
var self = this;
if (!self.isAcceptableValue(self.inputs.separation, 50, 2500) ||
!self.isAcceptableValue(self.inputs.leafHeight, 5, 30) ||
@@ -782,19 +804,19 @@ var SettingsMenu = UserMenuBase.extend({
self.phyloTree.set(key, $input.val());
});
},
+ /**
+ * Called to update the values input to that stored in the model
+ */
updateUI : function(){
- /**
- * Called to update the values input to that stored in the model
- */
var self = this;
$.each(self.inputs, function(key, $input){
$input.val(self.phyloTree.get(key));
});
},
+ /**
+ * Resets the value of the phyloTree model to its default
+ */
resetToDefaults : function(){
- /**
- * Resets the value of the phyloTree model to its default
- */
$(".bs-tooltip").remove(); // just in case the tool tip was not removed
var self = this;
$.each(self.phyloTree.defaults, function(key, value) {
@@ -810,10 +832,11 @@ var SettingsMenu = UserMenuBase.extend({
});
+/**
+ * View for inspecting node properties and editing them
+ */
var NodeSelectionView = UserMenuBase.extend({
- /**
- * View for inspecting node properties and editing them
- */
+
className: 'Settings',
initialize : function (options){
@@ -830,11 +853,12 @@ var NodeSelectionView = UserMenuBase.extend({
annotation : $("#phyloVizSelectedNodeAnnotation")
};
+ // temporarily stores the values in case user change their mind
self.valuesOfConcern = {
name : null,
dist : null,
annotation : null
- }; // temporarily stores the values in case user change their mind
+ };
//init UI buttons
$("#nodeSelCloseBtn").off().on("click", function() { self.el.hide(); });
@@ -859,10 +883,10 @@ var NodeSelectionView = UserMenuBase.extend({
});
},
+ /**
+ * For turning on and off the child elements
+ */
toggleUI : function(){
- /**
- * For turning on and off the child elements
- */
var self = this,
checked = self.UI.enableEdit.is(':checked');
@@ -881,10 +905,10 @@ var NodeSelectionView = UserMenuBase.extend({
},
+ /**
+ * Reverting to previous values in case user change their minds
+ */
cancelChanges : function() {
- /**
- * Reverting to previous values in case user change their minds
- */
var self = this,
node = self.phyloTree.get("selectedNode");
if (node){
@@ -894,10 +918,10 @@ var NodeSelectionView = UserMenuBase.extend({
}
},
+ /**
+ * Changing the data in the underlying tree with user-specified values
+ */
updateNodes : function (){
- /**
- * Changing the data in the underlying tree with user-specified values
- */
var self = this,
node = self.phyloTree.get("selectedNode");
if (node){
@@ -914,17 +938,15 @@ var NodeSelectionView = UserMenuBase.extend({
alert("No node selected");
}
}
-
-
});
+/**
+ * Initializes the search panel on phyloviz and handles its user interaction
+ * It allows user to search the entire free based on some qualifer, like dist <= val.
+ */
var PhyloVizSearch = UserMenuBase.extend({
- /**
- * Initializes the search panel on phyloviz and handles its user interaction
- * It allows user to search the entire free based on some qualifer, like dist <= val.
- */
initialize : function () {
var self = this;
@@ -942,10 +964,10 @@ var PhyloVizSearch = UserMenuBase.extend({
});
},
+ /**
+ * Searches the entire tree and will highlight the nodes that match the condition in green
+ */
searchTree : function (attr, condition, val){
- /**
- * Searches the entire tree and will highlight the nodes that match the condition in green
- */
d3.selectAll("g.node")
.classed("searchHighlight", function(d){
var attrVal = d[attr];
@@ -972,4 +994,4 @@ return {
PhylovizView: PhylovizView
};
-});
\ No newline at end of file
+});
diff --git a/templates/webapps/galaxy/visualization/phyloviz.mako b/templates/webapps/galaxy/visualization/phyloviz.mako
index c4defff7b03..7a8f8d7d62a 100644
--- a/templates/webapps/galaxy/visualization/phyloviz.mako
+++ b/templates/webapps/galaxy/visualization/phyloviz.mako
@@ -81,7 +81,7 @@
position: fixed;
## Borrowed from galaxy modal_dialogues
- background-color: white;
+ background-color: white;
border: 1px solid #999;
border: 1px solid rgba(0, 0, 0, 0.3);
-webkit-border-radius: 6px;
@@ -157,9 +157,9 @@
// -- Initialization code |-->
phyloviz = new phyloviz_mod.PhylovizView({
- data: data,
- layout : "Linear",
- config : config
+ data : data,
+ layout : "Linear",
+ config : config
});
// -- Render viz. --
@@ -169,7 +169,9 @@
$(function firstVizLoad(){ // calls when viz is loaded for the first time
var config = JSON.parse( '${ h.to_json_string( config )}');
+ window.config = config;
var data = JSON.parse('${h.to_json_string(data)}');
+ window.data = data;
initPhyloViz(data, config);
});
});
@@ -189,7 +191,6 @@
-
%if config["ext"] == "nex" and not config["saved_visualization"]:
@@ -208,10 +209,7 @@
4. Minimap: Currently displays an exact but scaled down replicate of the tree, orange bounding box is correct for linear only
Can be switched on or off
5. Changing Layouts: Able to change between circular and linear layouts.