vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
5.8 KiB

  1. var util = require('../../util');
  2. var DOMutil = require('../../DOMutil');
  3. var Component = require('./Component');
  4. /**
  5. * Legend for Graph2d
  6. */
  7. function Legend(body, options, side) {
  8. this.body = body;
  9. this.defaultOptions = {
  10. enabled: true,
  11. icons: true,
  12. iconSize: 20,
  13. iconSpacing: 6,
  14. left: {
  15. visible: true,
  16. position: 'top-left' // top/bottom - left,center,right
  17. },
  18. right: {
  19. visible: true,
  20. position: 'top-left' // top/bottom - left,center,right
  21. }
  22. }
  23. this.side = side;
  24. this.options = util.extend({},this.defaultOptions);
  25. this.svgElements = {};
  26. this.dom = {};
  27. this.groups = {};
  28. this.amountOfGroups = 0;
  29. this._create();
  30. this.setOptions(options);
  31. }
  32. Legend.prototype = new Component();
  33. Legend.prototype.addGroup = function(label, graphOptions) {
  34. if (!this.groups.hasOwnProperty(label)) {
  35. this.groups[label] = graphOptions;
  36. }
  37. this.amountOfGroups += 1;
  38. };
  39. Legend.prototype.updateGroup = function(label, graphOptions) {
  40. this.groups[label] = graphOptions;
  41. };
  42. Legend.prototype.removeGroup = function(label) {
  43. if (this.groups.hasOwnProperty(label)) {
  44. delete this.groups[label];
  45. this.amountOfGroups -= 1;
  46. }
  47. };
  48. Legend.prototype._create = function() {
  49. this.dom.frame = document.createElement('div');
  50. this.dom.frame.className = 'legend';
  51. this.dom.frame.style.position = "absolute";
  52. this.dom.frame.style.top = "10px";
  53. this.dom.frame.style.display = "block";
  54. this.dom.textArea = document.createElement('div');
  55. this.dom.textArea.className = 'legendText';
  56. this.dom.textArea.style.position = "relative";
  57. this.dom.textArea.style.top = "0px";
  58. this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
  59. this.svg.style.position = 'absolute';
  60. this.svg.style.top = 0 +'px';
  61. this.svg.style.width = this.options.iconSize + 5 + 'px';
  62. this.dom.frame.appendChild(this.svg);
  63. this.dom.frame.appendChild(this.dom.textArea);
  64. };
  65. /**
  66. * Hide the component from the DOM
  67. */
  68. Legend.prototype.hide = function() {
  69. // remove the frame containing the items
  70. if (this.dom.frame.parentNode) {
  71. this.dom.frame.parentNode.removeChild(this.dom.frame);
  72. }
  73. };
  74. /**
  75. * Show the component in the DOM (when not already visible).
  76. * @return {Boolean} changed
  77. */
  78. Legend.prototype.show = function() {
  79. // show frame containing the items
  80. if (!this.dom.frame.parentNode) {
  81. this.body.dom.center.appendChild(this.dom.frame);
  82. }
  83. };
  84. Legend.prototype.setOptions = function(options) {
  85. var fields = ['enabled','orientation','icons','left','right'];
  86. util.selectiveDeepExtend(fields, this.options, options);
  87. };
  88. Legend.prototype.redraw = function() {
  89. var activeGroups = 0;
  90. for (var groupId in this.groups) {
  91. if (this.groups.hasOwnProperty(groupId)) {
  92. if (this.groups[groupId].visible == true) {
  93. activeGroups++;
  94. }
  95. }
  96. }
  97. if (this.options[this.side].visible == false || this.amountOfGroups == 0 || this.options.enabled == false || activeGroups == 0) {
  98. this.hide();
  99. }
  100. else {
  101. this.show();
  102. if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'bottom-left') {
  103. this.dom.frame.style.left = '4px';
  104. this.dom.frame.style.textAlign = "left";
  105. this.dom.textArea.style.textAlign = "left";
  106. this.dom.textArea.style.left = (this.options.iconSize + 15) + 'px';
  107. this.dom.textArea.style.right = '';
  108. this.svg.style.left = 0 +'px';
  109. this.svg.style.right = '';
  110. }
  111. else {
  112. this.dom.frame.style.right = '4px';
  113. this.dom.frame.style.textAlign = "right";
  114. this.dom.textArea.style.textAlign = "right";
  115. this.dom.textArea.style.right = (this.options.iconSize + 15) + 'px';
  116. this.dom.textArea.style.left = '';
  117. this.svg.style.right = 0 +'px';
  118. this.svg.style.left = '';
  119. }
  120. if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'top-right') {
  121. this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px';
  122. this.dom.frame.style.bottom = '';
  123. }
  124. else {
  125. this.dom.frame.style.bottom = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px';
  126. this.dom.frame.style.top = '';
  127. }
  128. if (this.options.icons == false) {
  129. this.dom.frame.style.width = this.dom.textArea.offsetWidth + 10 + 'px';
  130. this.dom.textArea.style.right = '';
  131. this.dom.textArea.style.left = '';
  132. this.svg.style.width = '0px';
  133. }
  134. else {
  135. this.dom.frame.style.width = this.options.iconSize + 15 + this.dom.textArea.offsetWidth + 10 + 'px'
  136. this.drawLegendIcons();
  137. }
  138. var content = '';
  139. for (var groupId in this.groups) {
  140. if (this.groups.hasOwnProperty(groupId)) {
  141. if (this.groups[groupId].visible == true) {
  142. content += this.groups[groupId].content + '<br />';
  143. }
  144. }
  145. }
  146. this.dom.textArea.innerHTML = content;
  147. this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px';
  148. }
  149. };
  150. Legend.prototype.drawLegendIcons = function() {
  151. if (this.dom.frame.parentNode) {
  152. DOMutil.prepareElements(this.svgElements);
  153. var padding = window.getComputedStyle(this.dom.frame).paddingTop;
  154. var iconOffset = Number(padding.replace('px',''));
  155. var x = iconOffset;
  156. var iconWidth = this.options.iconSize;
  157. var iconHeight = 0.75 * this.options.iconSize;
  158. var y = iconOffset + 0.5 * iconHeight + 3;
  159. this.svg.style.width = iconWidth + 5 + iconOffset + 'px';
  160. for (var groupId in this.groups) {
  161. if (this.groups.hasOwnProperty(groupId)) {
  162. if (this.groups[groupId].visible == true) {
  163. this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight);
  164. y += iconHeight + this.options.iconSpacing;
  165. }
  166. }
  167. }
  168. DOMutil.cleanupElements(this.svgElements);
  169. }
  170. };
  171. module.exports = Legend;