d3.conceptrelationshiptree_connector.js : updated to handle bi-directional display
D3CTree, ConceptRelationshipPresenterTest, d3ctree_connector.js : testing bi-directional display
import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
import eu.etaxonomy.cdm.vaadin.presenter.ConceptRelationshipPresenter;
import eu.etaxonomy.cdm.vaadin.session.BasicEvent;
import eu.etaxonomy.cdm.vaadin.session.CdmChangeEvent;
}
- private void refreshRelationshipView() {
+ private void refreshRelationshipView(Direction direction) {
if(fromTaxonIun != null) {
try {
- listener.refreshRelationshipView(fromTaxonIun);
+ listener.refreshRelationshipView(fromTaxonIun, direction);
} catch (JSONException e) {
Notification.show("Error generating concept relation JSON", e.getMessage(), Type.WARNING_MESSAGE);
}
public void onSelect(SelectionEvent event) {
if(event.getSourceType().equals(StatusComposite.class)) {
fromTaxonIun = (IdUuidName)event.getSelectedObjects().get(0);
- view.setPrimaryStatusComposite((UUID)event.getSelectedObjects().get(1));
- refreshRelationshipView();
+ view.setPrimaryStatusCompositeUuid((UUID)event.getSelectedObjects().get(1));
+ refreshRelationshipView(view.getDirection());
}
}
public void onCreate(CdmChangeEvent event) {
if(event.getSourceType().equals(EditConceptRelationshipComposite.class)) {
setSelectedTaxonRelUuid(null);
- refreshRelationshipView();
+ refreshRelationshipView(view.getDirection());
}
public void onUpdate(CdmChangeEvent event) {
if(event.getSourceType().equals(EditConceptRelationshipComposite.class)) {
setSelectedTaxonRelUuid(null);
- refreshRelationshipView();
+ refreshRelationshipView(view.getDirection());
}
}
public void onDelete(CdmChangeEvent event) {
if(event.getSourceType().equals(EditConceptRelationshipComposite.class)) {
setSelectedTaxonRelUuid(null);
- refreshRelationshipView();
+ refreshRelationshipView(view.getDirection());
}
}
private Mode mode;
+ public enum Direction {
+ LEFT_RIGHT("left-right"),
+ RIGHT_LEFT("right-left");
+
+ private final String name;
+
+ private Direction(String s) {
+ name = s;
+ }
+
+ @Override
+ public String toString(){
+ return name;
+ }
+ }
+
+ private Direction direction;
+
private ConceptRelationshipComposite conceptRelComposite;
public D3ConceptRelationshipTree() {
- this(Mode.OneToOne);
+ this(Mode.OneToOne, Direction.LEFT_RIGHT);
}
- public D3ConceptRelationshipTree(Mode mode) {
- this.mode = mode;
+ public D3ConceptRelationshipTree(Direction direction) {
+ this(Mode.OneToOne, direction);
+ }
+ public D3ConceptRelationshipTree(Mode mode, Direction direction) {
+ this.mode = mode;
+ this.direction = direction;
addFunction("select", new JavaScriptFunction() {
@Override
}
- public void update(Taxon fromTaxon) throws JSONException {
+ public void update(Taxon fromTaxon, Direction direction) throws JSONException {
+ this.direction = direction;
switch(mode) {
case OneToOne:
updateForOneToOne(fromTaxon);
fromTaxonJO.put("name", fromTaxon.getName().getTitleCache());
fromTaxonJO.put("uuid", fromTaxon.getUuid().toString());
fromTaxonJO.put("type", "taxon");
+ fromTaxonJO.put("direction", direction.toString());
JSONArray ftChildren = new JSONArray();
fromTaxonJO.put("children", ftChildren);
import eu.etaxonomy.cdm.model.taxon.Taxon;
import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
import eu.etaxonomy.cdm.vaadin.util.CdmSpringContextHelper;
import eu.etaxonomy.cdm.vaadin.view.IConceptRelationshipComponentListener;
}
@Override
- public void refreshRelationshipView(IdUuidName taxonIun) throws JSONException {
+ public void refreshRelationshipView(IdUuidName taxonIun, Direction direction) throws JSONException {
TransactionStatus tx = app.startTransaction();
Taxon taxon = CdmBase.deproxy(taxonService.load(taxonIun.getUuid()), Taxon.class);
- crTree.update(taxon);
+ crTree.update(taxon, direction);
app.commitTransaction(tx);
}
import eu.etaxonomy.cdm.vaadin.component.ConceptRelationshipComposite;
import eu.etaxonomy.cdm.vaadin.component.StatusComposite;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
import eu.etaxonomy.cdm.vaadin.session.BasicEvent;
import eu.etaxonomy.cdm.vaadin.session.IBasicEventListener;
import eu.etaxonomy.cdm.vaadin.util.CdmVaadinSessionUtilities;
private StatusComposite statusCompositeLeft;
private StatusComposite primaryStatusComposite, secondaryStatusComposite;
+
+ private Direction direction;
/**
* The constructor should first build the main layout, set the
* composition root and then do any custom initialization.
conceptRelationshipComposite.setView(this);
conceptRelationshipComposite.setSizeFull();
- setPrimaryStatusComposite(statusCompositeLeft.getSelectedClassificationUuid());
-
+ setPrimaryStatusCompositeUuid(statusCompositeLeft.getSelectedClassificationUuid());
+ direction = Direction.LEFT_RIGHT;
CdmVaadinSessionUtilities.getCurrentBasicEventService().register(this);
}
}
- public void setPrimaryStatusComposite(UUID scUuid) {
+ public Direction getDirection() {
+ return direction;
+ }
+
+ public void setPrimaryStatusCompositeUuid(UUID scUuid) {
if(scUuid != null) {
- if(statusCompositeLeft.getSelectedClassificationUuid().equals(scUuid)) {
+ if(scUuid.equals(statusCompositeLeft.getSelectedClassificationUuid())) {
primaryStatusComposite = statusCompositeLeft;
secondaryStatusComposite = statusCompositeRight;
- } else {
+ direction = Direction.LEFT_RIGHT;
+ }
+ if(scUuid.equals(statusCompositeRight.getSelectedClassificationUuid())) {
secondaryStatusComposite = statusCompositeLeft;
primaryStatusComposite = statusCompositeRight;
+ direction = Direction.RIGHT_LEFT;
}
secondaryStatusComposite.clearTaxaTableSelections();
}
import org.json.JSONException;
import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
/**
* @author cmathew
public interface IConceptRelationshipComponentListener {
/**
- * @param taxonUuid
+ * @param taxonIun
+ * @param direction
* @throws JSONException
*/
- public void refreshRelationshipView(IdUuidName taxonUuid) throws JSONException;
+ public void refreshRelationshipView(IdUuidName taxonIun, Direction direction) throws JSONException;
-
+/**
+ * D3 Layout Tree (inspired by http://bl.ocks.org/mbostock/4339083)
+ * which displays a list concept relationships between a 'from' taxon
+ * and a number of 'to' taxon
+ */
window.eu_etaxonomy_cdm_vaadin_jscomponent_D3ConceptRelationshipTree = function() {
var connector = this;
var diagramElement = connector.getElement();
duration = 750,
root;
- var tree = d3.layout.tree()
- .size([height, width]);
-
- var diagonal = d3.svg.diagonal()
- .projection(function(d) { return [d.y, d.x]; });
+ var tree;
+ var diagonal;
var svg = d3.select(diagramElement).append("svg")
.attr("width", width + margin.right + margin.left)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var selectedNode;
+
+ var orientations = {
+ "topbottom": {
+ size: [width, height],
+ x: function(d) { return d.x; },
+ y: function(d) { return d.y; }
+ },
+ "rightleft": {
+ size: [height, width],
+ x: function(d) { return width - d.y; },
+ y: function(d) { return d.x; }
+ },
+ "bottomtop": {
+ size: [width, height],
+ x: function(d) { return d.x; },
+ y: function(d) { return height - d.y; }
+ },
+ "leftright": {
+ size: [height, width],
+ x: function(d) { return d.y; },
+ y: function(d) { return d.x; }
+ }
+ };
+ // default setting is left-right
+ var orientation = orientations.rightleft;
+ var tAnchorWithChildren = "end";
+ var tAnchorWithoutChildren = "start";
+ var dirMult = 1;
this.onStateChange = function() {
crTree = this.getState().conceptRelationshipTree;
if(crTree) {
root = JSON.parse(connector.getState().conceptRelationshipTree);
-
- root.x0 = height / 2;
- root.y0 = 0;
-
- function collapse(d) {
- if (d.children) {
- d._children = d.children;
- d._children.forEach(collapse);
- d.children = null;
- }
+
+ if(root.direction === "left-right") {
+ orientation = orientations.leftright;
+ tAnchorWithChildren = "end";
+ tAnchorWithoutChildren = "start";
+ dirMult = 1;
}
-
- //root.children.forEach(collapse);
+ if(root.direction === "right-left") {
+ orientation = orientations.rightleft;
+ tAnchorWithChildren = "start";
+ tAnchorWithoutChildren = "end";
+ dirMult = -1;
+ }
+
+ diagonal = d3.svg.diagonal().projection(function(d) { return [orientation.x(d), orientation.y(d)]; });
+ tree = d3.layout.tree().size(orientation.size);
update(root);
-
-
d3.select(self.frameElement).style("height", "800px");
- }
+ }
}
+
function update(source) {
// Compute the new tree layout.
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
- .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
+ .attr("transform", function(d) { return "translate(" + orientation.x(source) + "," + orientation.y(source) + ")"; })
.on("click", click);
nodeEnter.append("circle")
.attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
.style("fill", function(d) { return d === source && d.type === "conceptr" ? "#DF7401" : "#fff"; });
-
+
nodeEnter.append("text")
.attr("x", function(d) {
if(d.type === "conceptr") {
- return 50;
+ return dirMult*50;
} else {
- return d.children || d._children ? -10 : 10;
+ return d.children || d._children ? -1*dirMult*10 : dirMult*10;
}
})
.attr("y", function(d) { return d.type === "conceptr" ? -20 : 0; })
.attr("dy", ".35em")
- .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
+ .attr("text-anchor", function(d) { return d.children || d._children ? tAnchorWithChildren : tAnchorWithoutChildren; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
- .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
+ .attr("transform", function(d) { return "translate(" + orientation.x(d) + "," + orientation.y(d) + ")"; });
nodeUpdate.select("circle")
.attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
- .duration(duration)
- .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
- .remove();
+ .duration(duration)
+ .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
+ .remove();
nodeExit.select("circle")
- .attr("r", 1e-6);
+ .attr("r", 1e-6);
nodeExit.select("text")
- .style("fill-opacity", 1e-6);
-
+ .style("fill-opacity", 1e-6);
+
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
+ // Transition exiting nodes to the parent's new position.
+ link.exit().transition()
+ .duration(duration)
+ .attr("d", function(d) {
+ var o = {x: source.x, y: source.y};
+ return diagonal({source: o, target: o});
+ })
+ .remove();
+
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
- var o = {x: source.x0, y: source.y0};
+ var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
});
.duration(duration)
.attr("d", diagonal);
- // Transition exiting nodes to the parent's new position.
- link.exit().transition()
- .duration(duration)
- .attr("d", function(d) {
- var o = {x: source.x, y: source.y};
- return diagonal({source: o, target: o});
- })
- .remove();
-
- // Stash the old positions for transition.
- nodes.forEach(function(d) {
- d.x0 = d.x;
- d.y0 = d.y;
- });
}
private static final Logger logger = Logger.getLogger(D3CTree.class);
public D3CTree() {
- addFunction("test", new JavaScriptFunction() {
+ addFunction("select", new JavaScriptFunction() {
@Override
public void call(JSONArray arguments) throws JSONException {
cr1Children.put(0, taxonTo);
cr2Children.put(0, taxonTo);
- String conceptRelationshipTree = taxonFrom.toString();
-
+ //String conceptRelationshipTree = taxonFrom.toString();
+ String conceptRelationshipTree = "{\"direction\":\"right-left\",\"name\":\"Taxon d\",\"children\":[{\"name\":\"Congruent to\",\"children\":[{\"name\":\"Taxon e\",\"uuid\":\"84e99e24-f50a-4726-92d0-6088430c492a\",\"type\":\"taxon\"}],\"uuid\":\"511f504b-ae3b-4f04-b7b9-35c222f06e10\",\"type\":\"conceptr\"},{\"name\":\"Includes\",\"children\":[{\"name\":\"Taxon a\",\"uuid\":\"eaac797e-cac7-4649-97cf-c7b580076895\",\"type\":\"taxon\"}],\"uuid\":\"0e8b7922-974d-4389-b71e-af6fc9f98c56\",\"type\":\"conceptr\"},{\"name\":\"Includes\",\"children\":[{\"name\":\"Taxon b\",\"uuid\":\"5004a8e7-b907-4744-b67e-44ccb057ab3b\",\"type\":\"taxon\"}],\"uuid\":\"6fd9947e-21c3-4190-8748-57d9661e8659\",\"type\":\"conceptr\"},{\"name\":\"Excludes\",\"children\":[{\"name\":\"Taxon c\",\"uuid\":\"3d71c8b8-3bec-4f5f-ba23-6f9d55ef84e9\",\"type\":\"taxon\"}],\"uuid\":\"cc761030-38d2-4b5d-954d-32329c0ea106\",\"type\":\"conceptr\"}],\"uuid\":\"5f713f69-e03e-4a11-8a55-700fbbf44805\",\"type\":\"taxon\"}";
logger.warn("conceptRelationshipTree : " + conceptRelationshipTree);
setConceptRelationshipTree(conceptRelationshipTree);
import eu.etaxonomy.cdm.vaadin.CdmVaadinBaseTest;
import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
/**
* @author cmathew
@Test
public void testRefreshRelationshipView() throws JSONException {
UUID taxonUuid = UUID.fromString("5f713f69-e03e-4a11-8a55-700fbbf44805");
- crp.refreshRelationshipView(new IdUuidName(30, taxonUuid, null));
+ crp.refreshRelationshipView(new IdUuidName(30, taxonUuid, null), Direction.LEFT_RIGHT);
String expected = "{\"name\":\"Taxon d\",\"children\":[{\"name\":\"Congruent to\",\"children\":[{\"name\":\"Taxon e\",\"uuid\":\"84e99e24-f50a-4726-92d0-6088430c492a\",\"type\":\"taxon\"}],\"uuid\":\"511f504b-ae3b-4f04-b7b9-35c222f06e10\",\"type\":\"conceptr\"},{\"name\":\"Includes\",\"children\":[{\"name\":\"Taxon a\",\"uuid\":\"eaac797e-cac7-4649-97cf-c7b580076895\",\"type\":\"taxon\"}],\"uuid\":\"0e8b7922-974d-4389-b71e-af6fc9f98c56\",\"type\":\"conceptr\"},{\"name\":\"Includes\",\"children\":[{\"name\":\"Taxon b\",\"uuid\":\"5004a8e7-b907-4744-b67e-44ccb057ab3b\",\"type\":\"taxon\"}],\"uuid\":\"6fd9947e-21c3-4190-8748-57d9661e8659\",\"type\":\"conceptr\"},{\"name\":\"Excludes\",\"children\":[{\"name\":\"Taxon c\",\"uuid\":\"3d71c8b8-3bec-4f5f-ba23-6f9d55ef84e9\",\"type\":\"taxon\"}],\"uuid\":\"cc761030-38d2-4b5d-954d-32329c0ea106\",\"type\":\"conceptr\"}],\"uuid\":\"5f713f69-e03e-4a11-8a55-700fbbf44805\",\"type\":\"taxon\"}";
+ logger.warn(crTree.getState().getConceptRelationshipTree());
Assert.assertEquals(expected, crTree.getState().getConceptRelationshipTree());
taxonUuid = UUID.fromString("3d71c8b8-3bec-4f5f-ba23-6f9d55ef84e9");
- crp.refreshRelationshipView(new IdUuidName(20, taxonUuid, null));
+ crp.refreshRelationshipView(new IdUuidName(20, taxonUuid, null), Direction.LEFT_RIGHT);
expected = "{\"name\":\"Taxon c\",\"children\":[],\"uuid\":\"3d71c8b8-3bec-4f5f-ba23-6f9d55ef84e9\",\"type\":\"taxon\"}";
+ logger.warn(crTree.getState().getConceptRelationshipTree());
Assert.assertEquals(expected, crTree.getState().getConceptRelationshipTree());
}
* @date 8 Apr 2015
*
*/
-@Theme("mytheme")
+@Theme("edit")
public class D3CTreeUI extends UI {
private final static Logger logger =
duration = 750,
root;
- var tree = d3.layout.tree()
- .size([height, width]);
-
- var diagonal = d3.svg.diagonal()
- .projection(function(d) { return [d.y, d.x]; });
+ var tree;
+ var diagonal;
var svg = d3.select(diagramElement).append("svg")
.attr("width", width + margin.right + margin.left)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
- //alert(this.getState().conceptRelationshipTree);
- root = JSON.parse(this.getState().conceptRelationshipTree);
-
- root.x0 = height / 2;
- root.y0 = 0;
-
- function collapse(d) {
- if (d.children) {
- d._children = d.children;
- d._children.forEach(collapse);
- d.children = null;
- }
+ var selectedNode;
+
+ var orientations = {
+ "topbottom": {
+ size: [width, height],
+ x: function(d) { return d.x; },
+ y: function(d) { return d.y; }
+ },
+ "rightleft": {
+ size: [height, width],
+ x: function(d) { return width - d.y; },
+ y: function(d) { return d.x; }
+ },
+ "bottomtop": {
+ size: [width, height],
+ x: function(d) { return d.x; },
+ y: function(d) { return height - d.y; }
+ },
+ "leftright": {
+ size: [height, width],
+ x: function(d) { return d.y; },
+ y: function(d) { return d.x; }
+ }
+ };
+ // default setting is left-right
+ var orientation = orientations.rightleft;
+ var tAnchorWithChildren = "end";
+ var tAnchorWithoutChildren = "start";
+ var dirMult = 1;
+ this.onStateChange = function() {
+ crTree = this.getState().conceptRelationshipTree;
+
+ if(crTree) {
+ root = JSON.parse(connector.getState().conceptRelationshipTree);
+
+ if(root.direction === "left-right") {
+ orientation = orientations.leftright;
+ tAnchorWithChildren = "end";
+ tAnchorWithoutChildren = "start";
+ dirMult = 1;
+ }
+ if(root.direction === "right-left") {
+ orientation = orientations.rightleft;
+ tAnchorWithChildren = "start";
+ tAnchorWithoutChildren = "end";
+ dirMult = -1;
+ }
+
+ diagonal = d3.svg.diagonal().projection(function(d) { return [orientation.x(d), orientation.y(d)]; });
+ tree = d3.layout.tree().size(orientation.size);
+
+
+ update(root);
+ d3.select(self.frameElement).style("height", "800px");
+ }
}
- root.children.forEach(collapse);
- update(root);
-
-
- d3.select(self.frameElement).style("height", "800px");
-
+
function update(source) {
// Compute the new tree layout.
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
- .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
+ .attr("transform", function(d) { return "translate(" + orientation.x(source) + "," + orientation.y(source) + ")"; })
.on("click", click);
nodeEnter.append("circle")
- .attr("r", 10)
- .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
-
+ .attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
+ .style("fill", function(d) { return d === source && d.type === "conceptr" ? "#DF7401" : "#fff"; });
+
nodeEnter.append("text")
- .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
- .attr("y", "-10")
+ .attr("x", function(d) {
+ if(d.type === "conceptr") {
+ return dirMult*50;
+ } else {
+ return d.children || d._children ? -1*dirMult*10 : dirMult*10;
+ }
+ })
+ .attr("y", function(d) { return d.type === "conceptr" ? -20 : 0; })
.attr("dy", ".35em")
- .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
+ .attr("text-anchor", function(d) { return d.children || d._children ? tAnchorWithChildren : tAnchorWithoutChildren; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
- .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
+ .attr("transform", function(d) { return "translate(" + orientation.x(d) + "," + orientation.y(d) + ")"; });
nodeUpdate.select("circle")
- .attr("r", 10)
- .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
+ .attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
+ .style("fill", function(d) { return d === selectedNode && d.type === "conceptr" ? "#DF7401" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1);
- // Transition exiting nodes to the parent's new position.
- var nodeExit = node.exit().transition()
- .duration(duration)
- .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
- .remove();
-
- nodeExit.select("circle")
- .attr("r", 1e-6);
-
- nodeExit.select("text")
- .style("fill-opacity", 1e-6);
-
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
- var o = {x: source.x0, y: source.y0};
+ var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
});
.duration(duration)
.attr("d", diagonal);
- // Transition exiting nodes to the parent's new position.
- link.exit().transition()
- .duration(duration)
- .attr("d", function(d) {
- var o = {x: source.x, y: source.y};
- return diagonal({source: o, target: o});
- })
- .remove();
-
- // Stash the old positions for transition.
- nodes.forEach(function(d) {
- d.x0 = d.x;
- d.y0 = d.y;
- });
}
// Toggle children on click.
function click(d) {
- root.children.forEach(collapse);
- connector.test(d.name);
- if (d.children) {
- d._children = d.children;
- d.children = null;
- } else {
- d.children = d._children;
- d._children = null;
+ //root.children.forEach(collapse);
+
+ if(d.type === "conceptr") {
+ connector.select(d.uuid);
}
+
+ selectedNode = d;
update(d);
}
}
\ No newline at end of file