visjs-network
Version:
A dynamic, browser-based network visualization library.
240 lines (227 loc) • 7.5 kB
JavaScript
// 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)
}
}
}