views:

921

answers:

3

I have the following codes to create chart graphics by dojox.charting:

function createChart() {
  var node = dojo.byId("surfaceDiv");
  while (node.hasChildNodes())
  {
    node.removeChild(node.lastChild); // remove all the children graphics
  }
  var nodes =  "<div id='chart1' style='width: 10px; height: 10px;'></div><div id='legend1' ></div>";
  dojo.html.set(node, nodes);
  var nodeChart = dojo.byId("chart1");
  var nodeLegend = dojo.byId("legend1");

  var chart1 = new dojox.charting.Chart2D(nodeChart);
  // set chart types and point series
  chart1.render();
  // now to add legend:
  var legendNode = new dojox.charting.widget.Legent(
     {chart: chart1}, nodeLegend.id));
}

The function works fine for the first call; however, if it is called again, the chart is displayed OK, but the legend is not displayed. In firebug, I noticed there is an error saying "Tried to register widget with id==legend1 but that id is already registered" in manager.xd.js (line 8). It looks like that somewhere in dojox's library cached the previous legend object with the same id.

I guess I have to clean any legend previously registered or cached. How can I do that?

By the way, in my html page, I have several ancor links to call JavaScript functions to draw different graphics in a div node with id="surfaceDiv", and the legend node" is the next div with id="legendDiv". Therefore, the above function can be called again.

A: 

I think that is a bug in dojox.charting.widget.Legend(...). What I did was to clean all the graphics and legend dom elements under div "surfaceDiv", and add new div "chart1" for chart and div "legend1" as legend. The chart works OK but not legend. I have the following anchor link call to the function in my html:

....
<a href="javascript:createChart();">Curve chart</a>
....

As a result, the function createChart() can be called more than once within the same web page session. The first time the chart and legend were displayed but the legend was missing in the subsequent calls or clicks.

To work around the problem or bug, I have to set legend ID dynamically with different values. Any cached legend id value within dojox.charting.widget.Legend(...) will not be conflict with new ids. Here is the codes:

var legendCount = 0; // global value 

function createChart() {
  var node = dojo.byId("surfaceDiv");
  while (node.hasChildNodes())
  {
    node.removeChild(node.lastChild); // remove all the children graphics
  }
  var legendID = "legend" + legendCount++;
  var nodes =  "<div id='chart1' style='width: 10px; height: 10px;'></div>" +
    "<div id='" + legendID + "' ></div>"; // Set legend ID dynamically
  dojo.html.set(node, nodes);
  var nodeChart = dojo.byId("chart1");
  var nodeLegend = dojo.byId(legendID);

  var chart1 = new dojox.charting.Chart2D(nodeChart);
  // set chart types and point series
  chart1.render();
  // now to add legend:
  var legendNode = new dojox.charting.widget.Legent(
    {chart: chart1}, nodeLegend.id)); // no more conflict legend's ID
}

I tested my codes and html page again. Legend is displayed every time!

David.Chu.ca
A: 

The method I posted above is not a good way to resolve the issue. It is confirmed by a dojox's insider that it is a bug in dojox.charting based on my finding case. He does not recommend my way, removing HTML elements which I think for the chart and legend, as a solution.

I think his suggestion is right. The chart and legend are created by dojox.charting APIs. My case of html page may not reveal all the DOM objects to be removed just for the clean up. Some DOM objects in cache may be left uncleaned behind sense. For example, in JS codes, I added two divs under an empty div: one for chart and one for legend. dojox.charting APIs add svg nodes under the chart div and converted legend div to a table. In addition to that, several invisible divs are created outside my initial empty div. This cleaning up method would left some mess or cause unpredictable problems. Further more, my method may be broken in the future of new or updated dojox.charting APIs (fixing bugs as example).

Since I am new to dojox.charting (just started to write some testing codes by its APIs in the last week based on an article), I am not sure if dojox.charting provides any way to clean up charts and legends? I think that would be best way or APIs to do it if available.

Even my above solution works fine for my base, deleting all the chidlren nodesunder an empty div, you should be aware the potential problems.

All the demo codes, I can find out so far, are example codes to create or add new charts to a web page. There is no one, as far as I can tell, for updating, manipulating or simply refreshing charts. If the data series are coming from web services or REST, it would be a need just to update an area of charts. Here is an example of HTML page UP layout:

 Curve chart                 -----------------------
 Pie chart                   |  div area for chart |
 Bar chart                   |                     |
 Refresh chart with changes  |                     |
                             -----------------------

With options available to create chart in one div area, I think I do have a need to clean up the div if there is any chart generated previously.

By looking at the codes how a chart and a legend are created by dojox.charting APIs:

 // nodeDivForChart and NodeDivForLegend are div nodes
 var chart1  = new dojox.charting.Chart2D(nodeDivForChart);
 ....
 var legend1 = new dojox.charting.widget.Legend(
   {chart: chart1}, nodeDivForLegend.id);

My guess is that chart1 and legend1 are DOM instances or objects? Not sure if there is any way to destroy those instances as a way to clean up chart and legend? How?

David.Chu.ca
A: 

I'm using dojox 1.3.0 and found the following works fine for me (legend is a global var) without any errors:

if (legend != undefined) {
  legend.destroyRecursive(true); 
} 

legend = new dojox.charting.widget.Legend({chart: chart1,horizontal: true}, 'legend');

//or try this
var myObj = new dojoObject(...);
...
// do whatever we want with it
...
// now we don't need it and we want to dispose of it
myObj.destroy();
delete myObj;

In this case, the legend is destroyed before it's recreated.

Here is another link on this subject: http://www.dojotoolkit.org/forum/dojox-dojox/dojox-support/how-unregister-legend-dojox-charting

GoinOff