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

/**
* @constructor Group
* @param {Panel} groupPanel
* @param {Panel} labelPanel
* @param {Panel} backgroundPanel
* @param {Panel} axisPanel
* @param {Number | String} groupId
* @param {Object} [options] Options to set initial property values
* // TODO: describe available options
* @extends Component
*/
function Group (groupPanel, labelPanel, backgroundPanel, axisPanel, groupId, options) {
this.id = util.randomUUID();
this.groupPanel = groupPanel;
this.labelPanel = labelPanel;
this.backgroundPanel = backgroundPanel;
this.axisPanel = axisPanel;
this.groupId = groupId;
this.itemSet = null; // ItemSet
this.options = options || {};
this.options.top = 0;
this.props = {
label: {
width: 0,
height: 0
}
};
this.dom = {};
this.top = 0;
this.left = 0;
this.width = 0;
this.height = 0;
this._create();
}
Group.prototype = new Component();
// TODO: comment
Group.prototype.setOptions = Component.prototype.setOptions;
/**
* Create DOM elements for the group
* @private
*/
Group.prototype._create = function() {
var label = document.createElement('div');
label.className = 'vlabel';
this.dom.label = label;
var inner = document.createElement('div');
inner.className = 'inner';
label.appendChild(inner);
this.dom.inner = inner;
};
/**
* Set the group data for this group
* @param {Object} data Group data, can contain properties content and className
*/
Group.prototype.setData = function setData(data) {
// update contents
var content = data && data.content;
if (content instanceof Element) {
this.dom.inner.appendChild(content);
}
else if (content != undefined) {
this.dom.inner.innerHTML = content;
}
else {
this.dom.inner.innerHTML = this.groupId;
}
// update className
var className = data && data.className;
if (className) {
util.addClassName(this.dom.label, className);
}
};
/**
* Set item set for the group. The group will create a view on the itemSet,
* filtered by the groups id.
* @param {DataSet | DataView} itemsData
*/
Group.prototype.setItems = function setItems(itemsData) {
if (this.itemSet) {
// remove current item set
this.itemSet.setItems();
this.itemSet.hide();
this.groupPanel.frame.removeChild(this.itemSet.getFrame());
this.itemSet = null;
}
if (itemsData) {
var groupId = this.groupId;
var me = this;
var itemSetOptions = util.extend(this.options, {
height: function () {
// FIXME: setting height doesn't yet work
return Math.max(me.props.label.height, me.itemSet.height);
}
});
this.itemSet = new ItemSet(this.backgroundPanel, this.axisPanel, itemSetOptions);
this.itemSet.on('change', this.emit.bind(this, 'change')); // propagate change event
this.itemSet.parent = this;
this.groupPanel.frame.appendChild(this.itemSet.getFrame());
if (this.range) this.itemSet.setRange(this.range);
this.view = new DataView(itemsData, {
filter: function (item) {
return item.group == groupId;
}
});
this.itemSet.setItems(this.view);
}
};
/**
* hide the group, detach from DOM if needed
*/
Group.prototype.show = function show() {
if (!this.dom.label.parentNode) {
this.labelPanel.frame.appendChild(this.dom.label);
}
var itemSetFrame = this.itemSet && this.itemSet.getFrame();
if (itemSetFrame) {
if (itemSetFrame.parentNode) {
itemSetFrame.parentNode.removeChild(itemSetFrame);
}
this.groupPanel.frame.appendChild(itemSetFrame);
this.itemSet.show();
}
};
/**
* hide the group, detach from DOM if needed
*/
Group.prototype.hide = function hide() {
if (this.dom.label.parentNode) {
this.dom.label.parentNode.removeChild(this.dom.label);
}
if (this.itemSet) {
this.itemSet.hide();
}
var itemSetFrame = this.itemset && this.itemSet.getFrame();
if (itemSetFrame && itemSetFrame.parentNode) {
itemSetFrame.parentNode.removeChild(itemSetFrame);
}
};
/**
* Set range (start and end).
* @param {Range | Object} range A Range or an object containing start and end.
*/
Group.prototype.setRange = function (range) {
this.range = range;
if (this.itemSet) this.itemSet.setRange(range);
};
/**
* Set selected items by their id. Replaces the current selection.
* Unknown id's are silently ignored.
* @param {Array} [ids] An array with zero or more id's of the items to be
* selected. If ids is an empty array, all items will be
* unselected.
*/
Group.prototype.setSelection = function setSelection(ids) {
if (this.itemSet) this.itemSet.setSelection(ids);
};
/**
* Get the selected items by their id
* @return {Array} ids The ids of the selected items
*/
Group.prototype.getSelection = function getSelection() {
return this.itemSet ? this.itemSet.getSelection() : [];
};
/**
* Repaint the group
* @return {boolean} Returns true if the component is resized
*/
Group.prototype.repaint = function repaint() {
var resized = false;
this.show();
if (this.itemSet) {
resized = this.itemSet.repaint() || resized;
}
// calculate inner size of the label
resized = util.updateProperty(this.props.label, 'width', this.dom.inner.clientWidth) || resized;
resized = util.updateProperty(this.props.label, 'height', this.dom.inner.clientHeight) || resized;
this.height = this.itemSet ? this.itemSet.height : 0;
this.dom.label.style.height = this.height + 'px';
return resized;
};