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.

214 lines
6.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, linegraphOptions) {
  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.linegraphOptions = linegraphOptions;
  26. this.svgElements = {};
  27. this.dom = {};
  28. this.groups = {};
  29. this.amountOfGroups = 0;
  30. this._create();
  31. this.setOptions(options);
  32. }
  33. Legend.prototype = new Component();
  34. Legend.prototype.clear = function() {
  35. this.groups = {};
  36. this.amountOfGroups = 0;
  37. };
  38. Legend.prototype.addGroup = function(label, graphOptions) {
  39. // Include a group only if the group option 'excludeFromLegend: false' is not set.
  40. if (graphOptions.options.excludeFromLegend != true) {
  41. if (!this.groups.hasOwnProperty(label)) {
  42. this.groups[label] = graphOptions;
  43. }
  44. this.amountOfGroups += 1;
  45. }
  46. };
  47. Legend.prototype.updateGroup = function(label, graphOptions) {
  48. this.groups[label] = graphOptions;
  49. };
  50. Legend.prototype.removeGroup = function(label) {
  51. if (this.groups.hasOwnProperty(label)) {
  52. delete this.groups[label];
  53. this.amountOfGroups -= 1;
  54. }
  55. };
  56. Legend.prototype._create = function() {
  57. this.dom.frame = document.createElement('div');
  58. this.dom.frame.className = 'vis-legend';
  59. this.dom.frame.style.position = "absolute";
  60. this.dom.frame.style.top = "10px";
  61. this.dom.frame.style.display = "block";
  62. this.dom.textArea = document.createElement('div');
  63. this.dom.textArea.className = 'vis-legend-text';
  64. this.dom.textArea.style.position = "relative";
  65. this.dom.textArea.style.top = "0px";
  66. this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
  67. this.svg.style.position = 'absolute';
  68. this.svg.style.top = 0 +'px';
  69. this.svg.style.width = this.options.iconSize + 5 + 'px';
  70. this.svg.style.height = '100%';
  71. this.dom.frame.appendChild(this.svg);
  72. this.dom.frame.appendChild(this.dom.textArea);
  73. };
  74. /**
  75. * Hide the component from the DOM
  76. */
  77. Legend.prototype.hide = function() {
  78. // remove the frame containing the items
  79. if (this.dom.frame.parentNode) {
  80. this.dom.frame.parentNode.removeChild(this.dom.frame);
  81. }
  82. };
  83. /**
  84. * Show the component in the DOM (when not already visible).
  85. * @return {Boolean} changed
  86. */
  87. Legend.prototype.show = function() {
  88. // show frame containing the items
  89. if (!this.dom.frame.parentNode) {
  90. this.body.dom.center.appendChild(this.dom.frame);
  91. }
  92. };
  93. Legend.prototype.setOptions = function(options) {
  94. var fields = ['enabled','orientation','icons','left','right'];
  95. util.selectiveDeepExtend(fields, this.options, options);
  96. };
  97. Legend.prototype.redraw = function() {
  98. var activeGroups = 0;
  99. var groupArray = Object.keys(this.groups);
  100. groupArray.sort(function (a,b) {
  101. return (a < b ? -1 : 1);
  102. })
  103. for (var i = 0; i < groupArray.length; i++) {
  104. var groupId = groupArray[i];
  105. if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) {
  106. activeGroups++;
  107. }
  108. }
  109. if (this.options[this.side].visible == false || this.amountOfGroups == 0 || this.options.enabled == false || activeGroups == 0) {
  110. this.hide();
  111. }
  112. else {
  113. this.show();
  114. if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'bottom-left') {
  115. this.dom.frame.style.left = '4px';
  116. this.dom.frame.style.textAlign = "left";
  117. this.dom.textArea.style.textAlign = "left";
  118. this.dom.textArea.style.left = (this.options.iconSize + 15) + 'px';
  119. this.dom.textArea.style.right = '';
  120. this.svg.style.left = 0 +'px';
  121. this.svg.style.right = '';
  122. }
  123. else {
  124. this.dom.frame.style.right = '4px';
  125. this.dom.frame.style.textAlign = "right";
  126. this.dom.textArea.style.textAlign = "right";
  127. this.dom.textArea.style.right = (this.options.iconSize + 15) + 'px';
  128. this.dom.textArea.style.left = '';
  129. this.svg.style.right = 0 +'px';
  130. this.svg.style.left = '';
  131. }
  132. if (this.options[this.side].position == 'top-left' || this.options[this.side].position == 'top-right') {
  133. this.dom.frame.style.top = 4 - Number(this.body.dom.center.style.top.replace("px","")) + 'px';
  134. this.dom.frame.style.bottom = '';
  135. }
  136. else {
  137. var scrollableHeight = this.body.domProps.center.height - this.body.domProps.centerContainer.height;
  138. this.dom.frame.style.bottom = 4 + scrollableHeight + Number(this.body.dom.center.style.top.replace("px","")) + 'px';
  139. this.dom.frame.style.top = '';
  140. }
  141. if (this.options.icons == false) {
  142. this.dom.frame.style.width = this.dom.textArea.offsetWidth + 10 + 'px';
  143. this.dom.textArea.style.right = '';
  144. this.dom.textArea.style.left = '';
  145. this.svg.style.width = '0px';
  146. }
  147. else {
  148. this.dom.frame.style.width = this.options.iconSize + 15 + this.dom.textArea.offsetWidth + 10 + 'px'
  149. this.drawLegendIcons();
  150. }
  151. var content = '';
  152. for (var i = 0; i < groupArray.length; i++) {
  153. var groupId = groupArray[i];
  154. if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) {
  155. content += this.groups[groupId].content + '<br />';
  156. }
  157. }
  158. this.dom.textArea.innerHTML = content;
  159. this.dom.textArea.style.lineHeight = ((0.75 * this.options.iconSize) + this.options.iconSpacing) + 'px';
  160. }
  161. };
  162. Legend.prototype.drawLegendIcons = function() {
  163. if (this.dom.frame.parentNode) {
  164. var groupArray = Object.keys(this.groups);
  165. groupArray.sort(function (a,b) {
  166. return (a < b ? -1 : 1);
  167. });
  168. // this resets the elements so the order is maintained
  169. DOMutil.resetElements(this.svgElements);
  170. var padding = window.getComputedStyle(this.dom.frame).paddingTop;
  171. var iconOffset = Number(padding.replace('px',''));
  172. var x = iconOffset;
  173. var iconWidth = this.options.iconSize;
  174. var iconHeight = 0.75 * this.options.iconSize;
  175. var y = iconOffset + 0.5 * iconHeight + 3;
  176. this.svg.style.width = iconWidth + 5 + iconOffset + 'px';
  177. for (var i = 0; i < groupArray.length; i++) {
  178. var groupId = groupArray[i];
  179. if (this.groups[groupId].visible == true && (this.linegraphOptions.visibility[groupId] === undefined || this.linegraphOptions.visibility[groupId] == true)) {
  180. this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight);
  181. y += iconHeight + this.options.iconSpacing;
  182. }
  183. }
  184. }
  185. };
  186. module.exports = Legend;