@ -19,6 +19,9 @@ var locales = require('./locales');
// Load custom shapes into CanvasRenderingContext2D
// Load custom shapes into CanvasRenderingContext2D
require ( './shapes' ) ;
require ( './shapes' ) ;
import { ClusterEngine } from './modules/Clustering'
/ * *
/ * *
* @ constructor Network
* @ constructor Network
* Create a network visualization , displaying nodes and edges .
* Create a network visualization , displaying nodes and edges .
@ -61,6 +64,9 @@ function Network (container, data, options) {
return Math . max ( 0 , ( value - min ) * scale ) ;
return Math . max ( 0 , ( value - min ) * scale ) ;
}
}
} ;
} ;
// set constant values
// set constant values
this . defaultOptions = {
this . defaultOptions = {
nodes : {
nodes : {
@ -223,9 +229,31 @@ function Network (container, data, options) {
useDefaultGroups : true
useDefaultGroups : true
} ;
} ;
this . constants = util . extend ( { } , this . defaultOptions ) ;
this . constants = util . extend ( { } , this . defaultOptions ) ;
// containers for nodes and edges
this . body = {
sectors : { } ,
nodeIndices : [ ] ,
nodes : { } ,
edges : { } ,
data : {
nodes : null , // A DataSet or DataView
edges : null // A DataSet or DataView
} ,
functions : {
createNode : this . _createNode . bind ( this ) ,
createEdge : this . _createEdge . bind ( this )
} ,
emitter : {
on : this . on . bind ( this ) ,
off : this . off . bind ( this ) ,
emit : this . emit . bind ( this )
}
} ;
this . pixelRatio = 1 ;
this . pixelRatio = 1 ;
this . hoverObj = { nodes : { } , edges : { } } ;
this . hoverObj = { nodes : { } , edges : { } } ;
this . controlNodesActive = false ;
this . controlNodesActive = false ;
this . navigationHammers = [ ] ;
this . navigationHammers = [ ] ;
@ -246,11 +274,11 @@ function Network (container, data, options) {
this . redrawRequested = false ;
this . redrawRequested = false ;
// Node variables
// Node variables
var network = this ;
var me = this ;
this . groups = new Groups ( ) ; // object with groups
this . groups = new Groups ( ) ; // object with groups
this . images = new Images ( ) ; // object with images
this . images = new Images ( ) ; // object with images
this . images . setOnloadCallback ( function ( status ) {
this . images . setOnloadCallback ( function ( status ) {
network . _requestRedraw ( ) ;
me . _requestRedraw ( ) ;
} ) ;
} ) ;
// keyboard navigation variables
// keyboard navigation variables
@ -272,7 +300,6 @@ function Network (container, data, options) {
// load the selection system. (mandatory, required by Network)
// load the selection system. (mandatory, required by Network)
this . _loadHierarchySystem ( ) ;
this . _loadHierarchySystem ( ) ;
// apply options
// apply options
this . _setTranslation ( this . frame . clientWidth / 2 , this . frame . clientHeight / 2 ) ;
this . _setTranslation ( this . frame . clientWidth / 2 , this . frame . clientHeight / 2 ) ;
this . _setScale ( 1 ) ;
this . _setScale ( 1 ) ;
@ -286,20 +313,7 @@ function Network (container, data, options) {
this . stabilizationIterations = null ;
this . stabilizationIterations = null ;
this . draggingNodes = false ;
this . draggingNodes = false ;
// containers for nodes and edges
this . body = {
calculationNodes : { } ,
calculationNodeIndices : { } ,
nodeIndices : { } ,
nodes : { } ,
edges : { }
}
this . calculationNodes = { } ;
this . calculationNodeIndices = [ ] ;
this . nodeIndices = [ ] ; // array with all the indices of the nodes. Used to speed up forces calculation
this . nodes = { } ; // object with Node objects
this . edges = { } ; // object with Edge objects
this . clustering = new ClusterEngine ( this . body ) ;
// position and scale variables and objects
// position and scale variables and objects
this . canvasTopLeft = { "x" : 0 , "y" : 0 } ; // coordinates of the top left of the canvas. they will be set during _redraw.
this . canvasTopLeft = { "x" : 0 , "y" : 0 } ; // coordinates of the top left of the canvas. they will be set during _redraw.
@ -307,37 +321,33 @@ function Network (container, data, options) {
this . pointerPosition = { "x" : 0 , "y" : 0 } ; // coordinates of the bottom right of the canvas. they will be set during _redraw
this . pointerPosition = { "x" : 0 , "y" : 0 } ; // coordinates of the bottom right of the canvas. they will be set during _redraw
this . scale = 1 ; // defining the global scale variable in the constructor
this . scale = 1 ; // defining the global scale variable in the constructor
// datasets or dataviews
this . nodesData = null ; // A DataSet or DataView
this . edgesData = null ; // A DataSet or DataView
// create event listeners used to subscribe on the DataSets of the nodes and edges
// create event listeners used to subscribe on the DataSets of the nodes and edges
this . nodesListeners = {
this . nodesListeners = {
'add' : function ( event , params ) {
'add' : function ( event , params ) {
network . _addNodes ( params . items ) ;
network . start ( ) ;
me . _addNodes ( params . items ) ;
me . start ( ) ;
} ,
} ,
'update' : function ( event , params ) {
'update' : function ( event , params ) {
network . _updateNodes ( params . items , params . data ) ;
network . start ( ) ;
me . _updateNodes ( params . items , params . data ) ;
me . start ( ) ;
} ,
} ,
'remove' : function ( event , params ) {
'remove' : function ( event , params ) {
network . _removeNodes ( params . items ) ;
network . start ( ) ;
me . _removeNodes ( params . items ) ;
me . start ( ) ;
}
}
} ;
} ;
this . edgesListeners = {
this . edgesListeners = {
'add' : function ( event , params ) {
'add' : function ( event , params ) {
network . _addEdges ( params . items ) ;
network . start ( ) ;
me . _addEdges ( params . items ) ;
me . start ( ) ;
} ,
} ,
'update' : function ( event , params ) {
'update' : function ( event , params ) {
network . _updateEdges ( params . items ) ;
network . start ( ) ;
me . _updateEdges ( params . items ) ;
me . start ( ) ;
} ,
} ,
'remove' : function ( event , params ) {
'remove' : function ( event , params ) {
network . _removeEdges ( params . items ) ;
network . start ( ) ;
me . _removeEdges ( params . items ) ;
me . start ( ) ;
}
}
} ;
} ;
@ -363,12 +373,35 @@ function Network (container, data, options) {
this . initializing = false ;
this . initializing = false ;
}
}
var me = this ;
this . on ( "_dataChanged" , function ( ) {
console . log ( "here" )
me . _updateNodeIndexList ( ) ;
me . _updateCalculationNodes ( ) ;
me . _markAllEdgesAsDirty ( ) ;
if ( me . initializing !== true ) {
me . moving = true ;
me . start ( ) ;
}
} )
this . on ( "_newEdgesCreated" , this . _createBezierNodes . bind ( this ) ) ;
this . on ( "stabilizationIterationsDone" , function ( ) { this . initializing = false ; this . start ( ) ; } . bind ( this ) ) ;
this . on ( "stabilizationIterationsDone" , function ( ) { this . initializing = false ; this . start ( ) ; } . bind ( this ) ) ;
}
}
// Extend Network with an Emitter mixin
// Extend Network with an Emitter mixin
Emitter ( Network . prototype ) ;
Emitter ( Network . prototype ) ;
Network . prototype . _createNode = function ( properties ) {
return new Node ( properties , this . images , this . groups , this . constants )
}
Network . prototype . _createEdge = function ( properties ) {
return new Edge ( properties , this . body , this . constants )
}
/ * *
/ * *
* Determine if the browser requires a setTimeout or a requestAnimationFrame . This was required because
* Determine if the browser requires a setTimeout or a requestAnimationFrame . This was required because
* some implementations ( safari and IE9 ) did not support requestAnimationFrame
* some implementations ( safari and IE9 ) did not support requestAnimationFrame
@ -420,7 +453,7 @@ Network.prototype._getRange = function(specificNodes) {
var minY = 1 e9 , maxY = - 1 e9 , minX = 1 e9 , maxX = - 1 e9 , node ;
var minY = 1 e9 , maxY = - 1 e9 , minX = 1 e9 , maxX = - 1 e9 , node ;
if ( specificNodes . length > 0 ) {
if ( specificNodes . length > 0 ) {
for ( var i = 0 ; i < specificNodes . length ; i ++ ) {
for ( var i = 0 ; i < specificNodes . length ; i ++ ) {
node = this . nodes [ specificNodes [ i ] ] ;
node = this . body . nodes [ specificNodes [ i ] ] ;
if ( minX > ( node . boundingBox . left ) ) {
if ( minX > ( node . boundingBox . left ) ) {
minX = node . boundingBox . left ;
minX = node . boundingBox . left ;
}
}
@ -436,9 +469,9 @@ Network.prototype._getRange = function(specificNodes) {
}
}
}
}
else {
else {
for ( var nodeId in this . nodes ) {
if ( this . nodes . hasOwnProperty ( nodeId ) ) {
node = this . nodes [ nodeId ] ;
for ( var nodeId in this . body . nodes ) {
if ( this . body . nodes . hasOwnProperty ( nodeId ) ) {
node = this . body . nodes [ nodeId ] ;
if ( minX > ( node . boundingBox . left ) ) {
if ( minX > ( node . boundingBox . left ) ) {
minX = node . boundingBox . left ;
minX = node . boundingBox . left ;
}
}
@ -495,22 +528,22 @@ Network.prototype.zoomExtent = function(options, initialZoom, disableStart) {
if ( initialZoom == true ) {
if ( initialZoom == true ) {
// check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation.
// check if more than half of the nodes have a predefined position. If so, we use the range, not the approximation.
var positionDefined = 0 ;
var positionDefined = 0 ;
for ( var nodeId in this . nodes ) {
if ( this . nodes . hasOwnProperty ( nodeId ) ) {
var node = this . nodes [ nodeId ] ;
for ( var nodeId in this . body . nodes ) {
if ( this . body . nodes . hasOwnProperty ( nodeId ) ) {
var node = this . body . nodes [ nodeId ] ;
if ( node . predefinedPosition == true ) {
if ( node . predefinedPosition == true ) {
positionDefined += 1 ;
positionDefined += 1 ;
}
}
}
}
}
}
if ( positionDefined > 0.5 * this . nodeIndices . length ) {
if ( positionDefined > 0.5 * this . body . nodeIndices . length ) {
this . zoomExtent ( options , false , disableStart ) ;
this . zoomExtent ( options , false , disableStart ) ;
return ;
return ;
}
}
range = this . _getRange ( options . nodes ) ;
range = this . _getRange ( options . nodes ) ;
var numberOfNodes = this . nodeIndices . length ;
var numberOfNodes = this . body . nodeIndices . length ;
if ( this . constants . smoothCurves == true ) {
if ( this . constants . smoothCurves == true ) {
if ( this . constants . clustering . enabled == true &&
if ( this . constants . clustering . enabled == true &&
numberOfNodes >= this . constants . clustering . initialMaxNodes ) {
numberOfNodes >= this . constants . clustering . initialMaxNodes ) {
@ -568,12 +601,12 @@ Network.prototype.zoomExtent = function(options, initialZoom, disableStart) {
/ * *
/ * *
* Update the this . nodeIndices with the most recent node index list
* Update the this . body . nodeIndices with the most recent node index list
* @ private
* @ private
* /
* /
Network . prototype . _updateNodeIndexList = function ( ) {
Network . prototype . _updateNodeIndexList = function ( ) {
this . _clearNodeIndexList ( ) ;
this . _clearNodeIndexList ( ) ;
this . nodeIndices = Object . keys ( this . nodes ) ;
this . body . nodeIndices = Object . keys ( this . body . nodes ) ;
} ;
} ;
@ -1446,7 +1479,7 @@ Network.prototype._checkShowPopup = function (pointer) {
if ( this . popupObj == undefined ) {
if ( this . popupObj == undefined ) {
// search the nodes for overlap, select the top one in case of multiple nodes
// search the nodes for overlap, select the top one in case of multiple nodes
var nodes = this . nodes ;
var nodes = this . body . nodes ;
var overlappingNodes = [ ] ;
var overlappingNodes = [ ] ;
for ( id in nodes ) {
for ( id in nodes ) {
if ( nodes . hasOwnProperty ( id ) ) {
if ( nodes . hasOwnProperty ( id ) ) {
@ -1462,7 +1495,7 @@ Network.prototype._checkShowPopup = function (pointer) {
if ( overlappingNodes . length > 0 ) {
if ( overlappingNodes . length > 0 ) {
// if there are overlapping nodes, select the last one, this is the
// if there are overlapping nodes, select the last one, this is the
// one which is drawn on top of the others
// one which is drawn on top of the others
this . popupObj = this . nodes [ overlappingNodes [ overlappingNodes . length - 1 ] ] ;
this . popupObj = this . body . nodes [ overlappingNodes [ overlappingNodes . length - 1 ] ] ;
// if you hover over a node, the title of the edge is not supposed to be shown.
// if you hover over a node, the title of the edge is not supposed to be shown.
nodeUnderCursor = true ;
nodeUnderCursor = true ;
}
}
@ -1470,7 +1503,7 @@ Network.prototype._checkShowPopup = function (pointer) {
if ( this . popupObj === undefined && nodeUnderCursor == false ) {
if ( this . popupObj === undefined && nodeUnderCursor == false ) {
// search the edges for overlap
// search the edges for overlap
var edges = this . edges ;
var edges = this . body . edges ;
var overlappingEdges = [ ] ;
var overlappingEdges = [ ] ;
for ( id in edges ) {
for ( id in edges ) {
if ( edges . hasOwnProperty ( id ) ) {
if ( edges . hasOwnProperty ( id ) ) {
@ -1483,7 +1516,7 @@ Network.prototype._checkShowPopup = function (pointer) {
}
}
if ( overlappingEdges . length > 0 ) {
if ( overlappingEdges . length > 0 ) {
this . popupObj = this . edges [ overlappingEdges [ overlappingEdges . length - 1 ] ] ;
this . popupObj = this . body . edges [ overlappingEdges [ overlappingEdges . length - 1 ] ] ;
popupType = "edge" ;
popupType = "edge" ;
}
}
}
}
@ -1530,7 +1563,7 @@ Network.prototype._checkHidePopup = function (pointer) {
var stillOnObj = false ;
var stillOnObj = false ;
if ( this . popup . popupTargetType == 'node' ) {
if ( this . popup . popupTargetType == 'node' ) {
stillOnObj = this . nodes [ this . popup . popupTargetId ] . isOverlappingWith ( pointerObj ) ;
stillOnObj = this . body . nodes [ this . popup . popupTargetId ] . isOverlappingWith ( pointerObj ) ;
if ( stillOnObj === true ) {
if ( stillOnObj === true ) {
var overNode = this . _getNodeAt ( pointer ) ;
var overNode = this . _getNodeAt ( pointer ) ;
stillOnObj = overNode . id == this . popup . popupTargetId ;
stillOnObj = overNode . id == this . popup . popupTargetId ;
@ -1538,7 +1571,7 @@ Network.prototype._checkHidePopup = function (pointer) {
}
}
else {
else {
if ( this . _getNodeAt ( pointer ) === null ) {
if ( this . _getNodeAt ( pointer ) === null ) {
stillOnObj = this . edges [ this . popup . popupTargetId ] . isOverlappingWith ( pointerObj ) ;
stillOnObj = this . body . edges [ this . popup . popupTargetId ] . isOverlappingWith ( pointerObj ) ;
}
}
}
}
@ -1601,17 +1634,17 @@ Network.prototype.setSize = function(width, height) {
* @ private
* @ private
* /
* /
Network . prototype . _setNodes = function ( nodes ) {
Network . prototype . _setNodes = function ( nodes ) {
var oldNodesData = this . nodesData ;
var oldNodesData = this . body . data . nodes ;
if ( nodes instanceof DataSet || nodes instanceof DataView ) {
if ( nodes instanceof DataSet || nodes instanceof DataView ) {
this . nodesData = nodes ;
this . body . data . nodes = nodes ;
}
}
else if ( Array . isArray ( nodes ) ) {
else if ( Array . isArray ( nodes ) ) {
this . nodesData = new DataSet ( ) ;
this . nodesData . add ( nodes ) ;
this . body . data . nodes = new DataSet ( ) ;
this . body . data . nodes . add ( nodes ) ;
}
}
else if ( ! nodes ) {
else if ( ! nodes ) {
this . nodesData = new DataSet ( ) ;
this . body . data . nodes = new DataSet ( ) ;
}
}
else {
else {
throw new TypeError ( 'Array or DataSet expected' ) ;
throw new TypeError ( 'Array or DataSet expected' ) ;
@ -1625,17 +1658,17 @@ Network.prototype._setNodes = function(nodes) {
}
}
// remove drawn nodes
// remove drawn nodes
this . nodes = { } ;
this . body . nodes = { } ;
if ( this . nodesData ) {
if ( this . body . data . nodes ) {
// subscribe to new dataset
// subscribe to new dataset
var me = this ;
var me = this ;
util . forEach ( this . nodesListeners , function ( callback , event ) {
util . forEach ( this . nodesListeners , function ( callback , event ) {
me . nodesData . on ( event , callback ) ;
me . body . data . nodes . on ( event , callback ) ;
} ) ;
} ) ;
// draw all new nodes
// draw all new nodes
var ids = this . nodesData . getIds ( ) ;
var ids = this . body . data . nodes . getIds ( ) ;
this . _addNodes ( ids ) ;
this . _addNodes ( ids ) ;
}
}
this . _updateSelection ( ) ;
this . _updateSelection ( ) ;
@ -1650,9 +1683,9 @@ Network.prototype._addNodes = function(ids) {
var id ;
var id ;
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
id = ids [ i ] ;
id = ids [ i ] ;
var data = this . nodesData . get ( id ) ;
var data = this . body . data . nodes . get ( id ) ;
var node = new Node ( data , this . images , this . groups , this . constants ) ;
var node = new Node ( data , this . images , this . groups , this . constants ) ;
this . nodes [ id ] = node ; // note: this may replace an existing node
this . body . nodes [ id ] = node ; // note: this may replace an existing node
if ( ( node . xFixed == false || node . yFixed == false ) && ( node . x === null || node . y === null ) ) {
if ( ( node . xFixed == false || node . yFixed == false ) && ( node . x === null || node . y === null ) ) {
var radius = 10 * 0.1 * ids . length + 10 ;
var radius = 10 * 0.1 * ids . length + 10 ;
var angle = 2 * Math . PI * Math . random ( ) ;
var angle = 2 * Math . PI * Math . random ( ) ;
@ -1669,7 +1702,7 @@ Network.prototype._addNodes = function(ids) {
}
}
this . _updateCalculationNodes ( ) ;
this . _updateCalculationNodes ( ) ;
this . _reconnectEdges ( ) ;
this . _reconnectEdges ( ) ;
this . _updateValueRange ( this . nodes ) ;
this . _updateValueRange ( this . body . nodes ) ;
} ;
} ;
/ * *
/ * *
@ -1678,7 +1711,7 @@ Network.prototype._addNodes = function(ids) {
* @ private
* @ private
* /
* /
Network . prototype . _updateNodes = function ( ids , changedData ) {
Network . prototype . _updateNodes = function ( ids , changedData ) {
var nodes = this . nodes ;
var nodes = this . body . nodes ;
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
var id = ids [ i ] ;
var id = ids [ i ] ;
var node = nodes [ id ] ;
var node = nodes [ id ] ;
@ -1705,8 +1738,8 @@ Network.prototype._updateNodes = function(ids,changedData) {
Network . prototype . _markAllEdgesAsDirty = function ( ) {
Network . prototype . _markAllEdgesAsDirty = function ( ) {
for ( var edgeId in this . edges ) {
this . edges [ edgeId ] . colorDirty = true ;
for ( var edgeId in this . body . edges ) {
this . body . edges [ edgeId ] . colorDirty = true ;
}
}
}
}
@ -1716,13 +1749,13 @@ Network.prototype._markAllEdgesAsDirty = function() {
* @ private
* @ private
* /
* /
Network . prototype . _removeNodes = function ( ids ) {
Network . prototype . _removeNodes = function ( ids ) {
var nodes = this . nodes ;
var nodes = this . body . nodes ;
// remove from selection
// remove from selection
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
if ( this . selectionObj . nodes [ ids [ i ] ] !== undefined ) {
if ( this . selectionObj . nodes [ ids [ i ] ] !== undefined ) {
this . nodes [ ids [ i ] ] . unselect ( ) ;
this . _removeFromSelection ( this . nodes [ ids [ i ] ] ) ;
this . body . nodes [ ids [ i ] ] . unselect ( ) ;
this . _removeFromSelection ( this . body . nodes [ ids [ i ] ] ) ;
}
}
}
}
@ -1751,17 +1784,17 @@ Network.prototype._removeNodes = function(ids) {
* @ private
* @ private
* /
* /
Network . prototype . _setEdges = function ( edges ) {
Network . prototype . _setEdges = function ( edges ) {
var oldEdgesData = this . edgesData ;
var oldEdgesData = this . body . data . edges ;
if ( edges instanceof DataSet || edges instanceof DataView ) {
if ( edges instanceof DataSet || edges instanceof DataView ) {
this . edgesData = edges ;
this . body . data . edges = edges ;
}
}
else if ( Array . isArray ( edges ) ) {
else if ( Array . isArray ( edges ) ) {
this . edgesData = new DataSet ( ) ;
this . edgesData . add ( edges ) ;
this . body . data . edges = new DataSet ( ) ;
this . body . data . edges . add ( edges ) ;
}
}
else if ( ! edges ) {
else if ( ! edges ) {
this . edgesData = new DataSet ( ) ;
this . body . data . edges = new DataSet ( ) ;
}
}
else {
else {
throw new TypeError ( 'Array or DataSet expected' ) ;
throw new TypeError ( 'Array or DataSet expected' ) ;
@ -1775,17 +1808,17 @@ Network.prototype._setEdges = function(edges) {
}
}
// remove drawn edges
// remove drawn edges
this . edges = { } ;
this . body . edges = { } ;
if ( this . edgesData ) {
if ( this . body . data . edges ) {
// subscribe to new dataset
// subscribe to new dataset
var me = this ;
var me = this ;
util . forEach ( this . edgesListeners , function ( callback , event ) {
util . forEach ( this . edgesListeners , function ( callback , event ) {
me . edgesData . on ( event , callback ) ;
me . body . data . edges . on ( event , callback ) ;
} ) ;
} ) ;
// draw all new nodes
// draw all new nodes
var ids = this . edgesData . getIds ( ) ;
var ids = this . body . data . edges . getIds ( ) ;
this . _addEdges ( ids ) ;
this . _addEdges ( ids ) ;
}
}
@ -1798,8 +1831,8 @@ Network.prototype._setEdges = function(edges) {
* @ private
* @ private
* /
* /
Network . prototype . _addEdges = function ( ids ) {
Network . prototype . _addEdges = function ( ids ) {
var edges = this . edges ,
edgesData = this . edgesData ;
var edges = this . body . edges ,
edgesData = this . body . data . edges ;
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
var id = ids [ i ] ;
var id = ids [ i ] ;
@ -1810,7 +1843,7 @@ Network.prototype._addEdges = function (ids) {
}
}
var data = edgesData . get ( id , { "showInternalIds" : true } ) ;
var data = edgesData . get ( id , { "showInternalIds" : true } ) ;
edges [ id ] = new Edge ( data , this , this . constants ) ;
edges [ id ] = new Edge ( data , this . body , this . constants ) ;
}
}
this . moving = true ;
this . moving = true ;
this . _updateValueRange ( edges ) ;
this . _updateValueRange ( edges ) ;
@ -1828,8 +1861,8 @@ Network.prototype._addEdges = function (ids) {
* @ private
* @ private
* /
* /
Network . prototype . _updateEdges = function ( ids ) {
Network . prototype . _updateEdges = function ( ids ) {
var edges = this . edges ,
edgesData = this . edgesData ;
var edges = this . body . edges ;
var edgesData = this . body . data . edges ;
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
var id = ids [ i ] ;
var id = ids [ i ] ;
@ -1838,13 +1871,13 @@ Network.prototype._updateEdges = function (ids) {
if ( edge ) {
if ( edge ) {
// update edge
// update edge
edge . disconnect ( ) ;
edge . disconnect ( ) ;
edge . setProperties ( data , this . constants ) ;
edge . setProperties ( data ) ;
edge . connect ( ) ;
edge . connect ( ) ;
}
}
else {
else {
// create edge
// create edge
edge = new Edge ( data , this , this . constants ) ;
this . edges [ id ] = edge ;
edge = new Edge ( data , this . body , this . constants ) ;
this . body . edges [ id ] = edge ;
}
}
}
}
@ -1863,7 +1896,7 @@ Network.prototype._updateEdges = function (ids) {
* @ private
* @ private
* /
* /
Network . prototype . _removeEdges = function ( ids ) {
Network . prototype . _removeEdges = function ( ids ) {
var edges = this . edges ;
var edges = this . body . edges ;
// remove from selection
// remove from selection
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
for ( var i = 0 , len = ids . length ; i < len ; i ++ ) {
@ -1878,7 +1911,7 @@ Network.prototype._removeEdges = function (ids) {
var edge = edges [ id ] ;
var edge = edges [ id ] ;
if ( edge ) {
if ( edge ) {
if ( edge . via != null ) {
if ( edge . via != null ) {
delete this . sectors [ 'support' ] [ 'nodes' ] [ edge . via . id ] ;
delete this . body . sectors [ 'support' ] [ 'nodes' ] [ edge . via . id ] ;
}
}
edge . disconnect ( ) ;
edge . disconnect ( ) ;
delete edges [ id ] ;
delete edges [ id ] ;
@ -1900,8 +1933,8 @@ Network.prototype._removeEdges = function (ids) {
* /
* /
Network . prototype . _reconnectEdges = function ( ) {
Network . prototype . _reconnectEdges = function ( ) {
var id ,
var id ,
nodes = this . nodes ,
edges = this . edges ;
nodes = this . body . nodes ,
edges = this . body . edges ;
for ( id in nodes ) {
for ( id in nodes ) {
if ( nodes . hasOwnProperty ( id ) ) {
if ( nodes . hasOwnProperty ( id ) ) {
nodes [ id ] . edges = [ ] ;
nodes [ id ] . edges = [ ] ;
@ -2168,7 +2201,7 @@ Network.prototype._drawNodes = function(ctx,alwaysShow) {
}
}
// first draw the unselected nodes
// first draw the unselected nodes
var nodes = this . nodes ;
var nodes = this . body . nodes ;
var selected = [ ] ;
var selected = [ ] ;
for ( var id in nodes ) {
for ( var id in nodes ) {
@ -2200,7 +2233,7 @@ Network.prototype._drawNodes = function(ctx,alwaysShow) {
* @ private
* @ private
* /
* /
Network . prototype . _drawEdges = function ( ctx ) {
Network . prototype . _drawEdges = function ( ctx ) {
var edges = this . edges ;
var edges = this . body . edges ;
for ( var id in edges ) {
for ( var id in edges ) {
if ( edges . hasOwnProperty ( id ) ) {
if ( edges . hasOwnProperty ( id ) ) {
var edge = edges [ id ] ;
var edge = edges [ id ] ;
@ -2219,7 +2252,7 @@ Network.prototype._drawEdges = function(ctx) {
* @ private
* @ private
* /
* /
Network . prototype . _drawControlNodes = function ( ctx ) {
Network . prototype . _drawControlNodes = function ( ctx ) {
var edges = this . edges ;
var edges = this . body . edges ;
for ( var id in edges ) {
for ( var id in edges ) {
if ( edges . hasOwnProperty ( id ) ) {
if ( edges . hasOwnProperty ( id ) ) {
edges [ id ] . _drawControlNodes ( ctx ) ;
edges [ id ] . _drawControlNodes ( ctx ) ;
@ -2276,7 +2309,7 @@ Network.prototype._finalizeStabilization = function() {
* @ private
* @ private
* /
* /
Network . prototype . _freezeDefinedNodes = function ( ) {
Network . prototype . _freezeDefinedNodes = function ( ) {
var nodes = this . nodes ;
var nodes = this . body . nodes ;
for ( var id in nodes ) {
for ( var id in nodes ) {
if ( nodes . hasOwnProperty ( id ) ) {
if ( nodes . hasOwnProperty ( id ) ) {
if ( nodes [ id ] . x != null && nodes [ id ] . y != null ) {
if ( nodes [ id ] . x != null && nodes [ id ] . y != null ) {
@ -2295,7 +2328,7 @@ Network.prototype._freezeDefinedNodes = function() {
* @ private
* @ private
* /
* /
Network . prototype . _restoreFrozenNodes = function ( ) {
Network . prototype . _restoreFrozenNodes = function ( ) {
var nodes = this . nodes ;
var nodes = this . body . nodes ;
for ( var id in nodes ) {
for ( var id in nodes ) {
if ( nodes . hasOwnProperty ( id ) ) {
if ( nodes . hasOwnProperty ( id ) ) {
if ( nodes [ id ] . fixedData . x != null ) {
if ( nodes [ id ] . fixedData . x != null ) {
@ -2314,7 +2347,7 @@ Network.prototype._restoreFrozenNodes = function() {
* @ private
* @ private
* /
* /
Network . prototype . _isMoving = function ( vmin ) {
Network . prototype . _isMoving = function ( vmin ) {
var nodes = this . nodes ;
var nodes = this . body . nodes ;
for ( var id in nodes ) {
for ( var id in nodes ) {
if ( nodes [ id ] !== undefined ) {
if ( nodes [ id ] !== undefined ) {
if ( nodes [ id ] . isMoving ( vmin ) == true ) {
if ( nodes [ id ] . isMoving ( vmin ) == true ) {
@ -2334,7 +2367,7 @@ Network.prototype._isMoving = function(vmin) {
* /
* /
Network . prototype . _discreteStepNodes = function ( ) {
Network . prototype . _discreteStepNodes = function ( ) {
var interval = this . physicsDiscreteStepsize ;
var interval = this . physicsDiscreteStepsize ;
var nodes = this . nodes ;
var nodes = this . body . nodes ;
var nodeId ;
var nodeId ;
var nodesPresent = false ;
var nodesPresent = false ;
@ -2369,7 +2402,7 @@ Network.prototype._discreteStepNodes = function() {
Network . prototype . _revertPhysicsState = function ( ) {
Network . prototype . _revertPhysicsState = function ( ) {
var nodes = this . nodes ;
var nodes = this . body . nodes ;
for ( var nodeId in nodes ) {
for ( var nodeId in nodes ) {
if ( nodes . hasOwnProperty ( nodeId ) ) {
if ( nodes . hasOwnProperty ( nodeId ) ) {
nodes [ nodeId ] . revertPosition ( ) ;
nodes [ nodeId ] . revertPosition ( ) ;
@ -2567,20 +2600,20 @@ Network.prototype._configureSmoothCurves = function(disableStart) {
if ( this . constants . smoothCurves . enabled == true && this . constants . smoothCurves . dynamic == true ) {
if ( this . constants . smoothCurves . enabled == true && this . constants . smoothCurves . dynamic == true ) {
this . _createBezierNodes ( ) ;
this . _createBezierNodes ( ) ;
// cleanup unused support nodes
// cleanup unused support nodes
for ( var nodeId in this . sectors [ 'support' ] [ 'nodes' ] ) {
if ( this . sectors [ 'support' ] [ 'nodes' ] . hasOwnProperty ( nodeId ) ) {
if ( this . edges [ this . sectors [ 'support' ] [ 'nodes' ] [ nodeId ] . parentEdgeId ] === undefined ) {
delete this . sectors [ 'support' ] [ 'nodes' ] [ nodeId ] ;
for ( var nodeId in this . body . sectors [ 'support' ] [ 'nodes' ] ) {
if ( this . body . sectors [ 'support' ] [ 'nodes' ] . hasOwnProperty ( nodeId ) ) {
if ( this . body . edges [ this . body . sectors [ 'support' ] [ 'nodes' ] [ nodeId ] . parentEdgeId ] === undefined ) {
delete this . body . sectors [ 'support' ] [ 'nodes' ] [ nodeId ] ;
}
}
}
}
}
}
}
}
else {
else {
// delete the support nodes
// delete the support nodes
this . sectors [ 'support' ] [ 'nodes' ] = { } ;
for ( var edgeId in this . edges ) {
if ( this . edges . hasOwnProperty ( edgeId ) ) {
this . edges [ edgeId ] . via = null ;
this . body . sectors [ 'support' ] [ 'nodes' ] = { } ;
for ( var edgeId in this . body . edges ) {
if ( this . body . edges . hasOwnProperty ( edgeId ) ) {
this . body . edges [ edgeId ] . via = null ;
}
}
}
}
}
}
@ -2601,8 +2634,9 @@ Network.prototype._configureSmoothCurves = function(disableStart) {
* @ private
* @ private
* /
* /
Network . prototype . _createBezierNodes = function ( specificEdges ) {
Network . prototype . _createBezierNodes = function ( specificEdges ) {
console . log ( 'specifics' , specificEdges )
if ( specificEdges === undefined ) {
if ( specificEdges === undefined ) {
specificEdges = this . edges ;
specificEdges = this . body . edges ;
}
}
if ( this . constants . smoothCurves . enabled == true && this . constants . smoothCurves . dynamic == true ) {
if ( this . constants . smoothCurves . enabled == true && this . constants . smoothCurves . dynamic == true ) {
for ( var edgeId in specificEdges ) {
for ( var edgeId in specificEdges ) {
@ -2610,14 +2644,14 @@ Network.prototype._createBezierNodes = function(specificEdges) {
var edge = specificEdges [ edgeId ] ;
var edge = specificEdges [ edgeId ] ;
if ( edge . via == null ) {
if ( edge . via == null ) {
var nodeId = "edgeId:" . concat ( edge . id ) ;
var nodeId = "edgeId:" . concat ( edge . id ) ;
this . sectors [ 'support' ] [ 'nodes' ] [ nodeId ] = new Node (
this . body . sectors [ 'support' ] [ 'nodes' ] [ nodeId ] = new Node (
{ id : nodeId ,
{ id : nodeId ,
mass : 1 ,
mass : 1 ,
shape : 'circle' ,
shape : 'circle' ,
image : "" ,
image : "" ,
internalMultiplier : 1
internalMultiplier : 1
} , { } , { } , this . constants ) ;
} , { } , { } , this . constants ) ;
edge . via = this . sectors [ 'support' ] [ 'nodes' ] [ nodeId ] ;
edge . via = this . body . sectors [ 'support' ] [ 'nodes' ] [ nodeId ] ;
edge . via . parentEdgeId = edge . id ;
edge . via . parentEdgeId = edge . id ;
edge . positionBezierNode ( ) ;
edge . positionBezierNode ( ) ;
}
}
@ -2652,17 +2686,17 @@ Network.prototype.storePosition = function() {
* /
* /
Network . prototype . storePositions = function ( ) {
Network . prototype . storePositions = function ( ) {
var dataArray = [ ] ;
var dataArray = [ ] ;
for ( var nodeId in this . nodes ) {
if ( this . nodes . hasOwnProperty ( nodeId ) ) {
var node = this . nodes [ nodeId ] ;
var allowedToMoveX = ! this . nodes . xFixed ;
var allowedToMoveY = ! this . nodes . yFixed ;
if ( this . nodesData . _data [ nodeId ] . x != Math . round ( node . x ) || this . nodesData . _data [ nodeId ] . y != Math . round ( node . y ) ) {
for ( var nodeId in this . body . nodes ) {
if ( this . body . nodes . hasOwnProperty ( nodeId ) ) {
var node = this . body . nodes [ nodeId ] ;
var allowedToMoveX = ! this . body . nodes . xFixed ;
var allowedToMoveY = ! this . body . nodes . yFixed ;
if ( this . body . data . nodes . _data [ nodeId ] . x != Math . round ( node . x ) || this . body . data . nodes . _data [ nodeId ] . y != Math . round ( node . y ) ) {
dataArray . push ( { id : nodeId , x : Math . round ( node . x ) , y : Math . round ( node . y ) , allowedToMoveX : allowedToMoveX , allowedToMoveY : allowedToMoveY } ) ;
dataArray . push ( { id : nodeId , x : Math . round ( node . x ) , y : Math . round ( node . y ) , allowedToMoveX : allowedToMoveX , allowedToMoveY : allowedToMoveY } ) ;
}
}
}
}
}
}
this . nodesData . update ( dataArray ) ;
this . body . data . nodes . update ( dataArray ) ;
} ;
} ;
/ * *
/ * *
@ -2673,23 +2707,23 @@ Network.prototype.getPositions = function(ids) {
if ( ids !== undefined ) {
if ( ids !== undefined ) {
if ( Array . isArray ( ids ) == true ) {
if ( Array . isArray ( ids ) == true ) {
for ( var i = 0 ; i < ids . length ; i ++ ) {
for ( var i = 0 ; i < ids . length ; i ++ ) {
if ( this . nodes [ ids [ i ] ] !== undefined ) {
var node = this . nodes [ ids [ i ] ] ;
if ( this . body . nodes [ ids [ i ] ] !== undefined ) {
var node = this . body . nodes [ ids [ i ] ] ;
dataArray [ ids [ i ] ] = { x : Math . round ( node . x ) , y : Math . round ( node . y ) } ;
dataArray [ ids [ i ] ] = { x : Math . round ( node . x ) , y : Math . round ( node . y ) } ;
}
}
}
}
}
}
else {
else {
if ( this . nodes [ ids ] !== undefined ) {
var node = this . nodes [ ids ] ;
if ( this . body . nodes [ ids ] !== undefined ) {
var node = this . body . nodes [ ids ] ;
dataArray [ ids ] = { x : Math . round ( node . x ) , y : Math . round ( node . y ) } ;
dataArray [ ids ] = { x : Math . round ( node . x ) , y : Math . round ( node . y ) } ;
}
}
}
}
}
}
else {
else {
for ( var nodeId in this . nodes ) {
if ( this . nodes . hasOwnProperty ( nodeId ) ) {
var node = this . nodes [ nodeId ] ;
for ( var nodeId in this . body . nodes ) {
if ( this . body . nodes . hasOwnProperty ( nodeId ) ) {
var node = this . body . nodes [ nodeId ] ;
dataArray [ nodeId ] = { x : Math . round ( node . x ) , y : Math . round ( node . y ) } ;
dataArray [ nodeId ] = { x : Math . round ( node . x ) , y : Math . round ( node . y ) } ;
}
}
}
}
@ -2706,11 +2740,11 @@ Network.prototype.getPositions = function(ids) {
* @ param { Number } [ options ]
* @ param { Number } [ options ]
* /
* /
Network . prototype . focusOnNode = function ( nodeId , options ) {
Network . prototype . focusOnNode = function ( nodeId , options ) {
if ( this . nodes . hasOwnProperty ( nodeId ) ) {
if ( this . body . nodes . hasOwnProperty ( nodeId ) ) {
if ( options === undefined ) {
if ( options === undefined ) {
options = { } ;
options = { } ;
}
}
var nodePosition = { x : this . nodes [ nodeId ] . x , y : this . nodes [ nodeId ] . y } ;
var nodePosition = { x : this . body . nodes [ nodeId ] . x , y : this . body . nodes [ nodeId ] . y } ;
options . position = nodePosition ;
options . position = nodePosition ;
options . lockedOnNode = nodeId ;
options . lockedOnNode = nodeId ;
@ -2821,7 +2855,7 @@ Network.prototype.animateView = function (options) {
* @ private
* @ private
* /
* /
Network . prototype . _lockedRedraw = function ( ) {
Network . prototype . _lockedRedraw = function ( ) {
var nodePosition = { x : this . nodes [ this . lockedOnNodeId ] . x , y : this . nodes [ this . lockedOnNodeId ] . y } ;
var nodePosition = { x : this . body . nodes [ this . lockedOnNodeId ] . x , y : this . body . nodes [ this . lockedOnNodeId ] . y } ;
var viewCenter = this . DOMtoCanvas ( { x : 0.5 * this . frame . canvas . clientWidth , y : 0.5 * this . frame . canvas . clientHeight } ) ;
var viewCenter = this . DOMtoCanvas ( { x : 0.5 * this . frame . canvas . clientWidth , y : 0.5 * this . frame . canvas . clientHeight } ) ;
var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node
var distanceFromCenter = { // offset from view, distance view has to change by these x and y to center the node
x : viewCenter . x - nodePosition . x ,
x : viewCenter . x - nodePosition . x ,
@ -2909,6 +2943,21 @@ Network.prototype.getScale = function () {
} ;
} ;
/ * *
* Check if a node is a cluster .
* @ param nodeId
* @ returns { * }
* /
Network . prototype . isCluster = function ( nodeId ) {
if ( this . body . nodes [ nodeId ] !== undefined ) {
return this . body . nodes [ nodeId ] . isCluster ;
}
else {
console . log ( "Node does not exist." )
return false ;
}
} ;
/ * *
/ * *
* Returns the scale
* Returns the scale
* @ returns { Number }
* @ returns { Number }
@ -2919,15 +2968,15 @@ Network.prototype.getCenterCoordinates = function () {
Network . prototype . getBoundingBox = function ( nodeId ) {
Network . prototype . getBoundingBox = function ( nodeId ) {
if ( this . nodes [ nodeId ] !== undefined ) {
return this . nodes [ nodeId ] . boundingBox ;
if ( this . body . nodes [ nodeId ] !== undefined ) {
return this . body . nodes [ nodeId ] . boundingBox ;
}
}
}
}
Network . prototype . getConnectedNodes = function ( nodeId ) {
Network . prototype . getConnectedNodes = function ( nodeId ) {
var nodeList = [ ] ;
var nodeList = [ ] ;
if ( this . nodes [ nodeId ] !== undefined ) {
var node = this . nodes [ nodeId ] ;
if ( this . body . nodes [ nodeId ] !== undefined ) {
var node = this . body . nodes [ nodeId ] ;
var nodeObj = { nodeId : true } ; // used to quickly check if node already exists
var nodeObj = { nodeId : true } ; // used to quickly check if node already exists
for ( var i = 0 ; i < node . edges . length ; i ++ ) {
for ( var i = 0 ; i < node . edges . length ; i ++ ) {
var edge = node . edges [ i ] ;
var edge = node . edges [ i ] ;
@ -2951,8 +3000,8 @@ Network.prototype.getConnectedNodes = function(nodeId) {
Network . prototype . getEdgesFromNode = function ( nodeId ) {
Network . prototype . getEdgesFromNode = function ( nodeId ) {
var edgesList = [ ] ;
var edgesList = [ ] ;
if ( this . nodes [ nodeId ] !== undefined ) {
var node = this . nodes [ nodeId ] ;
if ( this . body . nodes [ nodeId ] !== undefined ) {
var node = this . body . nodes [ nodeId ] ;
for ( var i = 0 ; i < node . edges . length ; i ++ ) {
for ( var i = 0 ; i < node . edges . length ; i ++ ) {
edgesList . push ( node . edges [ i ] . id ) ;
edgesList . push ( node . edges [ i ] . id ) ;
}
}