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.

176 lines
5.3 KiB

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