Legend.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.charting.widget.Legend"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.charting.widget.Legend"] = true;
  8. dojo.provide("dojox.charting.widget.Legend");
  9. dojo.require("dijit._Widget");
  10. dojo.require("dijit._Templated");
  11. dojo.require("dojox.lang.functional.array");
  12. dojo.require("dojox.lang.functional.fold");
  13. var REVERSED_SERIES = /\.(StackedColumns|StackedAreas|ClusteredBars)$/;
  14. dojo.declare("dojox.charting.widget.Legend", [dijit._Widget, dijit._Templated], {
  15. // summary: A legend for a chart. A legend contains summary labels for
  16. // each series of data contained in the chart.
  17. //
  18. // Set the horizontal attribute to boolean false to layout legend labels vertically.
  19. // Set the horizontal attribute to a number to layout legend labels in horizontal
  20. // rows each containing that number of labels (except possibly the last row).
  21. //
  22. // (Line or Scatter charts (colored lines with shape symbols) )
  23. // -o- Series1 -X- Series2 -v- Series3
  24. //
  25. // (Area/Bar/Pie charts (letters represent colors))
  26. // [a] Series1 [b] Series2 [c] Series3
  27. chartRef: "",
  28. horizontal: true,
  29. swatchSize: 18,
  30. templateString: "<table dojoAttachPoint='legendNode' class='dojoxLegendNode' role='group' aria-label='chart legend'><tbody dojoAttachPoint='legendBody'></tbody></table>",
  31. legendNode: null,
  32. legendBody: null,
  33. postCreate: function(){
  34. if(!this.chart){
  35. if(!this.chartRef){ return; }
  36. this.chart = dijit.byId(this.chartRef);
  37. if(!this.chart){
  38. var node = dojo.byId(this.chartRef);
  39. if(node){
  40. this.chart = dijit.byNode(node);
  41. }else{
  42. console.log("Could not find chart instance with id: " + this.chartRef);
  43. return;
  44. }
  45. }
  46. this.series = this.chart.chart.series;
  47. }else{
  48. this.series = this.chart.series;
  49. }
  50. this.refresh();
  51. },
  52. refresh: function(){
  53. // summary: regenerates the legend to reflect changes to the chart
  54. var df = dojox.lang.functional;
  55. // cleanup
  56. if(this._surfaces){
  57. dojo.forEach(this._surfaces, function(surface){
  58. surface.destroy();
  59. });
  60. }
  61. this._surfaces = [];
  62. while(this.legendBody.lastChild){
  63. dojo.destroy(this.legendBody.lastChild);
  64. }
  65. if(this.horizontal){
  66. dojo.addClass(this.legendNode, "dojoxLegendHorizontal");
  67. // make a container <tr>
  68. this._tr = dojo.create("tr", null, this.legendBody);
  69. this._inrow = 0;
  70. }
  71. var s = this.series;
  72. if(s.length == 0){
  73. return;
  74. }
  75. if(s[0].chart.stack[0].declaredClass == "dojox.charting.plot2d.Pie"){
  76. var t = s[0].chart.stack[0];
  77. if(typeof t.run.data[0] == "number"){
  78. var filteredRun = df.map(t.run.data, "Math.max(x, 0)");
  79. if(df.every(filteredRun, "<= 0")){
  80. return;
  81. }
  82. var slices = df.map(filteredRun, "/this", df.foldl(filteredRun, "+", 0));
  83. dojo.forEach(slices, function(x, i){
  84. this._addLabel(t.dyn[i], t._getLabel(x * 100) + "%");
  85. }, this);
  86. }else{
  87. dojo.forEach(t.run.data, function(x, i){
  88. this._addLabel(t.dyn[i], x.legend || x.text || x.y);
  89. }, this);
  90. }
  91. }else{
  92. if(this._isReversal()){
  93. s = s.slice(0).reverse();
  94. }
  95. dojo.forEach(s, function(x){
  96. this._addLabel(x.dyn, x.legend || x.name);
  97. }, this);
  98. }
  99. },
  100. _addLabel: function(dyn, label){
  101. // create necessary elements
  102. var wrapper = dojo.create("td"),
  103. icon = dojo.create("div", null, wrapper),
  104. text = dojo.create("label", null, wrapper),
  105. div = dojo.create("div", {
  106. style: {
  107. "width": this.swatchSize + "px",
  108. "height":this.swatchSize + "px",
  109. "float": "left"
  110. }
  111. }, icon);
  112. dojo.addClass(icon, "dojoxLegendIcon dijitInline");
  113. dojo.addClass(text, "dojoxLegendText");
  114. // create a skeleton
  115. if(this._tr){
  116. // horizontal
  117. this._tr.appendChild(wrapper);
  118. if(++this._inrow === this.horizontal){
  119. // make a fresh container <tr>
  120. this._tr = dojo.create("tr", null, this.legendBody);
  121. this._inrow = 0;
  122. }
  123. }else{
  124. // vertical
  125. var tr = dojo.create("tr", null, this.legendBody);
  126. tr.appendChild(wrapper);
  127. }
  128. // populate the skeleton
  129. this._makeIcon(div, dyn);
  130. text.innerHTML = String(label);
  131. },
  132. _makeIcon: function(div, dyn){
  133. var mb = { h: this.swatchSize, w: this.swatchSize };
  134. var surface = dojox.gfx.createSurface(div, mb.w, mb.h);
  135. this._surfaces.push(surface);
  136. if(dyn.fill){
  137. // regions
  138. surface.createRect({x: 2, y: 2, width: mb.w - 4, height: mb.h - 4}).
  139. setFill(dyn.fill).setStroke(dyn.stroke);
  140. }else if(dyn.stroke || dyn.marker){
  141. // draw line
  142. var line = {x1: 0, y1: mb.h / 2, x2: mb.w, y2: mb.h / 2};
  143. if(dyn.stroke){
  144. surface.createLine(line).setStroke(dyn.stroke);
  145. }
  146. if(dyn.marker){
  147. // draw marker on top
  148. var c = {x: mb.w / 2, y: mb.h / 2};
  149. if(dyn.stroke){
  150. surface.createPath({path: "M" + c.x + " " + c.y + " " + dyn.marker}).
  151. setFill(dyn.stroke.color).setStroke(dyn.stroke);
  152. }else{
  153. surface.createPath({path: "M" + c.x + " " + c.y + " " + dyn.marker}).
  154. setFill(dyn.color).setStroke(dyn.color);
  155. }
  156. }
  157. }else{
  158. // nothing
  159. surface.createRect({x: 2, y: 2, width: mb.w - 4, height: mb.h - 4}).
  160. setStroke("black");
  161. surface.createLine({x1: 2, y1: 2, x2: mb.w - 2, y2: mb.h - 2}).setStroke("black");
  162. surface.createLine({x1: 2, y1: mb.h - 2, x2: mb.w - 2, y2: 2}).setStroke("black");
  163. }
  164. },
  165. _isReversal: function(){
  166. return (!this.horizontal) && dojo.some(this.chart.stack, function(item){
  167. return REVERSED_SERIES.test(item.declaredClass);
  168. });
  169. }
  170. });
  171. }