kayasa
kayasa

Reputation: 2085

Replace svg element

I am rendering a collapsible tree using D3.

(function () {

    Ext.define("d3.widgets.Treeview", {
        extend: 'Ext.Panel',
        alias: 'widget.d3_treeview',
        tree: '',
        svg: '',
        duration: 1000,
        diagonal: '',
        i: 0,
        me: null, 


        constructor: function (config) {
            console.log('1) Tree View Constructor called');
            this.callParent([config]);
            console.log("Treeview - constructor FINISH");
            me = this;
        },

        initComponent: function () {
            console.log('2) Tree View initComponent called');
            this.on('afterRender', function(){
                this.loadScript(this.onD3Loaded, this);
            }, this);
            this.callParent(arguments);
        },

      /*  afterRender: function () {
            console.log('4) Tree View afterRender called');
            this.loadScript(this.onD3Loaded, this);
            return this.callParent(arguments);
        }, */

        loadScript: function (callback, scope) {
            console.log('5) loadScript called');
            Ext.Loader.injectScriptElement('http://d3js.org/d3.v3.js', this.onLoad, this.onError, this);
            console.log('Treeview - D3 script loaded ');

        },

        onError: function () {
            console.log('Treeview On Error');
        },

        onLoad1: function () {
            console.log('Treeview On onLoad1');
        },

        onD3Loaded: function () {
            console.log('Treeview onD3Loaded - D3 script load callback');
        },


        onLoad: function () {

            console.log('Tree View Store --------------------------- ');
           var data = [{ "name": "Orders",     "parent": ""},
              { "name": "Order-No: ON57677",     "parent": "Orders"},
              { "name": "Vehicle-No: VN33255",     "parent": "Order-No: ON57677"},
              { "name": "Make: BMW",     "parent": "Vehicle-No: VN33255"},
              { "name": "Model: Z4",     "parent": "Vehicle-No: VN33255"},
              { "name": "VIN: 52465236",     "parent": "Vehicle-No: VN33255"},
              { "name": "Vehicle-No: VN22345",     "parent": "Order-No: ON57677"},
              { "name": "Make: Chevrolet",     "parent": "Vehicle-No: VN22345"},
              { "name": "Model: SS 454",     "parent": "Vehicle-No: VN22345"},
              { "name": "VIN: 32659852",     "parent": "Vehicle-No: VN22345"},
              { "name": "Vehicle-No: VN11234",     "parent": "Order-No: ON57677"},
              { "name": "Make: Ford",     "parent": "Vehicle-No: VN11234"},
              { "name": "Model: Fiesta",     "parent": "Vehicle-No: VN11234"},
              { "name": "VIN: 45218569",     "parent": "Vehicle-No: VN11234"}];


            var dataMap = data.reduce(function (map, node) {
                map[node.name] = node;
                return map;
            }, {});
            console.log('dataMap --' + dataMap);

            var treeData = [];
            data.forEach(function (node) {
                // add to parent
                var parent = dataMap[node.parent];
                if (parent) {
                    // create child array if it doesn't exist
                    (parent.children || (parent.children = []))
                    // add node to child array
                    .push(node);
                } else {
                    // parent is null or missing
                    treeData.push(node);
                }
            });
            console.log('treeData --' + treeData);
            // ************** Generate the tree diagram  *****************
            var margin = {
                top: 20,
                right: 120,
                bottom: 20,
                left: 120
            },
            width = 960 - margin.right - margin.left,
                height = 500 - margin.top - margin.bottom;

        //    var i = 0;
            i=0;
            // var duration = 1000;
            duration = 1000;
            //	var tree = d3.layout.tree()
            tree = d3.layout.tree()
                .size([height, width]);

            //	var diagonal = d3.svg.diagonal()
            diagonal = d3.svg.diagonal()
                .projection(function (d) {
                return [d.y, d.x];
            });

            d3.select("#treesvg").remove();
            svg = d3.select("#tree").append("svg")
                .attr("width", width + margin.right + margin.left)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
                .attr("id","treesvg");

            root = treeData[0];

            this.update(root);

            d3.select(self.frameElement).style("height", "800px");


        },
        update: function (source) {

            // Compute the new tree layout.
            var nodes = tree.nodes(root).reverse(),
                links = tree.links(nodes);

            // Normalize for fixed-depth.
            nodes.forEach(function (d) {
                d.y = d.depth * 180;
            });

            // Update the nodes…
            var node = svg.selectAll("g.node")
                .data(nodes, function (d) {
                return d.id || (d.id = ++i);
            });

            // 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 + ")";
            })
                .on("click", function (d) {
                if (d.children) {
                    d._children = d.children;
                    d.children = null;
                } else {
                    d.children = d._children;
                    d._children = null;
                }
                me.update(d);
            });

            nodeEnter.append("circle")
                .attr("r", 1e-6)
                .style("fill", function (d) {
                return d._children ? "lightsteelblue" : "#fff";
            });

            nodeEnter.append("text")
                .attr("x", function (d) {
                return d.children || d._children ? -10 : 10;
            })
                .attr("dy", ".35em")
                .attr("text-anchor", function (d) {
                return d.children || d._children ? "end" : "start";
            })
                .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 + ")";
            });

            nodeUpdate.select("circle")
                .attr("r", 4.5)
                .style("fill", function (d) {
                return d._children ? "lightsteelblue" : "#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;
            });

            // 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
                };
                return diagonal({
                    source: o,
                    target: o
                });
            });

            // Transition links to their new position.
            link.transition()
                .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.
        /*	click: function(d) {
	  if (d.children) {
		d._children = d.children;
		d.children = null;
	  } else {
		d.children = d._children;
		d._children = null;
	  }
	  update(d);
	},
*/
        onRender: function (ct, position) {
            console.log('3) onRender called ');
            this.callParent(arguments);
        },


        setValue: function (value) {
            console.log('Set Value called');
            this.callParent(arguments)
        },

        getValue: function () {
            console.log('Get Value called');
            return '';
        },



    });

})();

Ext.create('d3.widgets.Treeview', {
    renderTo : Ext.getBody()
});
.node circle {
    fill: #fff;
    stroke: steelblue;
    stroke-width: 3px;
}
.node text {
    font: 12px sans-serif;
}
.link {
    fill: none;
    stroke: #ccc;
    stroke-width: 2px;
}
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://cdn.sencha.com/ext/gpl/4.2.0/ext-all.js" charset="utf-8"></script>


<body>
    <div id="tree"></div>
</body>

This D3 tree is rendered within an Ext JS application. Based on the Order Number selected by the user, relevant part of the tree is displayed. For example, if 'Order-No: ON31225' is selected then 'Order-No: ON31225' and it's related items are shown.

When user selects an Order for the first time, everything works as expected. There is also one one svg element in the source.

Tree for 1st Order

The goal is that when user clicks on a second order, the diagram is refreshed and displayed with the new order number.

However, right now, it ends up creating another svg element and continues to displays the old diagram.

When 2nd Order is selected

I need a way to remove the old svg element and replace it with the new svg element, so that whenever user selects an OrderNumer, tree for that Order is displayed.

Can someone please help with this?

Thank you

Upvotes: 2

Views: 1522

Answers (1)

musically_ut
musically_ut

Reputation: 34288

Replace this code:

       d3.select("#treesvg").remove();
       svg = d3.select("#tree").append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
            .attr("id","treesvg");

with the following:

       svg = d3.select("#tree").selectAll("svg")
            .data([treedata]);

       svg.enter()
            .append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
            .attr("id","treesvg");

Upvotes: 2

Related Questions