Legend.js 5.9 KB

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