|
// DOM utility methods
|
|
|
|
/**
|
|
* this prepares the JSON container for allocating SVG elements
|
|
* @param {Object} JSONcontainer
|
|
* @private
|
|
*/
|
|
exports.prepareElements = function(JSONcontainer) {
|
|
// cleanup the redundant svgElements;
|
|
for (var elementType in JSONcontainer) {
|
|
if (JSONcontainer.hasOwnProperty(elementType)) {
|
|
JSONcontainer[elementType].redundant = JSONcontainer[elementType].used;
|
|
JSONcontainer[elementType].used = [];
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* this cleans up all the unused SVG elements. By asking for the parentNode, we only need to supply the JSON container from
|
|
* which to remove the redundant elements.
|
|
*
|
|
* @param {Object} JSONcontainer
|
|
* @private
|
|
*/
|
|
exports.cleanupElements = function(JSONcontainer) {
|
|
// cleanup the redundant svgElements;
|
|
for (var elementType in JSONcontainer) {
|
|
if (JSONcontainer.hasOwnProperty(elementType)) {
|
|
if (JSONcontainer[elementType].redundant) {
|
|
for (var i = 0; i < JSONcontainer[elementType].redundant.length; i++) {
|
|
JSONcontainer[elementType].redundant[i].parentNode.removeChild(JSONcontainer[elementType].redundant[i]);
|
|
}
|
|
JSONcontainer[elementType].redundant = [];
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Ensures that all elements are removed first up so they can be recreated cleanly
|
|
* @param {Object} JSONcontainer
|
|
*/
|
|
exports.resetElements = function(JSONcontainer) {
|
|
exports.prepareElements(JSONcontainer);
|
|
exports.cleanupElements(JSONcontainer);
|
|
exports.prepareElements(JSONcontainer);
|
|
};
|
|
|
|
/**
|
|
* Allocate or generate an SVG element if needed. Store a reference to it in the JSON container and draw it in the svgContainer
|
|
* the JSON container and the SVG container have to be supplied so other svg containers (like the legend) can use this.
|
|
*
|
|
* @param {String} elementType
|
|
* @param {Object} JSONcontainer
|
|
* @param {Object} svgContainer
|
|
* @returns {Element}
|
|
* @private
|
|
*/
|
|
exports.getSVGElement = function (elementType, JSONcontainer, svgContainer) {
|
|
var element;
|
|
// allocate SVG element, if it doesnt yet exist, create one.
|
|
if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before
|
|
// check if there is an redundant element
|
|
if (JSONcontainer[elementType].redundant.length > 0) {
|
|
element = JSONcontainer[elementType].redundant[0];
|
|
JSONcontainer[elementType].redundant.shift();
|
|
}
|
|
else {
|
|
// create a new element and add it to the SVG
|
|
element = document.createElementNS('http://www.w3.org/2000/svg', elementType);
|
|
svgContainer.appendChild(element);
|
|
}
|
|
}
|
|
else {
|
|
// create a new element and add it to the SVG, also create a new object in the svgElements to keep track of it.
|
|
element = document.createElementNS('http://www.w3.org/2000/svg', elementType);
|
|
JSONcontainer[elementType] = {used: [], redundant: []};
|
|
svgContainer.appendChild(element);
|
|
}
|
|
JSONcontainer[elementType].used.push(element);
|
|
return element;
|
|
};
|
|
|
|
|
|
/**
|
|
* Allocate or generate an SVG element if needed. Store a reference to it in the JSON container and draw it in the svgContainer
|
|
* the JSON container and the SVG container have to be supplied so other svg containers (like the legend) can use this.
|
|
*
|
|
* @param {String} elementType
|
|
* @param {Object} JSONcontainer
|
|
* @param {Element} DOMContainer
|
|
* @param {Element} insertBefore
|
|
* @returns {*}
|
|
*/
|
|
exports.getDOMElement = function (elementType, JSONcontainer, DOMContainer, insertBefore) {
|
|
var element;
|
|
// allocate DOM element, if it doesnt yet exist, create one.
|
|
if (JSONcontainer.hasOwnProperty(elementType)) { // this element has been created before
|
|
// check if there is an redundant element
|
|
if (JSONcontainer[elementType].redundant.length > 0) {
|
|
element = JSONcontainer[elementType].redundant[0];
|
|
JSONcontainer[elementType].redundant.shift();
|
|
}
|
|
else {
|
|
// create a new element and add it to the SVG
|
|
element = document.createElement(elementType);
|
|
if (insertBefore !== undefined) {
|
|
DOMContainer.insertBefore(element, insertBefore);
|
|
}
|
|
else {
|
|
DOMContainer.appendChild(element);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// create a new element and add it to the SVG, also create a new object in the svgElements to keep track of it.
|
|
element = document.createElement(elementType);
|
|
JSONcontainer[elementType] = {used: [], redundant: []};
|
|
if (insertBefore !== undefined) {
|
|
DOMContainer.insertBefore(element, insertBefore);
|
|
}
|
|
else {
|
|
DOMContainer.appendChild(element);
|
|
}
|
|
}
|
|
JSONcontainer[elementType].used.push(element);
|
|
return element;
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Draw a point object. This is a separate function because it can also be called by the legend.
|
|
* The reason the JSONcontainer and the target SVG svgContainer have to be supplied is so the legend can use these functions
|
|
* as well.
|
|
*
|
|
* @param {Number} x
|
|
* @param {Number} y
|
|
* @param {Object} groupTemplate: A template containing the necessary information to draw the datapoint e.g., {style: 'circle', size: 5, className: 'className' }
|
|
* @param {Object} JSONcontainer
|
|
* @param {Object} svgContainer
|
|
* @param {Object} labelObj
|
|
* @returns {vis.PointItem}
|
|
*/
|
|
exports.drawPoint = function(x, y, groupTemplate, JSONcontainer, svgContainer, labelObj) {
|
|
var point;
|
|
if (groupTemplate.style == 'circle') {
|
|
point = exports.getSVGElement('circle', JSONcontainer, svgContainer);
|
|
point.setAttributeNS(null, "cx", x);
|
|
point.setAttributeNS(null, "cy", y);
|
|
point.setAttributeNS(null, "r", 0.5 * groupTemplate.size);
|
|
}
|
|
else {
|
|
point = exports.getSVGElement('rect', JSONcontainer, svgContainer);
|
|
point.setAttributeNS(null, "x", x - 0.5 * groupTemplate.size);
|
|
point.setAttributeNS(null, "y", y - 0.5 * groupTemplate.size);
|
|
point.setAttributeNS(null, "width", groupTemplate.size);
|
|
point.setAttributeNS(null, "height", groupTemplate.size);
|
|
}
|
|
|
|
if (groupTemplate.styles !== undefined) {
|
|
point.setAttributeNS(null, "style", groupTemplate.styles);
|
|
}
|
|
point.setAttributeNS(null, "class", groupTemplate.className + " vis-point");
|
|
//handle label
|
|
|
|
|
|
if (labelObj) {
|
|
var label = exports.getSVGElement('text', JSONcontainer, svgContainer);
|
|
if (labelObj.xOffset) {
|
|
x = x + labelObj.xOffset;
|
|
}
|
|
|
|
if (labelObj.yOffset) {
|
|
y = y + labelObj.yOffset;
|
|
}
|
|
if (labelObj.content) {
|
|
label.textContent = labelObj.content;
|
|
}
|
|
|
|
if (labelObj.className) {
|
|
label.setAttributeNS(null, "class", labelObj.className + " vis-label");
|
|
}
|
|
label.setAttributeNS(null, "x", x);
|
|
label.setAttributeNS(null, "y", y);
|
|
}
|
|
|
|
return point;
|
|
};
|
|
|
|
/**
|
|
* draw a bar SVG element centered on the X coordinate
|
|
*
|
|
* @param {Number} x
|
|
* @param {Number} y
|
|
* @param {Number} width
|
|
* @param {Number} height
|
|
* @param {String} className
|
|
* @param {Object} JSONcontainer
|
|
* @param {Object} svgContainer
|
|
* @param {string} style
|
|
*/
|
|
exports.drawBar = function (x, y, width, height, className, JSONcontainer, svgContainer, style) {
|
|
if (height != 0) {
|
|
if (height < 0) {
|
|
height *= -1;
|
|
y -= height;
|
|
}
|
|
var rect = exports.getSVGElement('rect',JSONcontainer, svgContainer);
|
|
rect.setAttributeNS(null, "x", x - 0.5 * width);
|
|
rect.setAttributeNS(null, "y", y);
|
|
rect.setAttributeNS(null, "width", width);
|
|
rect.setAttributeNS(null, "height", height);
|
|
rect.setAttributeNS(null, "class", className);
|
|
if (style) {
|
|
rect.setAttributeNS(null, "style", style);
|
|
}
|
|
}
|
|
};
|