Browse Source

Enable jsdoc-require MethodDefinition (#3382)

* Enables require MethodDefinition for require-jsdoc lint rule and corrects 66% of missing Method Definitions

* Adds jsdoc for all remaining methods and corrects @class/@constructor documentation

* Define values more accurately

* Correct bugs that prevent jsdoc generation
revert-3409-performance
macleodbroad-wf 7 years ago
committed by Yotam Berkowitz
parent
commit
48c7cf93f1
63 changed files with 1509 additions and 296 deletions
  1. +1
    -1
      .eslintrc
  2. +4
    -1
      lib/DataSet.js
  3. +1
    -1
      lib/graph3d/Graph3d.js
  4. +8
    -2
      lib/network/CachedImage.js
  5. +8
    -3
      lib/network/Images.js
  6. +4
    -1
      lib/network/NetworkUtil.js
  7. +29
    -7
      lib/network/modules/Canvas.js
  8. +21
    -5
      lib/network/modules/CanvasRenderer.js
  9. +20
    -3
      lib/network/modules/Clustering.js
  10. +27
    -8
      lib/network/modules/EdgesHandler.js
  11. +7
    -1
      lib/network/modules/Groups.js
  12. +18
    -5
      lib/network/modules/InteractionHandler.js
  13. +15
    -2
      lib/network/modules/KamadaKawai.js
  14. +45
    -6
      lib/network/modules/LayoutEngine.js
  15. +66
    -0
      lib/network/modules/ManipulationSystem.js
  16. +19
    -6
      lib/network/modules/NodesHandler.js
  17. +13
    -3
      lib/network/modules/PhysicsEngine.js
  18. +25
    -4
      lib/network/modules/SelectionHandler.js
  19. +21
    -5
      lib/network/modules/View.js
  20. +53
    -15
      lib/network/modules/components/Edge.js
  21. +49
    -5
      lib/network/modules/components/NavigationHandler.js
  22. +42
    -21
      lib/network/modules/components/Node.js
  23. +12
    -1
      lib/network/modules/components/algorithms/FloydWarshall.js
  24. +22
    -5
      lib/network/modules/components/edges/BezierEdgeDynamic.js
  25. +12
    -5
      lib/network/modules/components/edges/BezierEdgeStatic.js
  26. +37
    -5
      lib/network/modules/components/edges/CubicBezierEdge.js
  27. +31
    -5
      lib/network/modules/components/edges/StraightEdge.js
  28. +11
    -5
      lib/network/modules/components/edges/util/BezierEdgeBase.js
  29. +7
    -4
      lib/network/modules/components/edges/util/CubicBezierEdgeBase.js
  30. +88
    -7
      lib/network/modules/components/edges/util/EdgeBase.js
  31. +9
    -6
      lib/network/modules/components/nodes/Cluster.js
  32. +36
    -4
      lib/network/modules/components/nodes/shapes/Box.js
  33. +34
    -5
      lib/network/modules/components/nodes/shapes/Circle.js
  34. +35
    -4
      lib/network/modules/components/nodes/shapes/CircularImage.js
  35. +29
    -6
      lib/network/modules/components/nodes/shapes/Database.js
  36. +22
    -4
      lib/network/modules/components/nodes/shapes/Diamond.js
  37. +22
    -4
      lib/network/modules/components/nodes/shapes/Dot.js
  38. +28
    -5
      lib/network/modules/components/nodes/shapes/Ellipse.js
  39. +42
    -4
      lib/network/modules/components/nodes/shapes/Icon.js
  40. +36
    -5
      lib/network/modules/components/nodes/shapes/Image.js
  41. +22
    -4
      lib/network/modules/components/nodes/shapes/Square.js
  42. +22
    -4
      lib/network/modules/components/nodes/shapes/Star.js
  43. +28
    -4
      lib/network/modules/components/nodes/shapes/Text.js
  44. +22
    -4
      lib/network/modules/components/nodes/shapes/Triangle.js
  45. +22
    -4
      lib/network/modules/components/nodes/shapes/TriangleDown.js
  46. +40
    -1
      lib/network/modules/components/nodes/util/CircleImageBase.js
  47. +63
    -8
      lib/network/modules/components/nodes/util/NodeBase.js
  48. +32
    -5
      lib/network/modules/components/nodes/util/ShapeBase.js
  49. +15
    -5
      lib/network/modules/components/physics/BarnesHutSolver.js
  50. +15
    -5
      lib/network/modules/components/physics/CentralGravitySolver.js
  51. +7
    -5
      lib/network/modules/components/physics/FA2BasedCentralGravitySolver.js
  52. +8
    -5
      lib/network/modules/components/physics/FA2BasedRepulsionSolver.js
  53. +11
    -5
      lib/network/modules/components/physics/HierarchicalRepulsionSolver.js
  54. +11
    -5
      lib/network/modules/components/physics/HierarchicalSpringSolver.js
  55. +11
    -5
      lib/network/modules/components/physics/RepulsionSolver.js
  56. +11
    -5
      lib/network/modules/components/physics/SpringSolver.js
  57. +70
    -9
      lib/network/modules/components/shared/Label.js
  58. +11
    -2
      lib/shared/ColorPicker.js
  59. +29
    -5
      lib/shared/Configurator.js
  60. +6
    -2
      lib/shared/Popup.js
  61. +39
    -11
      lib/shared/Validator.js
  62. +3
    -2
      lib/timeline/Timeline.js
  63. +2
    -2
      lib/util.js

+ 1
- 1
.eslintrc View File

@ -22,7 +22,7 @@
"require-jsdoc": ["error", {
"require": {
"FunctionDeclaration": true,
"MethodDefinition": false,
"MethodDefinition": true,
"ClassDeclaration": true,
"ArrowFunctionExpression": false
}

+ 4
- 1
lib/DataSet.js View File

@ -141,7 +141,10 @@ DataSet.prototype.on = function(event, callback) {
});
};
// TODO: remove this deprecated function some day (replaced with `on` since version 0.5, deprecated since v4.0)
/**
* TODO: remove this deprecated function some day (replaced with `on` since version 0.5, deprecated since v4.0)
* @throws {Error}
*/
DataSet.prototype.subscribe = function () {
throw new Error('DataSet.subscribe is deprecated. Use DataSet.on instead.');
};

+ 1
- 1
lib/graph3d/Graph3d.js View File

@ -1540,7 +1540,7 @@ Graph3d.prototype._getColorsColor = function(point) {
* Get the colors for the 'size' graph styles.
* These styles are currently: 'bar-size' and 'dot-size'
*
* @returns {{fill: *, border: (string|undefinedOptions.colorOptions.stroke|{string, undefined}|string|colorOptions.stroke|{string}|*)}}
* @returns {{fill: *, border: (string|colorOptions.stroke|{string, undefined}|string|colorOptions.stroke|{string}|*)}}
* @private
*/
Graph3d.prototype._getColorsSize = function() {

+ 8
- 2
lib/network/CachedImage.js View File

@ -7,10 +7,16 @@
*
* NOTE: Images can also be of type 'data:svg+xml`. This code also works
* for svg, but the mipmapping may not be necessary.
*
* @class CachedImage
*/
class CachedImage {
// eslint-disable-next-line no-unused-vars
constructor(image) {
/**
* Create a Chached Image
* @param {Image} image
* @constructor
*/
constructor(image) { // eslint-disable-line no-unused-vars
this.NUM_ITERATIONS = 4; // Number of items in the coordinates array
this.image = new Image();

+ 8
- 3
lib/network/Images.js View File

@ -3,16 +3,21 @@ import CachedImage from './CachedImage';
/**
* This class loads images and keeps them stored.
* @class Images
* class Images
*/
class Images {
constructor(callback){
/**
* Create a Images
* @callback callback
* @param {function} callback
* @constructor Images
*/
constructor(callback){
this.images = {};
this.imageBroken = {};
this.callback = callback;
}
/**
* @param {string} url The original Url that failed to load, if the broken image is successfully loaded it will be added to the cache using this Url as the key so that subsequent requests for this Url will return the broken image
* @param {string} brokenUrl Url the broken image to try and load

+ 4
- 1
lib/network/NetworkUtil.js View File

@ -1,9 +1,12 @@
let util = require("../util");
/**
* @constructor NetworkUtil
* @class NetworkUtil
*/
class NetworkUtil {
/**
* @constructor NetworkUtil
*/
constructor() {}
/**

+ 29
- 7
lib/network/modules/Canvas.js View File

@ -8,9 +8,14 @@ let util = require('../../util');
* This function is executed once when a Network object is created. The frame
* contains a canvas, and this canvas contains all objects like the axis and
* nodes.
* @private
*
* @class Canvas
*/
class Canvas {
/**
* @param {Object} body
* @constructor Canvas
*/
constructor(body) {
this.body = body;
this.pixelRatio = 1;
@ -31,6 +36,9 @@ class Canvas {
this.bindEventListeners();
}
/**
* Binds event listeners
*/
bindEventListeners() {
// bind the events
this.body.emitter.once("resize", (obj) => {
@ -47,10 +55,11 @@ class Canvas {
this.hammer.destroy();
this._cleanUp();
});
}
/**
* @param {Object} options
*/
setOptions(options) {
if (options !== undefined) {
let fields = ['width','height','autoResize'];
@ -71,6 +80,9 @@ class Canvas {
}
}
/**
* @private
*/
_cleanUp() {
// automatically adapt to a changing size of the browser.
if (this.resizeTimer !== undefined) {
@ -80,6 +92,9 @@ class Canvas {
this.resizeFunction = undefined;
}
/**
* @private
*/
_onResize() {
this.setSize();
this.body.emitter.emit("_redraw");
@ -144,6 +159,13 @@ class Canvas {
}
}
/**
*
* @param {number|string} value
* @returns {string}
* @private
* @static
*/
_prepareValue(value) {
if (typeof value === 'number') {
return value + 'px';
@ -335,12 +357,14 @@ class Canvas {
return emitEvent;
}
/**
*
* @returns {CanvasRenderingContext2D}
*/
getContext() {
return this.frame.canvas.getContext("2d");
}
/**
* Determine the pixel ratio for various browsers.
*
@ -360,7 +384,6 @@ class Canvas {
ctx.backingStorePixelRatio || 1);
}
/**
* Lazy determination of pixel ratio.
*
@ -370,7 +393,6 @@ class Canvas {
this.pixelRatio = this._determinePixelRatio();
}
/**
* Set the transform in the contained context, based on its pixelRatio
*/

+ 21
- 5
lib/network/modules/CanvasRenderer.js View File

@ -44,12 +44,14 @@ function _initRequestAnimationFrame() {
let util = require('../../util');
/**
*
* @param {Object} body
* @param {Canvas} canvas
* @constructor CanvasRenderer
* @class CanvasRenderer
*/
class CanvasRenderer {
/**
* @param {Object} body
* @param {Canvas} canvas
* @constructor CanvasRenderer
*/
constructor(body, canvas) {
_initRequestAnimationFrame();
this.body = body;
@ -74,6 +76,9 @@ class CanvasRenderer {
this.bindEventListeners();
}
/**
* Binds event listeners
*/
bindEventListeners() {
this.body.emitter.on("dragStart", () => { this.dragging = true; });
this.body.emitter.on("dragEnd", () => { this.dragging = false; });
@ -111,6 +116,10 @@ class CanvasRenderer {
}
/**
*
* @param {Object} options
*/
setOptions(options) {
if (options !== undefined) {
let fields = ['hideEdgesOnDrag','hideNodesOnDrag'];
@ -157,7 +166,10 @@ class CanvasRenderer {
return timer;
}
/**
*
* @private
*/
_startRendering() {
if (this.renderingActive === true) {
if (this.renderTimer === undefined) {
@ -166,6 +178,10 @@ class CanvasRenderer {
}
}
/**
*
* @private
*/
_renderStep() {
if (this.renderingActive === true) {
// reset the renderTimer so a new scheduled animation step can be set

+ 20
- 3
lib/network/modules/Clustering.js View File

@ -99,11 +99,13 @@ var Edge = require('./components/Edge').default; // Only needed for check on ty
var Node = require('./components/Node').default; // Only needed for check on type!
/**
*
* @param {Object} body
* @constructor ClusterEngine
* @class ClusterEngine
*/
class ClusterEngine {
/**
* @param {Object} body
* @constructor ClusterEngine
*/
constructor(body) {
this.body = body;
this.clusteredNodes = {}; // key: node id, value: { clusterId: <id of cluster>, node: <node instance>}
@ -580,12 +582,22 @@ class ClusterEngine {
}
}
/**
*
* @param {Edge} edge
* @private
*/
_backupEdgeOptions(edge) {
if (this.clusteredEdges[edge.id] === undefined) {
this.clusteredEdges[edge.id] = {physics: edge.options.physics};
}
}
/**
*
* @param {Edge} edge
* @private
*/
_restoreEdge(edge) {
let originalOptions = this.clusteredEdges[edge.id];
if (originalOptions !== undefined) {
@ -772,6 +784,11 @@ class ClusterEngine {
}
}
/**
*
* @param {Cluster.id} clusterId
* @returns {Array<Node.id>}
*/
getNodesInCluster(clusterId) {
let nodesArray = [];
if (this.isCluster(clusterId) === true) {

+ 27
- 8
lib/network/modules/EdgesHandler.js View File

@ -6,13 +6,15 @@ var Edge = require("./components/Edge").default;
var Label = require("./components/shared/Label").default;
/**
*
* @param {Object} body
* @param {Array<Image>} images
* @param {Array<Group>} groups
* @constructor EdgesHandler
* @class EdgesHandler
*/
class EdgesHandler {
/**
* @param {Object} body
* @param {Array<Image>} images
* @param {Array<Group>} groups
* @constructor EdgesHandler
*/
constructor(body, images, groups) {
this.body = body;
this.images = images;
@ -120,6 +122,9 @@ class EdgesHandler {
this.bindEventListeners();
}
/**
* Binds event listeners
*/
bindEventListeners() {
// this allows external modules to force all dynamic curves to turn static.
this.body.emitter.on("_forceDisableDynamicCurves", (type, emit = true) => {
@ -184,6 +189,10 @@ class EdgesHandler {
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.edgeOptions = options;
if (options !== undefined) {
@ -358,7 +367,9 @@ class EdgesHandler {
}
}
/**
* Refreshes Edge Handler
*/
refresh() {
let edges = this.body.edges;
for (let edgeId in edges) {
@ -373,6 +384,11 @@ class EdgesHandler {
}
}
/**
*
* @param {Object} properties
* @returns {Edge}
*/
create(properties) {
return new Edge(properties, this.body, this.options, this.defaultOptions, this.edgeOptions)
}
@ -402,7 +418,11 @@ class EdgesHandler {
}
}
/**
*
* @param {Edge.id} edgeId
* @returns {Array}
*/
getConnectedNodes(edgeId) {
let nodeList = [];
if (this.body.edges[edgeId] !== undefined) {
@ -413,7 +433,6 @@ class EdgesHandler {
return nodeList;
}
/**
* Scan for missing nodes and remove corresponding edges, if any.
*

+ 7
- 1
lib/network/modules/Groups.js View File

@ -5,6 +5,9 @@ let util = require('../../util');
* @class Groups
*/
class Groups {
/**
* @constructor Groups
*/
constructor() {
this.clear();
this.defaultIndex = 0;
@ -44,7 +47,10 @@ class Groups {
util.extend(this.options, this.defaultOptions);
}
/**
*
* @param {Object} options
*/
setOptions(options) {
let optionFields = ['useDefaultGroups'];

+ 18
- 5
lib/network/modules/InteractionHandler.js View File

@ -4,13 +4,15 @@ var NavigationHandler = require('./components/NavigationHandler').default;
var Popup = require('./../../shared/Popup').default;
/**
*
* @param {Object} body
* @param {Canvas} canvas
* @param {SelectionHandler} selectionHandler
* @constructor InteractionHandler
* @class InteractionHandler
*/
class InteractionHandler {
/**
* @param {Object} body
* @param {Canvas} canvas
* @param {SelectionHandler} selectionHandler
* @constructor InteractionHandler
*/
constructor(body, canvas, selectionHandler) {
this.body = body;
this.canvas = canvas;
@ -59,6 +61,9 @@ class InteractionHandler {
this.bindEventListeners()
}
/**
* Binds event listeners
*/
bindEventListeners() {
this.body.emitter.on('destroy', () => {
clearTimeout(this.popupTimer);
@ -66,6 +71,10 @@ class InteractionHandler {
})
}
/**
*
* @param {Object} options
*/
setOptions(options) {
if (options !== undefined) {
// extend all but the values in fields
@ -174,6 +183,10 @@ class InteractionHandler {
}
}
/**
*
* @param {Event} event
*/
onContext(event) {
let pointer = this.getPointer({x:event.clientX, y:event.clientY});
this.selectionHandler._generateClickEvent('oncontext', event, pointer);

+ 15
- 2
lib/network/modules/KamadaKawai.js View File

@ -9,8 +9,16 @@ import FloydWarshall from "./components/algorithms/FloydWarshall.js"
* -- Tomihisa KAMADA and Satoru KAWAI in 1989
*
* Possible optimizations in the distance calculation can be implemented.
*
* @class KamadaKawai
*/
class KamadaKawai {
/**
* @param {Object} body
* @param {Number} edgeLength
* @param {Number} edgeStrength
* @constructor KamadaKawai
*/
constructor(body, edgeLength, edgeStrength) {
this.body = body;
this.springLength = edgeLength;
@ -121,7 +129,7 @@ class KamadaKawai {
/**
* move the node based on it's energy
* the dx and dy are calculated from the linear system proposed by Kamada and Kawai
* @param {vis.Node.id} m
* @param {Number} m
* @param {Number} dE_dx
* @param {Number} dE_dy
* @private
@ -242,7 +250,12 @@ class KamadaKawai {
}
}
//Update method, just doing single column (rows are auto-updated) (update all sums)
/**
* Update method, just doing single column (rows are auto-updated) (update all sums)
*
* @param {Number} m
* @private
*/
_updateE_matrix(m) {
let nodesArray = this.body.nodeIndices;
let nodes = this.body.nodes;

+ 45
- 6
lib/network/modules/LayoutEngine.js View File

@ -37,10 +37,13 @@ var NetworkUtil = require('../NetworkUtil').default;
/**
* Container for derived data on current network, relating to hierarchy.
*
* Local, private class.
* @class HierarchicalStatus
* @private
*/
class HierarchicalStatus {
/**
* @constructor HierarchicalStatus
*/
constructor() {
this.childrenReference = {}; // child id's per node id
this.parentReference = {}; // parent id's per node id
@ -54,7 +57,6 @@ class HierarchicalStatus {
this.treeIndex = -1; // Highest tree id in current network.
}
/**
* Add the relation between given nodes to the current state.
*
@ -160,6 +162,11 @@ class HierarchicalStatus {
}
/**
*
* @param {Node} nodeA
* @param {Node} nodeB
*/
levelDownstream(nodeA, nodeB) {
if (this.levels[nodeB.id] === undefined) {
// set initial level
@ -309,11 +316,13 @@ class HierarchicalStatus {
}
/**
*
* @param {Object} body
* @constructor LayoutEngine
* @class LayoutEngine
*/
class LayoutEngine {
/**
* @param {Object} body
* @constructor LayoutEngine
*/
constructor(body) {
this.body = body;
@ -342,6 +351,9 @@ class LayoutEngine {
this.bindEventListeners();
}
/**
* Binds event listeners
*/
bindEventListeners() {
this.body.emitter.on('_dataChanged', () => {
this.setupHierarchicalLayout();
@ -364,6 +376,12 @@ class LayoutEngine {
});
}
/**
*
* @param {Object} options
* @param {Object} allOptions
* @returns {Object}
*/
setOptions(options, allOptions) {
if (options !== undefined) {
let hierarchical = this.options.hierarchical;
@ -406,6 +424,11 @@ class LayoutEngine {
return allOptions;
}
/**
*
* @param {Object} allOptions
* @returns {Object}
*/
adaptAllOptionsForHierarchicalLayout(allOptions) {
if (this.options.hierarchical.enabled === true) {
let backupPhysics = this.optionsBackup.physics;
@ -482,11 +505,19 @@ class LayoutEngine {
return allOptions;
}
/**
*
* @returns {number}
*/
seededRandom() {
let x = Math.sin(this.randomSeed++) * 10000;
return x - Math.floor(x);
}
/**
*
* @param {Array<Node>} nodesArray
*/
positionInitially(nodesArray) {
if (this.options.hierarchical.enabled !== true) {
this.randomSeed = this.initialRandomSeed;
@ -614,6 +645,10 @@ class LayoutEngine {
}
}
/**
* Expands all clusters
* @private
*/
_declusterAll() {
let clustersPresent = true;
while (clustersPresent === true) {
@ -630,6 +665,10 @@ class LayoutEngine {
}
}
/**
*
* @returns {number|*}
*/
getSeed() {
return this.initialRandomSeed;
}

+ 66
- 0
lib/network/modules/ManipulationSystem.js View File

@ -6,9 +6,15 @@ let hammerUtil = require('../../hammerUtil');
/**
* clears the toolbar div element of children
*
* @class ManipulationSystem
* @private
*/
class ManipulationSystem {
/**
* @param {Object} body
* @param {Canvas} canvas
* @param {SelectionHandler} selectionHandler
*/
constructor(body, canvas, selectionHandler) {
this.body = body;
this.canvas = canvas;
@ -114,6 +120,9 @@ class ManipulationSystem {
}
/**
* Enables Edit Mode
*/
enableEditMode() {
this.editMode = true;
@ -126,6 +135,9 @@ class ManipulationSystem {
}
}
/**
* Disables Edit Mode
*/
disableEditMode() {
this.editMode = false;
@ -675,30 +687,55 @@ class ManipulationSystem {
// ---------------------- DOM functions for buttons --------------------------//
/**
*
* @param {Locale} locale
* @private
*/
_createAddNodeButton(locale) {
let button = this._createButton('addNode', 'vis-button vis-add', locale['addNode'] || this.options.locales['en']['addNode']);
this.manipulationDiv.appendChild(button);
this._bindHammerToDiv(button, this.addNodeMode.bind(this));
}
/**
*
* @param {Locale} locale
* @private
*/
_createAddEdgeButton(locale) {
let button = this._createButton('addEdge', 'vis-button vis-connect', locale['addEdge'] || this.options.locales['en']['addEdge']);
this.manipulationDiv.appendChild(button);
this._bindHammerToDiv(button, this.addEdgeMode.bind(this));
}
/**
*
* @param {Locale} locale
* @private
*/
_createEditNodeButton(locale) {
let button = this._createButton('editNode', 'vis-button vis-edit', locale['editNode'] || this.options.locales['en']['editNode']);
this.manipulationDiv.appendChild(button);
this._bindHammerToDiv(button, this.editNode.bind(this));
}
/**
*
* @param {Locale} locale
* @private
*/
_createEditEdgeButton(locale) {
let button = this._createButton('editEdge', 'vis-button vis-edit', locale['editEdge'] || this.options.locales['en']['editEdge']);
this.manipulationDiv.appendChild(button);
this._bindHammerToDiv(button, this.editEdgeMode.bind(this));
}
/**
*
* @param {Locale} locale
* @private
*/
_createDeleteButton(locale) {
var deleteBtnClass;
if (this.options.rtl) {
@ -711,12 +748,26 @@ class ManipulationSystem {
this._bindHammerToDiv(button, this.deleteSelected.bind(this));
}
/**
*
* @param {Locale} locale
* @private
*/
_createBackButton(locale) {
let button = this._createButton('back', 'vis-button vis-back', locale['back'] || this.options.locales['en']['back']);
this.manipulationDiv.appendChild(button);
this._bindHammerToDiv(button, this.showManipulatorToolbar.bind(this));
}
/**
*
* @param {number|string} id
* @param {string} className
* @param {label} label
* @param {string} labelClassName
* @returns {HTMLElement}
* @private
*/
_createButton(id, className, label, labelClassName = 'vis-label') {
this.manipulationDOM[id+'Div'] = document.createElement('div');
@ -728,6 +779,11 @@ class ManipulationSystem {
return this.manipulationDOM[id+'Div'];
}
/**
*
* @param {Label} label
* @private
*/
_createDescription(label) {
this.manipulationDiv.appendChild(
this._createButton('description', 'vis-button vis-none', label)
@ -998,6 +1054,11 @@ class ManipulationSystem {
}
}
/**
*
* @param {Event} event
* @private
*/
_dragControlNode(event) {
let pointer = this.body.functions.getPointer(event.center);
if (this.temporaryIds.nodes[0] !== undefined) {
@ -1062,6 +1123,11 @@ class ManipulationSystem {
}
/**
*
* @param {Event} event
* @private
*/
_dragStartEdge(event) {
let pointer = this.lastTouch;
this.selectionHandler._generateClickEvent('dragStart', event, pointer, undefined, true);

+ 19
- 6
lib/network/modules/NodesHandler.js View File

@ -6,14 +6,16 @@ var Node = require("./components/Node").default;
var Label = require("./components/shared/Label").default;
/**
*
* @param {Object} body
* @param {Array<Image>} images
* @param {Array<Group>} groups
* @param {LayoutEngine} layoutEngine
* @constructor NodesHandler
* @class NodesHandler
*/
class NodesHandler {
/**
* @param {Object} body
* @param {Images} images
* @param {Array<Group>} groups
* @param {LayoutEngine} layoutEngine
* @constructor NodesHandler
*/
constructor(body, images, groups, layoutEngine) {
this.body = body;
this.images = images;
@ -148,6 +150,9 @@ class NodesHandler {
this.bindEventListeners();
}
/**
* Binds event listeners
*/
bindEventListeners() {
// refresh the nodes. Used when reverting from hierarchical layout
this.body.emitter.on('refreshNodes', this.refresh.bind(this));
@ -165,6 +170,10 @@ class NodesHandler {
});
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.nodeOptions = options;
if (options !== undefined) {
@ -355,6 +364,10 @@ class NodesHandler {
}
/**
*
* @param {boolean} [clearPositions=false]
*/
refresh(clearPositions = false) {
let nodes = this.body.nodes;
for (let nodeId in nodes) {

+ 13
- 3
lib/network/modules/PhysicsEngine.js View File

@ -11,11 +11,13 @@ var util = require('../../util');
/**
*
* @param {Object} body
* @constructor PhysicsEngine
* @class PhysicsEngine
*/
class PhysicsEngine {
/**
* @param {Object} body
* @constructor PhysicsEngine
*/
constructor(body) {
this.body = body;
this.physicsBody = {physicsNodeIndices:[], physicsEdgeIndices:[], forces: {}, velocities: {}};
@ -96,6 +98,9 @@ class PhysicsEngine {
this.bindEventListeners();
}
/**
* Binds event listeners
*/
bindEventListeners() {
this.body.emitter.on('initPhysics', () => {this.initPhysics();});
this.body.emitter.on('_layoutFailed', () => {this.layoutFailed = true;});
@ -716,6 +721,11 @@ class PhysicsEngine {
}
/**
* TODO: Is this function used at all? If not, remove it!
* @param {CanvasRenderingContext2D} ctx
* @private
*/
_drawForces(ctx) {
for (var i = 0; i < this.physicsBody.physicsNodeIndices.length; i++) {
let node = this.body.nodes[this.physicsBody.physicsNodeIndices[i]];

+ 25
- 4
lib/network/modules/SelectionHandler.js View File

@ -4,12 +4,14 @@ var Edge = require('./components/Edge').default;
let util = require('../../util');
/**
*
* @param {Object} body
* @param {Canvas} canvas
* @constructor SelectionHandler
* @class SelectionHandler
*/
class SelectionHandler {
/**
* @param {Object} body
* @param {Canvas} canvas
* @constructor SelectionHandler
*/
constructor(body, canvas) {
this.body = body;
this.canvas = canvas;
@ -31,6 +33,10 @@ class SelectionHandler {
}
/**
*
* @param {Object} [options]
*/
setOptions(options) {
if (options !== undefined) {
let fields = ['multiselect','hoverConnectedEdges','selectable','selectConnectedEdges'];
@ -61,6 +67,11 @@ class SelectionHandler {
return selected;
}
/**
*
* @param {{x: Number, y: Number}} pointer
* @returns {boolean}
*/
selectAdditionalOnPoint(pointer) {
let selectionChanged = false;
if (this.options.selectable === true) {
@ -134,6 +145,12 @@ class SelectionHandler {
this.body.emitter.emit(eventType, properties);
}
/**
*
* @param {Object} obj
* @param {boolean} [highlightEdges=this.options.selectConnectedEdges]
* @returns {boolean}
*/
selectObject(obj, highlightEdges = this.options.selectConnectedEdges) {
if (obj !== undefined) {
if (obj instanceof Node) {
@ -148,6 +165,10 @@ class SelectionHandler {
return false;
}
/**
*
* @param {Object} obj
*/
deselectObject(obj) {
if (obj.isSelected() === true) {
obj.selected = false;

+ 21
- 5
lib/network/modules/View.js View File

@ -3,12 +3,14 @@ let util = require('../../util');
var NetworkUtil = require('../NetworkUtil').default;
/**
*
* @param {Object} body
* @param {Canvas} canvas
* @constructor View
* @class View
*/
class View {
/**
* @param {Object} body
* @param {Canvas} canvas
* @constructor View
*/
constructor(body, canvas) {
this.body = body;
this.canvas = canvas;
@ -31,7 +33,10 @@ class View {
this.body.emitter.on("unlockNode", this.releaseNode.bind(this));
}
/**
*
* @param {Object} [options={}]
*/
setOptions(options = {}) {
this.options = options;
}
@ -236,6 +241,9 @@ class View {
this.body.view.translation = targetTranslation;
}
/**
* Resets state of a locked on Node
*/
releaseNode() {
if (this.lockedOnNodeId !== undefined && this.viewFunction !== undefined) {
this.body.emitter.off("initRedraw", this.viewFunction);
@ -273,10 +281,18 @@ class View {
}
/**
*
* @returns {number}
*/
getScale() {
return this.body.view.scale;
}
/**
*
* @returns {{x: number, y: number}}
*/
getViewPosition() {
return this.canvas.DOMtoCanvas({x: 0.5 * this.canvas.frame.canvas.clientWidth, y: 0.5 * this.canvas.frame.canvas.clientHeight});
}

+ 53
- 15
lib/network/modules/components/Edge.js View File

@ -8,19 +8,25 @@ var StraightEdge = require('./edges/StraightEdge').default;
/**
* A edge connects two nodes
* @param {Object} properties Object with options. Must contain
* At least options from and to.
* Available options: from (number),
* to (number), label (string, color (string),
* width (number), style (string),
* length (number), title (string)
* @param {Network} network A Network object, used to find and edge to
* nodes.
* @param {Object} constants An object with default values for
* example for the color
* @class Edge
*/
class Edge {
/**
*
* @param {Object} options Object with options. Must contain
* At least options from and to.
* Available options: from (number),
* to (number), label (string, color (string),
* width (number), style (string),
* length (number), title (string)
* @param {Object} body A Network object, used to find and edge to
* nodes.
* @param {Object} globalOptions An object with default values for
* example for the color
* @param {Object} defaultOptions
* @param {Object} edgeOptions
* @constructor Edge
*/
constructor(options, body, globalOptions, defaultOptions, edgeOptions) {
if (body === undefined) {
throw "No body provided";
@ -103,6 +109,13 @@ class Edge {
return dataChanged;
}
/**
*
* @param {Object} parentOptions
* @param {Object} newOptions
* @param {boolean} [allowDeletion=false]
* @param {Object} [globalOptions={}]
*/
static parseOptions(parentOptions, newOptions, allowDeletion = false, globalOptions = {}) {
var fields = [
'arrowStrikethrough',
@ -205,6 +218,10 @@ class Edge {
}
}
/**
*
* @param {Object} options
*/
choosify(options) {
this.chooser = true;
@ -221,6 +238,10 @@ class Edge {
}
}
/**
*
* @returns {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}}
*/
getFormattingValues() {
let toArrow = (this.options.arrows.to === true) || (this.options.arrows.to.enabled === true)
let fromArrow = (this.options.arrows.from === true) || (this.options.arrows.from.enabled === true)
@ -417,7 +438,6 @@ class Edge {
}
/**
* Retrieve the value of the edge. Can be undefined
* @return {Number} value
@ -453,6 +473,10 @@ class Edge {
this.updateLabelModule();
}
/**
*
* @private
*/
_setInteractionWidths() {
if (typeof this.options.hoverWidth === 'function') {
this.edgeType.hoverWidth = this.options.hoverWidth(this.options.width);
@ -510,7 +534,12 @@ class Edge {
this.drawLabel (ctx, viaNode);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Object} arrowData
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
drawArrows(ctx, arrowData, values) {
if (values.fromArrow) {
this.edgeType.drawArrowHead(ctx, values, this.selected, this.hover, arrowData.from);
@ -523,7 +552,11 @@ class Edge {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Node} viaNode
*/
drawLabel(ctx, viaNode) {
if (this.options.label !== undefined) {
// set style
@ -622,6 +655,7 @@ class Edge {
* @param {Number} percentage Value between 0 (line start) and 1 (line end)
* @return {Object} point
* @private
* @static
*/
_pointOnCircle(x, y, radius, percentage) {
var angle = percentage * 2 * Math.PI;
@ -631,12 +665,16 @@ class Edge {
}
}
/**
* Sets selected state to true
*/
select() {
this.selected = true;
}
/**
* Sets selected state to false
*/
unselect() {
this.selected = false;
}

+ 49
- 5
lib/network/modules/components/NavigationHandler.js View File

@ -3,12 +3,14 @@ var hammerUtil = require('../../../hammerUtil');
var keycharm = require('keycharm');
/**
*
* @param {Object} body
* @param {Canvas} canvas
* @constructor NavigationHandler
* @class NavigationHandler
*/
class NavigationHandler {
/**
* @param {Object} body
* @param {Canvas} canvas
* @constructor NavigationHandler
*/
constructor(body, canvas) {
this.body = body;
this.canvas = canvas;
@ -27,6 +29,10 @@ class NavigationHandler {
this.options = {}
}
/**
*
* @param {Object} options
*/
setOptions(options) {
if (options !== undefined) {
this.options = options;
@ -34,6 +40,9 @@ class NavigationHandler {
}
}
/**
* Creates or refreshes navigation and sets key bindings
*/
create() {
if (this.options.navigationButtons === true) {
if (this.iconsCreated === false) {
@ -47,6 +56,9 @@ class NavigationHandler {
this.configureKeyboardBindings();
}
/**
* Cleans up previous navigation items
*/
cleanNavigation() {
// clean hammer bindings
if (this.navigationHammers.length != 0) {
@ -108,6 +120,10 @@ class NavigationHandler {
this.iconsCreated = true;
}
/**
*
* @param {String} action
*/
bindToRedraw(action) {
if (this.boundFunctions[action] === undefined) {
this.boundFunctions[action] = this[action].bind(this);
@ -116,6 +132,10 @@ class NavigationHandler {
}
}
/**
*
* @param {String} action
*/
unbindFromRedraw(action) {
if (this.boundFunctions[action] !== undefined) {
this.body.emitter.off("initRedraw", this.boundFunctions[action]);
@ -150,11 +170,30 @@ class NavigationHandler {
}
this.boundFunctions = {};
}
/**
*
* @private
*/
_moveUp() {this.body.view.translation.y += this.options.keyboard.speed.y;}
/**
*
* @private
*/
_moveDown() {this.body.view.translation.y -= this.options.keyboard.speed.y;}
/**
*
* @private
*/
_moveLeft() {this.body.view.translation.x += this.options.keyboard.speed.x;}
/**
*
* @private
*/
_moveRight(){this.body.view.translation.x -= this.options.keyboard.speed.x;}
/**
*
* @private
*/
_zoomIn() {
var scaleOld = this.body.view.scale;
var scale = this.body.view.scale * (1 + this.options.keyboard.speed.zoom);
@ -168,6 +207,11 @@ class NavigationHandler {
this.body.emitter.emit('zoom', { direction: '+', scale: this.body.view.scale, pointer: null });
}
/**
*
* @private
*/
_zoomOut() {
var scaleOld = this.body.view.scale;
var scale = this.body.view.scale / (1 + this.options.keyboard.speed.zoom);

+ 42
- 21
lib/network/modules/components/Node.js View File

@ -21,29 +21,34 @@ var { printStyle } = require("../../../shared/Validator");
/**
* A node. A node can be connected to other nodes via one or multiple edges.
* @param {object} options An object containing options for the node. All
* options are optional, except for the id.
* {number} id Id of the node. Required
* {string} label Text label for the node
* {number} x Horizontal position of the node
* {number} y Vertical position of the node
* {string} shape Node shape, available:
* "database", "circle", "ellipse",
* "box", "image", "text", "dot",
* "star", "triangle", "triangleDown",
* "square", "icon"
* {string} image An image url
* {string} title An title text, can be HTML
* {anytype} group A group name or number
* @param {Network.Images} imagelist A list with images. Only needed
* when the node has an image
* @param {Network.Groups} grouplist A list with groups. Needed for
* retrieving group options
* @param {Object} constants An object with default values for
* example for the color
* @class Node
*/
class Node {
/**
*
* @param {object} options An object containing options for the node. All
* options are optional, except for the id.
* {number} id Id of the node. Required
* {string} label Text label for the node
* {number} x Horizontal position of the node
* {number} y Vertical position of the node
* {string} shape Node shape, available:
* "database", "circle", "ellipse",
* "box", "image", "text", "dot",
* "star", "triangle", "triangleDown",
* "square", "icon"
* {string} image An image url
* {string} title An title text, can be HTML
* {anytype} group A group name or number
* @param {Object} body
* @param {Network.Images} imagelist A list with images. Only needed
* when the node has an image
* @param {Groups} grouplist A list with groups. Needed for
* retrieving group options
* @param {Object} globalOptions An object with default values for
* example for the color
* @param {Object} defaultOptions
* @param {Object} nodeOptions
*/
constructor(options, body, imagelist, grouplist, globalOptions, defaultOptions, nodeOptions) {
this.options = util.bridgeObject(globalOptions);
this.globalOptions = globalOptions;
@ -254,6 +259,10 @@ class Node {
}
}
/**
*
* @param {Object} options
*/
choosify(options) {
this.chooser = true;
@ -270,6 +279,10 @@ class Node {
}
}
/**
*
* @returns {{color: *, borderWidth: *, borderColor: *, size: *, borderDashes: (boolean|Array|allOptions.nodes.shapeProperties.borderDashes|{boolean, array}), borderRadius: (number|allOptions.nodes.shapeProperties.borderRadius|{number}|Array), shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *}}
*/
getFormattingValues() {
let values = {
color: this.options.color.background,
@ -314,6 +327,10 @@ class Node {
}
/**
*
* @param {Object} options
*/
updateLabelModule(options) {
if (this.options.label === undefined || this.options.label === null) {
this.options.label = '';
@ -326,6 +343,10 @@ class Node {
this.labelModule.choosify(this.nodeOptions, options, this.defaultOptions);
}
/**
*
* @param {string} currentShape
*/
updateShape(currentShape) {
if (currentShape === this.options.shape && this.shape) {
this.shape.setOptions(this.options, this.imageObj, this.imageObjAlt);

+ 12
- 1
lib/network/modules/components/algorithms/FloydWarshall.js View File

@ -1,10 +1,21 @@
/**
* @constructor FloydWarshall
* @class FloydWarshall
*/
class FloydWarshall {
/**
* @constructor FloydWarshall
*/
constructor() {
}
/**
*
* @param {Object} body
* @param {Array<Node>} nodesArray
* @param {Array<Edge>} edgesArray
* @returns {{}}
* @static
*/
getDistances(body, nodesArray, edgesArray) {
let D_matrix = {};
let edges = body.edges;

+ 22
- 5
lib/network/modules/components/edges/BezierEdgeDynamic.js View File

@ -5,13 +5,16 @@ import BezierEdgeBase from './util/BezierEdgeBase'
* curves in paths between nodes. The Dynamic piece refers to how the curve
* reacts to physics changes.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor BezierEdgeDynamic
* @class BezierEdgeDynamic
* @extends BezierEdgeBase
*/
class BezierEdgeDynamic extends BezierEdgeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor BezierEdgeDynamic
*/
constructor(options, body, labelModule) {
//this.via = undefined; // Here for completeness but not allowed to defined before super() is invoked.
super(options, body, labelModule); // --> this calls the setOptions below
@ -19,6 +22,10 @@ class BezierEdgeDynamic extends BezierEdgeBase {
this.body.emitter.on("_repositionBezierNodes", this._boundFunction);
}
/**
*
* @param {Object} options
*/
setOptions(options) {
// check if the physics has changed.
let physicsChange = false;
@ -43,6 +50,9 @@ class BezierEdgeDynamic extends BezierEdgeBase {
}
}
/**
* Connects an edge to node(s)
*/
connect() {
this.from = this.body.nodes[this.options.from];
this.to = this.body.nodes[this.options.to];
@ -97,6 +107,9 @@ class BezierEdgeDynamic extends BezierEdgeBase {
}
}
/**
* Positions bezier node
*/
positionBezierNode() {
if (this.via !== undefined && this.from !== undefined && this.to !== undefined) {
this.via.x = 0.5 * (this.from.x + this.to.x);
@ -111,7 +124,7 @@ class BezierEdgeDynamic extends BezierEdgeBase {
/**
* Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx
* @param {Array<Object>} values
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {vis.Node} viaNode
* @private
*/
@ -119,6 +132,10 @@ class BezierEdgeDynamic extends BezierEdgeBase {
this._bezierCurve(ctx, values, viaNode);
}
/**
*
* @returns {Node|undefined|*|{index, line, column}}
*/
getViaNode() {
return this.via;
}

+ 12
- 5
lib/network/modules/components/edges/BezierEdgeStatic.js View File

@ -4,13 +4,16 @@ import BezierEdgeBase from './util/BezierEdgeBase'
* A Static Bezier Edge. Bezier curves are used to model smooth gradual
* curves in paths between nodes.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor BezierEdgeStatic
* @class BezierEdgeStatic
* @extends BezierEdgeBase
*/
class BezierEdgeStatic extends BezierEdgeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor BezierEdgeStatic
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
}
@ -18,7 +21,7 @@ class BezierEdgeStatic extends BezierEdgeBase {
/**
* Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx
* @param {Array<Object>} values
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {vis.Node} viaNode
* @private
*/
@ -26,6 +29,10 @@ class BezierEdgeStatic extends BezierEdgeBase {
this._bezierCurve(ctx, values, viaNode);
}
/**
*
* @returns {Array<{x: number, y: number}>}
*/
getViaNode() {
return this._getViaCoordinates();
}

+ 37
- 5
lib/network/modules/components/edges/CubicBezierEdge.js View File

@ -4,13 +4,16 @@ import CubicBezierEdgeBase from './util/CubicBezierEdgeBase'
* A Cubic Bezier Edge. Bezier curves are used to model smooth gradual
* curves in paths between nodes.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor CubicBezierEdge
* @class CubicBezierEdge
* @extends CubicBezierEdgeBase
*/
class CubicBezierEdge extends CubicBezierEdgeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor CubicBezierEdge
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
}
@ -18,7 +21,7 @@ class CubicBezierEdge extends CubicBezierEdgeBase {
/**
* Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx
* @param {Array<Object>} values
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {Array<vis.Node>} viaNodes
* @private
*/
@ -29,6 +32,11 @@ class CubicBezierEdge extends CubicBezierEdgeBase {
this._bezierCurve(ctx, values, via1, via2);
}
/**
*
* @returns {Array<{x: number, y: number}>}
* @private
*/
_getViaCoordinates() {
let dx = this.from.x - this.to.x;
let dy = this.from.y - this.to.y;
@ -53,14 +61,38 @@ class CubicBezierEdge extends CubicBezierEdgeBase {
return [{x: x1, y: y1},{x: x2, y: y2}];
}
/**
*
* @returns {Array<{x: number, y: number}>}
*/
getViaNode() {
return this._getViaCoordinates();
}
/**
*
* @param {Node} nearNode
* @param {CanvasRenderingContext2D} ctx
* @returns {{x: number, y: number, t: number}}
* @private
*/
_findBorderPosition(nearNode, ctx) {
return this._findBorderPositionBezier(nearNode, ctx);
}
/**
*
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @param {number} x3
* @param {number} y3
* @param {Node} via1
* @param {Node} via2
* @returns {number}
* @private
*/
_getDistanceToEdge(x1, y1, x2, y2, x3, y3, [via1, via2] = this._getViaCoordinates()) { // x3,y3 is the point
return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via1, via2);
}

+ 31
- 5
lib/network/modules/components/edges/StraightEdge.js View File

@ -3,13 +3,16 @@ import EdgeBase from './util/EdgeBase'
/**
* A Straight Edge.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor StraightEdge
* @class StraightEdge
* @extends EdgeBase
*/
class StraightEdge extends EdgeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor StraightEdge
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
}
@ -17,7 +20,7 @@ class StraightEdge extends EdgeBase {
/**
* Draw a line between two nodes
* @param {CanvasRenderingContext2D} ctx
* @param {Array<Object>} values
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @private
*/
_line(ctx, values) {
@ -31,6 +34,11 @@ class StraightEdge extends EdgeBase {
this.disableShadow(ctx, values);
}
/**
*
* @returns {undefined}
* @static
*/
getViaNode() {
return undefined;
}
@ -49,6 +57,13 @@ class StraightEdge extends EdgeBase {
}
}
/**
*
* @param {Node} nearNode
* @param {CanvasRenderingContext2D} ctx
* @returns {{x: number, y: number}}
* @private
*/
_findBorderPosition(nearNode, ctx) {
let node1 = this.to;
let node2 = this.from;
@ -71,6 +86,17 @@ class StraightEdge extends EdgeBase {
return borderPos;
}
/**
*
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @param {number} x3
* @param {number} y3
* @returns {number}
* @private
*/
_getDistanceToEdge(x1, y1, x2, y2, x3, y3) { // x3,y3 is the point
return this._getDistanceToLine(x1, y1, x2, y2, x3, y3);
}

+ 11
- 5
lib/network/modules/components/edges/util/BezierEdgeBase.js View File

@ -4,13 +4,16 @@ import EdgeBase from './EdgeBase'
* The Base Class for all Bezier edges. Bezier curves are used to model smooth
* gradual curves in paths between nodes.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor BezierEdgeBase
* @class BezierEdgeBase
* @extends EdgeBase
*/
class BezierEdgeBase extends EdgeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor BezierEdgeBase
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
}
@ -146,7 +149,10 @@ class BezierEdgeBase extends EdgeBase {
this.disableShadow(ctx, values);
}
/**
*
* @returns {*|{x, y}|{x: undefined, y: undefined}}
*/
getViaNode() {
return this._getViaCoordinates();
}

+ 7
- 4
lib/network/modules/components/edges/util/CubicBezierEdgeBase.js View File

@ -4,13 +4,16 @@ import BezierEdgeBase from './BezierEdgeBase'
* A Base Class for all Cubic Bezier Edges. Bezier curves are used to model
* smooth gradual curves in paths between nodes.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor CubicBezierEdgeBase
* @class CubicBezierEdgeBase
* @extends BezierEdgeBase
*/
class CubicBezierEdgeBase extends BezierEdgeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor CubicBezierEdgeBase
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
}

+ 88
- 7
lib/network/modules/components/edges/util/EdgeBase.js View File

@ -3,12 +3,15 @@ let util = require("../../../../../util");
/**
* The Base Class for all edges.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor EdgeBase
* @class EdgeBase
*/
class EdgeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor EdgeBase
*/
constructor(options, body, labelModule) {
this.body = body;
this.labelModule = labelModule;
@ -22,15 +25,26 @@ class EdgeBase {
this.toPoint = this.to;
}
/**
* Connects a node to itself
*/
connect() {
this.from = this.body.nodes[this.options.from];
this.to = this.body.nodes[this.options.to];
}
/**
*
* @returns {boolean} always false
*/
cleanup() {
return false;
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.options = options;
this.from = this.body.nodes[this.options.from];
@ -64,6 +78,15 @@ class EdgeBase {
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Array} values
* @param {vis.Node} viaNode
* @param {{x: Number, y: Number}} [fromPoint]
* @param {{x: Number, y: Number}} [toPoint]
* @private
*/
_drawLine(ctx, values, viaNode, fromPoint, toPoint) {
if (this.from != this.to) {
// draw line
@ -75,6 +98,15 @@ class EdgeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Array} values
* @param {vis.Node} viaNode
* @param {{x: Number, y: Number}} [fromPoint] TODO: Remove in next major release
* @param {{x: Number, y: Number}} [toPoint] TODO: Remove in next major release
* @private
*/
_drawDashedLine(ctx, values, viaNode, fromPoint, toPoint) { // eslint-disable-line no-unused-vars
ctx.lineCap = 'round';
let pattern = [5,5];
@ -125,6 +157,13 @@ class EdgeBase {
}
/**
*
* @param {Node} nearNode
* @param {CanvasRenderingContext2D} ctx
* @param {Object} options
* @returns {{x: Number, y: Number}}
*/
findBorderPosition(nearNode, ctx, options) {
if (this.from != this.to) {
return this._findBorderPosition(nearNode, ctx, options);
@ -134,6 +173,11 @@ class EdgeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @returns {{from: ({x: number, y: number, t: number}|*), to: ({x: number, y: number, t: number}|*)}}
*/
findBorderPositions(ctx) {
let from = {};
let to = {};
@ -150,6 +194,12 @@ class EdgeBase {
return {from, to};
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @returns {Array<Number>} x, y, radius
* @private
*/
_getCircleData(ctx) {
let x, y;
let node = this.from;
@ -252,7 +302,7 @@ class EdgeBase {
* connected nodes is selected.
* @param {boolean} selected
* @param {boolean} hover
* @return {Number} width
* @returns {Number} width
* @private
*/
getLineWidth(selected, hover) {
@ -269,7 +319,14 @@ class EdgeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {boolean} selected - Unused
* @param {boolean} hover - Unused
* @returns {string}
*/
getColor(ctx, values, selected, hover) { // eslint-disable-line no-unused-vars
if (values.inheritsColor !== false) {
// when this is a loop edge, just use the 'from' method
@ -369,6 +426,18 @@ class EdgeBase {
}
}
/**
*
* @param {number} x1
* @param {number} y1
* @param {number} x2
* @param {number} y2
* @param {number} x3
* @param {number} y3
* @returns {number}
* @private
* @static
*/
_getDistanceToLine(x1, y1, x2, y2, x3, y3) {
let px = x2 - x1;
let py = y2 - y1;
@ -482,7 +551,7 @@ class EdgeBase {
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Array<Object>} values
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @param {boolean} selected
* @param {boolean} hover
* @param {Object} arrowData
@ -509,6 +578,12 @@ class EdgeBase {
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @static
*/
enableShadow(ctx, values) {
if (values.shadow === true) {
ctx.shadowColor = values.shadowColor;
@ -518,6 +593,12 @@ class EdgeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @static
*/
disableShadow(ctx, values) {
if (values.shadow === true) {
ctx.shadowColor = 'rgba(0,0,0,0)';

+ 9
- 6
lib/network/modules/components/nodes/Cluster.js View File

@ -4,15 +4,18 @@ import Node from '../Node'
* A Cluster is a special Node that allows a group of Nodes positioned closely together
* to be represented by a single Cluster Node.
*
* @param {Object} options
* @param {Object} body
* @param {Array<HTMLImageElement>}imagelist
* @param {Array} grouplist
* @param {Object} globalOptions
* @constructor Cluster
* @class Cluster
* @extends Node
*/
class Cluster extends Node {
/**
* @param {Object} options
* @param {Object} body
* @param {Array<HTMLImageElement>}imagelist
* @param {Array} grouplist
* @param {Object} globalOptions
* @constructor Cluster
*/
constructor(options, body, imagelist, grouplist, globalOptions) {
super(options, body, imagelist, grouplist, globalOptions);

+ 36
- 4
lib/network/modules/components/nodes/shapes/Box.js View File

@ -5,18 +5,27 @@ import NodeBase from '../util/NodeBase'
/**
* A Box Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Box
* @class Box
* @extends NodeBase
*/
class Box extends NodeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Box
*/
constructor (options, body, labelModule) {
super(options,body,labelModule);
this._setMargins(labelModule);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {boolean} [selected]
* @param {boolean} [hover]
*/
resize(ctx, selected = this.selected, hover = this.hover) {
if (this.needsRefresh(selected, hover)) {
this.textSize = this.labelModule.getTextSize(ctx, selected, hover);
@ -26,6 +35,15 @@ class Box extends NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);
this.left = x - this.width / 2;
@ -40,6 +58,14 @@ class Box extends NodeBase {
this.top + this.textSize.height / 2 + this.margin.top, selected, hover);
}
/**
*
* @param {number} x width
* @param {number} y height
* @param {CanvasRenderingContext2D} ctx
* @param {boolean} selected
* @param {boolean} hover
*/
updateBoundingBox(x, y, ctx, selected, hover) {
this._updateBoundingBox(x, y, ctx, selected, hover);
@ -47,6 +73,12 @@ class Box extends NodeBase {
this._addBoundingBoxMargin(borderRadius);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} angle
* @returns {number}
*/
distanceToBorder(ctx, angle) {
this.resize(ctx);
let borderWidth = this.options.borderWidth;

+ 34
- 5
lib/network/modules/components/nodes/shapes/Circle.js View File

@ -5,18 +5,27 @@ import CircleImageBase from '../util/CircleImageBase'
/**
* A Circle Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Circle
* @class Circle
* @extends CircleImageBase
*/
class Circle extends CircleImageBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Circle
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
this._setMargins(labelModule);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {boolean} [selected]
* @param {boolean} [hover]
*/
resize(ctx, selected = this.selected, hover = this.hover) {
if (this.needsRefresh(selected, hover)) {
this.textSize = this.labelModule.getTextSize(ctx, selected, hover);
@ -30,6 +39,15 @@ class Circle extends CircleImageBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);
this.left = x - this.width / 2;
@ -42,13 +60,24 @@ class Circle extends CircleImageBase {
y, selected, hover);
}
updateBoundingBox(x,y) {
/**
*
* @param {number} x width
* @param {number} y height
*/
updateBoundingBox(x, y) {
this.boundingBox.top = y - this.options.size;
this.boundingBox.left = x - this.options.size;
this.boundingBox.right = x + this.options.size;
this.boundingBox.bottom = y + this.options.size;
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} angle - Unused
* @returns {number}
*/
distanceToBorder(ctx, angle) { // eslint-disable-line no-unused-vars
this.resize(ctx);
return this.width * 0.5;

+ 35
- 4
lib/network/modules/components/nodes/shapes/CircularImage.js View File

@ -5,19 +5,30 @@ import CircleImageBase from '../util/CircleImageBase'
/**
* A CircularImage Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor CircularImage
* @class CircularImage
* @extends CircleImageBase
*/
class CircularImage extends CircleImageBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @param {Image} imageObj
* @param {Image} imageObjAlt
* @constructor CircularImage
*/
constructor (options, body, labelModule, imageObj, imageObjAlt) {
super(options, body, labelModule);
this.setImages(imageObj, imageObjAlt);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {boolean} [selected]
* @param {boolean} [hover]
*/
resize(ctx, selected = this.selected, hover = this.hover) {
var imageAbsent = (this.imageObj.src === undefined) ||
(this.imageObj.width === undefined) ||
@ -37,6 +48,15 @@ class CircularImage extends CircleImageBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this.switchImages(selected);
this.resize();
@ -61,6 +81,11 @@ class CircularImage extends CircleImageBase {
}
// TODO: compare with Circle.updateBoundingBox(), consolidate? More stuff is happening here
/**
*
* @param {number} x width
* @param {number} y height
*/
updateBoundingBox(x,y) {
this.boundingBox.top = y - this.options.size;
this.boundingBox.left = x - this.options.size;
@ -74,6 +99,12 @@ class CircularImage extends CircleImageBase {
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} angle - Unused
* @returns {Number}
*/
distanceToBorder(ctx, angle) { // eslint-disable-line no-unused-vars
this.resize(ctx);
return this.width * 0.5;

+ 29
- 6
lib/network/modules/components/nodes/shapes/Database.js View File

@ -5,18 +5,27 @@ import NodeBase from '../util/NodeBase'
/**
* A Database Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Database
* @class Database
* @extends NodeBase
*/
class Database extends NodeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Database
*/
constructor (options, body, labelModule) {
super(options, body, labelModule);
this._setMargins(labelModule);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {boolean} selected
* @param {boolean} hover
*/
resize(ctx, selected, hover) {
if (this.needsRefresh(selected, hover)) {
this.textSize = this.labelModule.getTextSize(ctx, selected, hover);
@ -27,6 +36,15 @@ class Database extends NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);
this.left = x - this.width / 2;
@ -40,9 +58,14 @@ class Database extends NodeBase {
this.labelModule.draw(ctx, this.left + this.textSize.width / 2 + this.margin.left,
this.top + this.textSize.height / 2 + this.margin.top, selected, hover);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} angle
* @returns {number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
return this._distanceToBorder(ctx, angle);
}
}

+ 22
- 4
lib/network/modules/components/nodes/shapes/Diamond.js View File

@ -5,21 +5,39 @@ import ShapeBase from '../util/ShapeBase'
/**
* A Diamond Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Diamond
* @class Diamond
* @extends ShapeBase
*/
class Diamond extends ShapeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Diamond
*/
constructor(options, body, labelModule) {
super(options, body, labelModule)
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'diamond', 4, x, y, selected, hover, values);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
}

+ 22
- 4
lib/network/modules/components/nodes/shapes/Dot.js View File

@ -5,21 +5,39 @@ import ShapeBase from '../util/ShapeBase'
/**
* A Dot Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Dot
* @class Dot
* @extends ShapeBase
*/
class Dot extends ShapeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Dot
*/
constructor(options, body, labelModule) {
super(options, body, labelModule)
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'circle', 2, x, y, selected, hover, values);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) { // eslint-disable-line no-unused-vars
this.resize(ctx);
return this.options.size;

+ 28
- 5
lib/network/modules/components/nodes/shapes/Ellipse.js View File

@ -5,17 +5,26 @@ import NodeBase from '../util/NodeBase'
/**
* Am Ellipse Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Ellipse
* @class Ellipse
* @extends NodeBase
*/
class Ellipse extends NodeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Ellipse
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
}
/**
*
* @param {CanvasRenderingContext2D} ctx - Unused.
* @param {Boolean} [selected]
* @param {Boolean} [hover]
*/
resize(ctx, selected = this.selected, hover = this.hover) {
if (this.needsRefresh(selected, hover)) {
var textSize = this.labelModule.getTextSize(ctx, selected, hover);
@ -26,6 +35,15 @@ class Ellipse extends NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);
this.left = x - this.width * 0.5;
@ -39,7 +57,12 @@ class Ellipse extends NodeBase {
this.labelModule.draw(ctx, x, y, selected, hover);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
this.resize(ctx);
var a = this.width * 0.5;

+ 42
- 4
lib/network/modules/components/nodes/shapes/Icon.js View File

@ -5,18 +5,27 @@ import NodeBase from '../util/NodeBase'
/**
* An icon replacement for the default Node shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Icon
* @class Icon
* @extends NodeBase
*/
class Icon extends NodeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Icon
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
this._setMargins(labelModule);
}
/**
*
* @param {CanvasRenderingContext2D} ctx - Unused.
* @param {Boolean} [selected]
* @param {Boolean} [hover]
*/
resize(ctx, selected, hover) {
if (this.needsRefresh(selected, hover)) {
this.iconSize = {
@ -29,6 +38,15 @@ class Icon extends NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);
this.options.icon.size = this.options.icon.size || 50;
@ -46,6 +64,11 @@ class Icon extends NodeBase {
this.updateBoundingBox(x, y)
}
/**
*
* @param {Number} x
* @param {Number} y
*/
updateBoundingBox(x, y) {
this.boundingBox.top = y - this.options.icon.size * 0.5;
this.boundingBox.left = x - this.options.icon.size * 0.5;
@ -60,6 +83,15 @@ class Icon extends NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover - Unused
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
_icon(ctx, x, y, selected, hover, values) {
let iconSize = Number(this.options.icon.size);
@ -83,6 +115,12 @@ class Icon extends NodeBase {
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
}

+ 36
- 5
lib/network/modules/components/nodes/shapes/Image.js View File

@ -6,19 +6,30 @@ import CircleImageBase from '../util/CircleImageBase'
/**
* An image-based replacement for the default Node shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Image
* @class Image
* @extends CircleImageBase
*/
class Image extends CircleImageBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @param {Image} imageObj
* @param {Image} imageObjAlt
* @constructor Image
*/
constructor (options, body, labelModule, imageObj, imageObjAlt) {
super(options, body, labelModule);
this.setImages(imageObj, imageObjAlt);
}
/**
*
* @param {CanvasRenderingContext2D} ctx - Unused.
* @param {Boolean} [selected]
* @param {Boolean} [hover]
*/
resize(ctx, selected = this.selected, hover = this.hover) {
var imageAbsent = (this.imageObj.src === undefined) ||
(this.imageObj.width === undefined) ||
@ -36,6 +47,15 @@ class Image extends CircleImageBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this.switchImages(selected);
this.resize();
@ -75,7 +95,12 @@ class Image extends CircleImageBase {
this.updateBoundingBox(x,y);
}
updateBoundingBox(x,y) {
/**
*
* @param {Number} x
* @param {Number} y
*/
updateBoundingBox(x, y) {
this.resize();
this._updateBoundingBox(x, y);
@ -86,6 +111,12 @@ class Image extends CircleImageBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
}

+ 22
- 4
lib/network/modules/components/nodes/shapes/Square.js View File

@ -5,21 +5,39 @@ import ShapeBase from '../util/ShapeBase'
/**
* A Square Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Square
* @class Square
* @extends ShapeBase
*/
class Square extends ShapeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Square
*/
constructor(options, body, labelModule) {
super(options, body, labelModule)
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'square', 2, x, y, selected, hover, values);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
}

+ 22
- 4
lib/network/modules/components/nodes/shapes/Star.js View File

@ -5,21 +5,39 @@ import ShapeBase from '../util/ShapeBase'
/**
* A Star Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor TriangleDown
* @class TriangleDown
* @extends ShapeBase
*/
class Star extends ShapeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor TriangleDown
*/
constructor(options, body, labelModule) {
super(options, body, labelModule)
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'star', 4, x, y, selected, hover, values);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
}

+ 28
- 4
lib/network/modules/components/nodes/shapes/Text.js View File

@ -5,18 +5,27 @@ import NodeBase from '../util/NodeBase'
/**
* A text-based replacement for the default Node shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Text
* @class Text
* @extends NodeBase
*/
class Text extends NodeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Text
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
this._setMargins(labelModule);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {boolean} selected
* @param {boolean} hover
*/
resize(ctx, selected, hover) {
if (this.needsRefresh(selected, hover)) {
this.textSize = this.labelModule.getTextSize(ctx, selected, hover);
@ -26,6 +35,15 @@ class Text extends NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this.resize(ctx, selected, hover);
this.left = x - this.width / 2;
@ -42,6 +60,12 @@ class Text extends NodeBase {
this.updateBoundingBox(x, y, ctx, selected, hover);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
}

+ 22
- 4
lib/network/modules/components/nodes/shapes/Triangle.js View File

@ -5,21 +5,39 @@ import ShapeBase from '../util/ShapeBase'
/**
* A Triangle Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Triangle
* @class Triangle
* @extends ShapeBase
*/
class Triangle extends ShapeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor Triangle
*/
constructor(options, body, labelModule) {
super(options, body, labelModule)
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} x
* @param {Number} y
* @param {Boolean} selected
* @param {Boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'triangle', 3, x, y, selected, hover, values);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
}

+ 22
- 4
lib/network/modules/components/nodes/shapes/TriangleDown.js View File

@ -5,21 +5,39 @@ import ShapeBase from '../util/ShapeBase'
/**
* A downward facing Triangle Node/Cluster shape.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor TriangleDown
* @class TriangleDown
* @extends ShapeBase
*/
class TriangleDown extends ShapeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor TriangleDown
*/
constructor(options, body, labelModule) {
super(options, body, labelModule)
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} x
* @param {Number} y
* @param {Boolean} selected
* @param {Boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
draw(ctx, x, y, selected, hover, values) {
this._drawShape(ctx, 'triangleDown', 3, x, y, selected, hover, values);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
*/
distanceToBorder(ctx, angle) {
return this._distanceToBorder(ctx,angle);
}

+ 40
- 1
lib/network/modules/components/nodes/util/CircleImageBase.js View File

@ -12,14 +12,30 @@ import NodeBase from './NodeBase';
* TODO: Refactor, move _drawRawCircle to different module, derive Circle from NodeBase
* Rename this to ImageBase
* Consolidate common code in Image and CircleImage to base class
*
* @class CircleImageBase
* @extends NodeBase
*/
class CircleImageBase extends NodeBase {
/**
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor CircleImageBase
*/
constructor(options, body, labelModule) {
super(options, body, labelModule);
this.labelOffset = 0;
this.selected = false;
}
/**
*
* @param {Object} options
* @param {Object} [imageObj]
* @param {Object} [imageObjAlt]
*/
setOptions(options, imageObj, imageObjAlt) {
this.options = options;
@ -56,7 +72,7 @@ class CircleImageBase extends NodeBase {
*
* Do the switch only if imageObjAlt exists.
*
* @param {true|false} selected value of new selected state for current node
* @param {Boolean} selected value of new selected state for current node
*/
switchImages(selected) {
var selection_changed = ((selected && !this.selected) || (!selected && this.selected));
@ -106,12 +122,26 @@ class CircleImageBase extends NodeBase {
this.radius = 0.5 * this.width;
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @private
*/
_drawRawCircle(ctx, x, y, values) {
this.initContextForDraw(ctx, values);
ctx.circle(x, y, values.size);
this.performFill(ctx, values);
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @private
*/
_drawImageAtPosition(ctx, values) {
if (this.imageObj.width != 0) {
// draw the image
@ -132,6 +162,15 @@ class CircleImageBase extends NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {number} x width
* @param {number} y height
* @param {boolean} selected
* @param {boolean} hover
* @private
*/
_drawImageLabel(ctx, x, y, selected, hover) {
var yLabel;
var offset = 0;

+ 63
- 8
lib/network/modules/components/nodes/util/NodeBase.js View File

@ -1,12 +1,15 @@
/**
* The Base class for all Nodes.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor NodeBase
* @class NodeBase
*/
class NodeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor NodeBase
*/
constructor(options, body, labelModule) {
this.body = body;
this.labelModule = labelModule;
@ -21,10 +24,19 @@ class NodeBase {
this.boundingBox = {top: 0, left: 0, right: 0, bottom: 0};
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.options = options;
}
/**
*
* @param {Label} labelModule
* @private
*/
_setMargins(labelModule) {
this.margin = {};
if (this.options.margin) {
@ -43,6 +55,13 @@ class NodeBase {
labelModule.adjustSizes(this.margin)
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Number} angle
* @returns {Number}
* @private
*/
_distanceToBorder(ctx,angle) {
var borderWidth = this.options.borderWidth;
this.resize(ctx);
@ -51,6 +70,11 @@ class NodeBase {
Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth;
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
enableShadow(ctx, values) {
if (values.shadow) {
ctx.shadowColor = values.shadowColor;
@ -60,6 +84,11 @@ class NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
disableShadow(ctx, values) {
if (values.shadow) {
ctx.shadowColor = 'rgba(0,0,0,0)';
@ -69,6 +98,11 @@ class NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
enableBorderDashes(ctx, values) {
if (values.borderDashes !== false) {
if (ctx.setLineDash !== undefined) {
@ -86,6 +120,11 @@ class NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
disableBorderDashes(ctx, values) {
if (values.borderDashes !== false) {
if (ctx.setLineDash !== undefined) {
@ -99,7 +138,6 @@ class NodeBase {
}
}
/**
* Determine if the shape of a node needs to be recalculated.
*
@ -119,7 +157,11 @@ class NodeBase {
return (this.width === undefined) || (this.labelModule.differentState(selected, hover));
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
initContextForDraw(ctx, values) {
var borderWidth = values.borderWidth / this.body.view.scale;
@ -128,7 +170,11 @@ class NodeBase {
ctx.fillStyle = values.color;
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
performStroke(ctx, values) {
var borderWidth = values.borderWidth / this.body.view.scale;
@ -145,7 +191,11 @@ class NodeBase {
ctx.restore();
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
*/
performFill(ctx, values) {
// draw shadow if enabled
this.enableShadow(ctx, values);
@ -158,6 +208,11 @@ class NodeBase {
}
/**
*
* @param {Number} margin
* @private
*/
_addBoundingBoxMargin(margin) {
this.boundingBox.left -= margin;
this.boundingBox.top -= margin;

+ 32
- 5
lib/network/modules/components/nodes/util/ShapeBase.js View File

@ -3,17 +3,27 @@ import NodeBase from '../util/NodeBase'
/**
* Base class for constructing Node/Cluster Shapes.
*
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor ShapeBase
* @class ShapeBase
* @extends NodeBase
*/
class ShapeBase extends NodeBase {
/**
* @param {Object} options
* @param {Object} body
* @param {Label} labelModule
* @constructor ShapeBase
*/
constructor(options, body, labelModule) {
super(options, body, labelModule)
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {Boolean} [selected]
* @param {Boolean} [hover]
* @param {Object} [values={size: this.options.size}]
*/
resize(ctx, selected = this.selected, hover = this.hover, values = { size: this.options.size }) {
if (this.needsRefresh(selected, hover)) {
this.labelModule.getTextSize(ctx, selected, hover);
@ -24,6 +34,18 @@ class ShapeBase extends NodeBase {
}
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {String} shape
* @param {Number} sizeMultiplier - Unused! TODO: Remove next major release
* @param {Number} x
* @param {Number} y
* @param {Boolean} selected
* @param {Boolean} hover
* @param {{toArrow: boolean, toArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), toArrowType: *, middleArrow: boolean, middleArrowScale: (number|allOptions.edges.arrows.middle.scaleFactor|{number}|Array), middleArrowType: (allOptions.edges.arrows.middle.type|{string}|string|*), fromArrow: boolean, fromArrowScale: (allOptions.edges.arrows.to.scaleFactor|{number}|allOptions.edges.arrows.middle.scaleFactor|allOptions.edges.arrows.from.scaleFactor|Array|number), fromArrowType: *, arrowStrikethrough: (*|boolean|allOptions.edges.arrowStrikethrough|{boolean}), color: undefined, inheritsColor: (string|string|string|allOptions.edges.color.inherit|{string, boolean}|Array|*), opacity: *, hidden: *, length: *, shadow: *, shadowColor: *, shadowSize: *, shadowX: *, shadowY: *, dashes: (*|boolean|Array|allOptions.edges.dashes|{boolean, array}), width: *}} values
* @private
*/
_drawShape(ctx, shape, sizeMultiplier, x, y, selected, hover, values) {
this.resize(ctx, selected, hover, values);
this.left = x - this.width / 2;
@ -43,7 +65,12 @@ class ShapeBase extends NodeBase {
this.updateBoundingBox(x,y);
}
updateBoundingBox(x,y) {
/**
*
* @param {Number} x
* @param {Number} y
*/
updateBoundingBox(x, y) {
this.boundingBox.top = y - this.options.size;
this.boundingBox.left = x - this.options.size;
this.boundingBox.right = x + this.options.size;

+ 15
- 5
lib/network/modules/components/physics/BarnesHutSolver.js View File

@ -1,11 +1,13 @@
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor BarnesHutSolver
* @class BarnesHutSolver
*/
class BarnesHutSolver {
/**
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor BarnesHutSolver
*/
constructor(body, physicsBody, options) {
this.body = body;
this.physicsBody = physicsBody;
@ -17,12 +19,20 @@ class BarnesHutSolver {
//this.body.emitter.on("afterDrawing", (ctx) => {this._debug(ctx,'#ff0000')})
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.options = options;
this.thetaInversed = 1 / this.options.theta;
this.overlapAvoidanceFactor = 1 - Math.max(0, Math.min(1,this.options.avoidOverlap)); // if 1 then min distance = 0.5, if 0.5 then min distance = 0.5 + 0.5*node.shape.radius
}
/**
*
* @returns {number} random integer
*/
seededRandom() {
var x = Math.sin(this.randomSeed++) * 10000;
return x - Math.floor(x);

+ 15
- 5
lib/network/modules/components/physics/CentralGravitySolver.js View File

@ -1,21 +1,31 @@
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor CentralGravitySolver
* @class CentralGravitySolver
*/
class CentralGravitySolver {
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor CentralGravitySolver
*/
constructor(body, physicsBody, options) {
this.body = body;
this.physicsBody = physicsBody;
this.setOptions(options);
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.options = options;
}
/**
* Calculates forces for each node
*/
solve() {
let dx, dy, distance, node;
let nodes = this.body.nodes;

+ 7
- 5
lib/network/modules/components/physics/FA2BasedCentralGravitySolver.js View File

@ -1,14 +1,16 @@
import CentralGravitySolver from "./CentralGravitySolver"
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor ForceAtlas2BasedCentralGravitySolver
* @class ForceAtlas2BasedCentralGravitySolver
* @extends CentralGravitySolver
*/
class ForceAtlas2BasedCentralGravitySolver extends CentralGravitySolver {
/**
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor ForceAtlas2BasedCentralGravitySolver
*/
constructor(body, physicsBody, options) {
super(body, physicsBody, options);
}

+ 8
- 5
lib/network/modules/components/physics/FA2BasedRepulsionSolver.js View File

@ -1,14 +1,17 @@
import BarnesHutSolver from "./BarnesHutSolver"
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor ForceAtlas2BasedRepulsionSolver
* @class ForceAtlas2BasedRepulsionSolver
* @extends BarnesHutSolver
*/
class ForceAtlas2BasedRepulsionSolver extends BarnesHutSolver {
/**
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor ForceAtlas2BasedRepulsionSolver
* @extends BarnesHutSolver
*/
constructor(body, physicsBody, options) {
super(body, physicsBody, options);
}

+ 11
- 5
lib/network/modules/components/physics/HierarchicalRepulsionSolver.js View File

@ -1,17 +1,23 @@
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor HierarchicalRepulsionSolver
* @class HierarchicalRepulsionSolver
*/
class HierarchicalRepulsionSolver {
/**
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor HierarchicalRepulsionSolver
*/
constructor(body, physicsBody, options) {
this.body = body;
this.physicsBody = physicsBody;
this.setOptions(options);
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.options = options;
}

+ 11
- 5
lib/network/modules/components/physics/HierarchicalSpringSolver.js View File

@ -1,17 +1,23 @@
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor HierarchicalSpringSolver
* @class HierarchicalSpringSolver
*/
class HierarchicalSpringSolver {
/**
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor HierarchicalSpringSolver
*/
constructor(body, physicsBody, options) {
this.body = body;
this.physicsBody = physicsBody;
this.setOptions(options);
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.options = options;
}

+ 11
- 5
lib/network/modules/components/physics/RepulsionSolver.js View File

@ -1,17 +1,23 @@
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor RepulsionSolver
* @class RepulsionSolver
*/
class RepulsionSolver {
/**
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor RepulsionSolver
*/
constructor(body, physicsBody, options) {
this.body = body;
this.physicsBody = physicsBody;
this.setOptions(options);
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.options = options;
}

+ 11
- 5
lib/network/modules/components/physics/SpringSolver.js View File

@ -1,17 +1,23 @@
/**
*
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor SpringSolver
* @class SpringSolver
*/
class SpringSolver {
/**
* @param {Object} body
* @param {{physicsNodeIndices: Array, physicsEdgeIndices: Array, forces: {}, velocities: {}}} physicsBody
* @param {Object} options
* @constructor SpringSolver
*/
constructor(body, physicsBody, options) {
this.body = body;
this.physicsBody = physicsBody;
this.setOptions(options);
}
/**
*
* @param {Object} options
*/
setOptions(options) {
this.options = options;
}

+ 70
- 9
lib/network/modules/components/shared/Label.js View File

@ -6,11 +6,17 @@ let util = require('../../../../util');
*
* This has been moved away from the label processing code for better undestanding upon reading.
*
* @class LabelAccumulator
* @private
*/
class LabelAccumulator {
/**
* @callback measureText
* @param {function} measureText - callback to determine text dimensions, using the parent label settings.
* @constructor LabelAccumulator
*/
constructor(measureText) {
this.measureText = measureText; // callback to determine text dimensions, using the parent label settings.
this.measureText = measureText;
this.current = 0;
this.width = 0;
this.height = 0;
@ -137,12 +143,15 @@ class LabelAccumulator {
/**
* A Label to be used for Nodes or Edges.
*
* @param {Object} options
* @param {Object} body
* @param {boolean} [edgeLabel=false]
* @constructor Label
* @class Label
*/
class Label {
/**
* @param {Object} body
* @param {Object} options
* @param {boolean} [edgelabel=false]
* @constructor Label
*/
constructor(body, options, edgelabel = false) {
this.body = body;
@ -154,6 +163,11 @@ class Label {
this.isEdgeLabel = edgelabel;
}
/**
*
* @param {Object} options
* @param {Boolean} [allowDeletion=false]
*/
setOptions(options, allowDeletion = false) {
this.elementOptions = options;
@ -178,6 +192,12 @@ class Label {
}
}
/**
*
* @param {Object} parentOptions
* @param {Object} newOptions
* @param {Boolean} [allowDeletion=false]
*/
static parseOptions(parentOptions, newOptions, allowDeletion = false) {
if (Label.parseFontString(parentOptions, newOptions.font)) {
parentOptions.vadjust = 0;
@ -214,7 +234,13 @@ class Label {
}
// set the width and height constraints based on 'nearest' value
/**
* Set the width and height constraints based on 'nearest' value
*
* @param {Object} elementOptions
* @param {Object} options
* @param {Object} defaultOptions
*/
constrain(elementOptions, options, defaultOptions) {
this.fontOptions.constrainWidth = false;
this.fontOptions.maxWdt = -1;
@ -258,7 +284,13 @@ class Label {
}
}
// set the selected functions based on 'nearest' value
/**
* Set the selected functions based on 'nearest' value
*
* @param {Object} elementOptions
* @param {Object} options
* @param {Object} defaultOptions
*/
choosify(elementOptions, options, defaultOptions) {
this.fontOptions.chooser = true;
@ -275,8 +307,12 @@ class Label {
}
}
// When margins are set in an element, adjust sizes is called to remove them
// from the width/height constraints. This must be done prior to label sizing.
/**
* When margins are set in an element, adjust sizes is called to remove them
* from the width/height constraints. This must be done prior to label sizing.
*
* @param {{top: number, right: number, bottom: number, left: number}} margins
*/
adjustSizes(margins) {
let widthBias = (margins) ? (margins.right + margins.left) : 0;
if (this.fontOptions.constrainWidth) {
@ -691,6 +727,11 @@ class Label {
}
}
/**
*
* @param {String} text
* @returns {Array}
*/
splitMarkdownBlocks(text) {
let blocks = [];
let s = {
@ -809,6 +850,11 @@ class Label {
return blocks;
}
/**
*
* @param {String} text
* @returns {Array}
*/
splitHtmlBlocks(text) {
let blocks = [];
let s = {
@ -921,6 +967,14 @@ class Label {
return blocks;
}
/**
*
* @param {CanvasRenderingContext2D} ctx
* @param {boolean} selected
* @param {boolean} hover
* @param {string} mod
* @returns {{color, size, face, mod, vadjust, strokeWidth: *, strokeColor: (*|string|allOptions.edges.font.strokeColor|{string}|allOptions.nodes.font.strokeColor|Array)}}
*/
getFormattingValues(ctx, selected, hover, mod) {
var getValue = function(fontOptions, mod, option) {
if (mod === "normal") {
@ -960,6 +1014,13 @@ class Label {
return values;
}
/**
*
* @param {boolean} selected
* @param {boolean} hover
* @returns {boolean}
*/
differentState(selected, hover) {
return ((selected !== this.fontOptions.selectedState) && (hover !== this.fontOptions.hoverState));
}

+ 11
- 2
lib/shared/ColorPicker.js View File

@ -3,10 +3,13 @@ let hammerUtil = require('../hammerUtil');
let util = require('../util');
/**
*
* @param {Number} [pixelRatio=1]
* @class ColorPicker
*/
class ColorPicker {
/**
* @param {Number} [pixelRatio=1]
* @constructor ColorPicker
*/
constructor(pixelRatio = 1) {
this.pixelRatio = pixelRatio;
this.generated = false;
@ -69,6 +72,12 @@ class ColorPicker {
}
}
/**
*
* @param {String} color
* @returns {String}
* @private
*/
_isColorString(color) {
var htmlColors = {black: '#000000',navy: '#000080',darkblue: '#00008B',mediumblue: '#0000CD',blue: '#0000FF',darkgreen: '#006400',green: '#008000',teal: '#008080',darkcyan: '#008B8B',deepskyblue: '#00BFFF',darkturquoise: '#00CED1',mediumspringgreen: '#00FA9A',lime: '#00FF00',springgreen: '#00FF7F',aqua: '#00FFFF',cyan: '#00FFFF',midnightblue: '#191970',dodgerblue: '#1E90FF',lightseagreen: '#20B2AA',forestgreen: '#228B22',seagreen: '#2E8B57',darkslategray: '#2F4F4F',limegreen: '#32CD32',mediumseagreen: '#3CB371',turquoise: '#40E0D0',royalblue: '#4169E1',steelblue: '#4682B4',darkslateblue: '#483D8B',mediumturquoise: '#48D1CC',indigo: '#4B0082',darkolivegreen: '#556B2F',cadetblue: '#5F9EA0',cornflowerblue: '#6495ED',mediumaquamarine: '#66CDAA',dimgray: '#696969',slateblue: '#6A5ACD',olivedrab: '#6B8E23',slategray: '#708090',lightslategray: '#778899',mediumslateblue: '#7B68EE',lawngreen: '#7CFC00',chartreuse: '#7FFF00',aquamarine: '#7FFFD4',maroon: '#800000',purple: '#800080',olive: '#808000',gray: '#808080',skyblue: '#87CEEB',lightskyblue: '#87CEFA',blueviolet: '#8A2BE2',darkred: '#8B0000',darkmagenta: '#8B008B',saddlebrown: '#8B4513',darkseagreen: '#8FBC8F',lightgreen: '#90EE90',mediumpurple: '#9370D8',darkviolet: '#9400D3',palegreen: '#98FB98',darkorchid: '#9932CC',yellowgreen: '#9ACD32',sienna: '#A0522D',brown: '#A52A2A',darkgray: '#A9A9A9',lightblue: '#ADD8E6',greenyellow: '#ADFF2F',paleturquoise: '#AFEEEE',lightsteelblue: '#B0C4DE',powderblue: '#B0E0E6',firebrick: '#B22222',darkgoldenrod: '#B8860B',mediumorchid: '#BA55D3',rosybrown: '#BC8F8F',darkkhaki: '#BDB76B',silver: '#C0C0C0',mediumvioletred: '#C71585',indianred: '#CD5C5C',peru: '#CD853F',chocolate: '#D2691E',tan: '#D2B48C',lightgrey: '#D3D3D3',palevioletred: '#D87093',thistle: '#D8BFD8',orchid: '#DA70D6',goldenrod: '#DAA520',crimson: '#DC143C',gainsboro: '#DCDCDC',plum: '#DDA0DD',burlywood: '#DEB887',lightcyan: '#E0FFFF',lavender: '#E6E6FA',darksalmon: '#E9967A',violet: '#EE82EE',palegoldenrod: '#EEE8AA',lightcoral: '#F08080',khaki: '#F0E68C',aliceblue: '#F0F8FF',honeydew: '#F0FFF0',azure: '#F0FFFF',sandybrown: '#F4A460',wheat: '#F5DEB3',beige: '#F5F5DC',whitesmoke: '#F5F5F5',mintcream: '#F5FFFA',ghostwhite: '#F8F8FF',salmon: '#FA8072',antiquewhite: '#FAEBD7',linen: '#FAF0E6',lightgoldenrodyellow: '#FAFAD2',oldlace: '#FDF5E6',red: '#FF0000',fuchsia: '#FF00FF',magenta: '#FF00FF',deeppink: '#FF1493',orangered: '#FF4500',tomato: '#FF6347',hotpink: '#FF69B4',coral: '#FF7F50',darkorange: '#FF8C00',lightsalmon: '#FFA07A',orange: '#FFA500',lightpink: '#FFB6C1',pink: '#FFC0CB',gold: '#FFD700',peachpuff: '#FFDAB9',navajowhite: '#FFDEAD',moccasin: '#FFE4B5',bisque: '#FFE4C4',mistyrose: '#FFE4E1',blanchedalmond: '#FFEBCD',papayawhip: '#FFEFD5',lavenderblush: '#FFF0F5',seashell: '#FFF5EE',cornsilk: '#FFF8DC',lemonchiffon: '#FFFACD',floralwhite: '#FFFAF0',snow: '#FFFAFA',yellow: '#FFFF00',lightyellow: '#FFFFE0',ivory: '#FFFFF0',white: '#FFFFFF'};
if (typeof color === 'string') {

+ 29
- 5
lib/shared/Configurator.js View File

@ -11,12 +11,17 @@ var ColorPicker = require('./ColorPicker').default;
*
* The options are matched with their counterparts in each of the modules and the values used in the configuration are
*
* @param {Object} parentModule | the location where parentModule.setOptions() can be called
* @param {Object} defaultContainer | the default container of the module
* @param {Object} configureOptions | the fully configured and predefined options set found in allOptions.js
* @param {Number} pixelRatio | canvas pixel ratio
* @class Configurator
*/
class Configurator {
/**
*
* @param {Object} parentModule | the location where parentModule.setOptions() can be called
* @param {Object} defaultContainer | the default container of the module
* @param {Object} configureOptions | the fully configured and predefined options set found in allOptions.js
* @param {Number} pixelRatio | canvas pixel ratio
* @constructor Configurator
*/
constructor(parentModule, defaultContainer, configureOptions, pixelRatio = 1) {
this.parent = parentModule;
this.changedOptions = [];
@ -95,7 +100,10 @@ class Configurator {
this._clean();
}
/**
*
* @param {Object} moduleOptions
*/
setModuleOptions(moduleOptions) {
this.moduleOptions = moduleOptions;
if (this.options.enabled === true) {
@ -676,6 +684,15 @@ class Configurator {
this.parent.setOptions(options);
}
/**
*
* @param {String|Boolean} value
* @param {Array<String>} path
* @param {{}} optionsObj
* @returns {{}}
* @private
*/
_constructOptions(value, path, optionsObj = {}) {
let pointer = optionsObj;
@ -699,11 +716,18 @@ class Configurator {
return optionsObj;
}
/**
* @private
*/
_printOptions() {
let options = this.getOptions();
this.optionsContainer.innerHTML = '<pre>var options = ' + JSON.stringify(options, null, 2) + '</pre>';
}
/**
*
* @returns {{}} options
*/
getOptions() {
let options = {};
for (var i = 0; i < this.changedOptions.length; i++) {

+ 6
- 2
lib/shared/Popup.js View File

@ -1,9 +1,13 @@
/**
* Popup is a class to create a popup window with some text
* @param {Element} container The container object.
* @param {string} overflowMethod How the popup should act to overflowing ('flip' or 'cap')
* @class Popup
*/
class Popup {
/**
* @param {Element} container The container object.
* @param {string} overflowMethod How the popup should act to overflowing ('flip' or 'cap')
* @constructor Popup
*/
constructor(container, overflowMethod) {
this.container = container;
this.overflowMethod = overflowMethod || 'cap';

+ 39
- 11
lib/shared/Validator.js View File

@ -5,8 +5,12 @@ let allOptions;
let printStyle = 'background: #FFeeee; color: #dd0000';
/**
* Used to validate options.
* @class Validator
*/
class Validator {
/**
* @constructor Validator
*/
constructor() {
}
@ -125,7 +129,11 @@ class Validator {
}
}
/**
*
* @param {Object|Boolean|Number|String|Array<Number>|Date|Node|Moment|undefined|null} object
* @returns {String}
*/
static getType(object) {
var type = typeof object;
@ -171,6 +179,11 @@ class Validator {
return type;
}
/**
* @param {String} option
* @param {Object} options
* @param {Array<String>} path
*/
static getSuggestion(option, options, path) {
let localSearch = Validator.findInOptions(option,options,path,false);
let globalSearch = Validator.findInOptions(option,allOptions,[],true);
@ -241,6 +254,12 @@ class Validator {
return {closestMatch:closestMatch, path:closestMatchPath, distance:min, indexMatch: indexMatch};
}
/**
* @param {Array<string>} path
* @param {Object} option
* @param {String} prefix
* @returns {String}
*/
static printLocation(path, option, prefix = 'Problem value found at: \n') {
let str = '\n\n' + prefix + 'options = {\n';
for (let i = 0; i < path.length; i++) {
@ -262,21 +281,30 @@ class Validator {
return str + '\n\n';
}
/**
* @param {Object} options
* @returns {String}
*/
static print(options) {
return JSON.stringify(options).replace(/(\")|(\[)|(\])|(,"__type__")/g, "").replace(/(\,)/g, ', ')
}
// Compute the edit distance between the two given strings
// http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
/*
Copyright (c) 2011 Andrei Mackenzie
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/**
* Compute the edit distance between the two given strings
* http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript
*
* Copyright (c) 2011 Andrei Mackenzie
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* @param {string} a
* @param {string} b
* @returns {Array<Array<Number>>}}
*/
static levenshteinDistance(a, b) {
if (a.length === 0) return b.length;

+ 3
- 2
lib/timeline/Timeline.js View File

@ -451,7 +451,8 @@ function getEnd(item) {
/**
* Determine the range of the items, taking into account their actual width
* and a margin of 10 pixels on both sides.
* @returns {{min: [Date], max: [Date]}}
*
* @returns {{min: Date, max: Date}}
*/
Timeline.prototype.getItemRange = function () {
// get a rough approximation for the range based on the items start and end dates
@ -524,7 +525,7 @@ Timeline.prototype.getItemRange = function () {
/**
* Calculate the data range of the items start and end dates
* @returns {{min: [Date], max: [Date]}}
* @returns {{min: Date, max: Date}}
*/
Timeline.prototype.getDataRange = function() {
var min = null;

+ 2
- 2
lib/util.js View File

@ -139,7 +139,7 @@ exports.fillIfDefined = function (a, b, allowDeletion = false) {
* Extend object a with the properties of object b or a series of objects
* Only properties with defined values are copied
* @param {Object} a
* @param {... Object} b
* @param {...Object} b
* @return {Object} a
*/
exports.protoExtend = function (a, b) { // eslint-disable-line no-unused-vars
@ -156,7 +156,7 @@ exports.protoExtend = function (a, b) { // eslint-disable-line no-unused-vars
* Extend object a with the properties of object b or a series of objects
* Only properties with defined values are copied
* @param {Object} a
* @param {... Object} b
* @param {...Object} b
* @return {Object} a
*/
exports.extend = function (a, b) { // eslint-disable-line no-unused-vars

Loading…
Cancel
Save