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.

213 lines
5.4 KiB

  1. /**
  2. * @constructor Group
  3. * @param {Panel} groupPanel
  4. * @param {Panel} labelPanel
  5. * @param {Panel} backgroundPanel
  6. * @param {Panel} axisPanel
  7. * @param {Number | String} groupId
  8. * @param {Object} [options] Options to set initial property values
  9. * // TODO: describe available options
  10. * @extends Component
  11. */
  12. function Group (groupPanel, labelPanel, backgroundPanel, axisPanel, groupId, options) {
  13. this.id = util.randomUUID();
  14. this.groupPanel = groupPanel;
  15. this.labelPanel = labelPanel;
  16. this.backgroundPanel = backgroundPanel;
  17. this.axisPanel = axisPanel;
  18. this.groupId = groupId;
  19. this.itemSet = null; // ItemSet
  20. this.options = options || {};
  21. this.options.top = 0;
  22. this.props = {
  23. label: {
  24. width: 0,
  25. height: 0
  26. }
  27. };
  28. this.dom = {};
  29. this.top = 0;
  30. this.left = 0;
  31. this.width = 0;
  32. this.height = 0;
  33. this._create();
  34. }
  35. Group.prototype = new Component();
  36. // TODO: comment
  37. Group.prototype.setOptions = Component.prototype.setOptions;
  38. /**
  39. * Create DOM elements for the group
  40. * @private
  41. */
  42. Group.prototype._create = function() {
  43. var label = document.createElement('div');
  44. label.className = 'vlabel';
  45. this.dom.label = label;
  46. var inner = document.createElement('div');
  47. inner.className = 'inner';
  48. label.appendChild(inner);
  49. this.dom.inner = inner;
  50. };
  51. /**
  52. * Set the group data for this group
  53. * @param {Object} data Group data, can contain properties content and className
  54. */
  55. Group.prototype.setData = function setData(data) {
  56. // update contents
  57. var content = data && data.content;
  58. if (content instanceof Element) {
  59. this.dom.inner.appendChild(content);
  60. }
  61. else if (content != undefined) {
  62. this.dom.inner.innerHTML = content;
  63. }
  64. else {
  65. this.dom.inner.innerHTML = this.groupId;
  66. }
  67. // update className
  68. var className = data && data.className;
  69. if (className) {
  70. util.addClassName(this.dom.label, className);
  71. }
  72. };
  73. /**
  74. * Set item set for the group. The group will create a view on the itemSet,
  75. * filtered by the groups id.
  76. * @param {DataSet | DataView} itemsData
  77. */
  78. Group.prototype.setItems = function setItems(itemsData) {
  79. if (this.itemSet) {
  80. // remove current item set
  81. this.itemSet.setItems();
  82. this.itemSet.hide();
  83. this.groupPanel.frame.removeChild(this.itemSet.getFrame());
  84. this.itemSet = null;
  85. }
  86. if (itemsData) {
  87. var groupId = this.groupId;
  88. var me = this;
  89. var itemSetOptions = util.extend(this.options, {
  90. height: function () {
  91. // FIXME: setting height doesn't yet work
  92. return Math.max(me.props.label.height, me.itemSet.height);
  93. }
  94. });
  95. this.itemSet = new ItemSet(this.backgroundPanel, this.axisPanel, itemSetOptions);
  96. this.itemSet.on('change', this.emit.bind(this, 'change')); // propagate change event
  97. this.itemSet.parent = this;
  98. this.groupPanel.frame.appendChild(this.itemSet.getFrame());
  99. if (this.range) this.itemSet.setRange(this.range);
  100. this.view = new DataView(itemsData, {
  101. filter: function (item) {
  102. return item.group == groupId;
  103. }
  104. });
  105. this.itemSet.setItems(this.view);
  106. }
  107. };
  108. /**
  109. * hide the group, detach from DOM if needed
  110. */
  111. Group.prototype.show = function show() {
  112. if (!this.dom.label.parentNode) {
  113. this.labelPanel.frame.appendChild(this.dom.label);
  114. }
  115. var itemSetFrame = this.itemSet && this.itemSet.getFrame();
  116. if (itemSetFrame) {
  117. if (itemSetFrame.parentNode) {
  118. itemSetFrame.parentNode.removeChild(itemSetFrame);
  119. }
  120. this.groupPanel.frame.appendChild(itemSetFrame);
  121. this.itemSet.show();
  122. }
  123. };
  124. /**
  125. * hide the group, detach from DOM if needed
  126. */
  127. Group.prototype.hide = function hide() {
  128. if (this.dom.label.parentNode) {
  129. this.dom.label.parentNode.removeChild(this.dom.label);
  130. }
  131. if (this.itemSet) {
  132. this.itemSet.hide();
  133. }
  134. var itemSetFrame = this.itemset && this.itemSet.getFrame();
  135. if (itemSetFrame && itemSetFrame.parentNode) {
  136. itemSetFrame.parentNode.removeChild(itemSetFrame);
  137. }
  138. };
  139. /**
  140. * Set range (start and end).
  141. * @param {Range | Object} range A Range or an object containing start and end.
  142. */
  143. Group.prototype.setRange = function (range) {
  144. this.range = range;
  145. if (this.itemSet) this.itemSet.setRange(range);
  146. };
  147. /**
  148. * Set selected items by their id. Replaces the current selection.
  149. * Unknown id's are silently ignored.
  150. * @param {Array} [ids] An array with zero or more id's of the items to be
  151. * selected. If ids is an empty array, all items will be
  152. * unselected.
  153. */
  154. Group.prototype.setSelection = function setSelection(ids) {
  155. if (this.itemSet) this.itemSet.setSelection(ids);
  156. };
  157. /**
  158. * Get the selected items by their id
  159. * @return {Array} ids The ids of the selected items
  160. */
  161. Group.prototype.getSelection = function getSelection() {
  162. return this.itemSet ? this.itemSet.getSelection() : [];
  163. };
  164. /**
  165. * Repaint the group
  166. * @return {boolean} Returns true if the component is resized
  167. */
  168. Group.prototype.repaint = function repaint() {
  169. var resized = false;
  170. this.show();
  171. if (this.itemSet) {
  172. resized = this.itemSet.repaint() || resized;
  173. }
  174. // calculate inner size of the label
  175. resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized;
  176. resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized;
  177. this.height = this.itemSet ? this.itemSet.height : 0;
  178. this.dom.label.style.height = this.height + 'px';
  179. return resized;
  180. };