cytoscape-automove
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -7,2 +7,3 @@ ;(function(){ 'use strict'; | ||
// - a selector that matches the nodes | ||
// - a collection or array of nodes (very good for performance) | ||
nodesMatching: function( node ){ return false; }, | ||
@@ -19,3 +20,3 @@ | ||
// calls update() when reposition updates should occur | ||
// - function( update ){ /* ... */ } => a manual function for updating | ||
// - function( update ){ /* ... */ update(); } => a manual function for updating | ||
// - 'matching' => automatically update on position events for nodesMatching | ||
@@ -32,5 +33,7 @@ // - set efficiently and automatically for | ||
var typeofObj = typeof {}; | ||
var typeofFn = typeof function(){}; | ||
var isObject = function( x ){ return typeof x === typeofObj; }; | ||
var isString = function( x ){ return typeof x === typeofStr; }; | ||
var isFunction = function( x ){ return typeof x === typeofFn; }; | ||
@@ -50,10 +53,6 @@ // Object.assign() polyfill | ||
var requestAnimationFrame = ( window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame ).bind( window ); | ||
var onNextTick = function( fn ){ | ||
setTimeout( fn, 0 ); | ||
}; | ||
var eleMatchesSpec = function( ele, spec ){ | ||
if( isString( spec ) ){ | ||
if( ele == null || ele.removed() ){ | ||
return false; | ||
} else if( isString( spec ) ){ | ||
return ele.is( spec ); | ||
@@ -68,8 +67,8 @@ } else { | ||
var bind = function( cy, events, selector, fn ){ | ||
cy.on( events, 'node', fn ); | ||
var b = { cy: cy, events: events, selector: selector || 'node', fn: fn }; | ||
var b = { cy: cy, events: events, selector: 'node', fn: fn }; | ||
bindings.push( b ); | ||
cy.on( b.events, b.selector, b.fn ); | ||
return b; | ||
@@ -115,14 +114,22 @@ }; | ||
var meanNeighborhoodPosition = function( node ){ | ||
var nhood = node.neighbourhood().nodes(); | ||
var currPos = node.position(); | ||
var nhood = node.neighborhood(); | ||
var avgPos = { x: 0, y: 0 }; | ||
var nhoodSize = 0; | ||
for( var i = 0; i < nhood.length; i++ ){ | ||
var pos = nhood[i].position(); | ||
var nhoodEle = nhood[i]; | ||
avgPos.x += pos.x; | ||
avgPos.y += pos.y; | ||
if( nhoodEle.isNode() ){ | ||
var pos = nhoodEle.position(); | ||
avgPos.x += pos.x; | ||
avgPos.y += pos.y; | ||
nhoodSize++; | ||
} | ||
} | ||
avgPos.x /= nhood.length; | ||
avgPos.y /= nhood.length; | ||
avgPos.x /= nhoodSize; | ||
avgPos.y /= nhoodSize; | ||
@@ -169,9 +176,24 @@ return avgPos; | ||
return function( update, cy ){ | ||
let matches = function( ele ){ | ||
// must meet ele set and be connected to more than (1 edge + 1 node) | ||
return rule.matches( ele ) && ele.neighborhood().length > 2; | ||
}; | ||
bindOnRule( rule, cy, 'position', 'node', function(){ | ||
var movedNode = this; | ||
if( movedNode.closedNeighborhood().some( rule.matches ) ){ | ||
if( movedNode.neighborhood().some( matches ) ){ | ||
update( cy, [ rule ] ); | ||
} | ||
}); | ||
bindOnRule( rule, cy, 'add remove', 'edge', function(){ | ||
var edge = this; | ||
var src = cy.getElementById( edge.data('source') ); | ||
var tgt = cy.getElementById( edge.data('target') ); | ||
if( [ src, tgt ].some( matches ) ){ | ||
update( cy, [ rule ] ); | ||
} | ||
}); | ||
}; | ||
@@ -210,5 +232,13 @@ }; | ||
rule.getNewPos = getRepositioner( rule.reposition, cy ); | ||
rule.matches = function( ele ){ return eleMatchesSpec( ele, rule.nodesMatching ); }; | ||
rule.listener = getListener( cy, rule ); | ||
var nodesAreCollection = isObject( rule.nodesMatching ) && isFunction( rule.nodesMatching.collection ); | ||
if( nodesAreCollection ){ | ||
rule.nodes = rule.nodesMatching; | ||
rule.matches = function( ele ){ return ele != null && rule.nodes.intersection( ele ).length > 0; }; | ||
} else { | ||
rule.matches = function( ele ){ return eleMatchesSpec( ele, rule.nodesMatching ); }; | ||
} | ||
rule.listener( function(){ | ||
@@ -225,5 +255,18 @@ update( cy, [ rule ] ); | ||
var bindForNodeList = function( cy, scratch ){ | ||
scratch.onAddNode = function( evt ){ | ||
var target = evt.target; | ||
scratch.nodes.push( target ); | ||
}; | ||
cy.on('add', 'node', scratch.onAddNode); | ||
}; | ||
var unbindForNodeList = function( cy, scratch ){ | ||
cy.removeListener('add', 'node', scratch.onAddNode); | ||
}; | ||
var update = function( cy, rules ){ | ||
var scratch = cy.scratch().automove; | ||
var nodes = cy.nodes(); | ||
@@ -233,10 +276,17 @@ rules = rules != null ? rules : scratch.rules; | ||
cy.batch(function(){ // batch for performance | ||
for( var i = 0; i < nodes.length; i++ ){ | ||
var node = nodes[i]; | ||
for( var i = 0; i < rules.length; i++ ){ | ||
var rule = rules[i]; | ||
for( var j = 0; j < rules.length; j++ ){ | ||
var rule = rules[j]; | ||
if( rule.destroyed || !rule.enabled ){ break; } // ignore destroyed rules b/c user may use custom when() | ||
if( rule.destroyed || !rule.enabled ){ break; } // ignore destroyed rules b/c user may use custom when() | ||
var nodes = rule.nodes || scratch.nodes; | ||
for( var j = nodes.length - 1; j >= 0; j-- ){ | ||
var node = nodes[j]; | ||
if( node.removed() ){ // remove from list for perf | ||
nodes.splice( j, 1 ); | ||
continue; | ||
} | ||
if( !rule.matches(node) ){ continue; } | ||
@@ -250,2 +300,4 @@ | ||
node.position( newPos ); | ||
node.trigger('automove'); | ||
} | ||
@@ -269,5 +321,14 @@ } | ||
if( scratch.rules.length === 0 ){ | ||
scratch.nodes = cy.nodes().toArray(); | ||
bindForNodeList( cy, scratch ); | ||
} | ||
if( options === 'destroy' ){ | ||
scratch.rules.forEach(function( r ){ r.destroy(); }); | ||
scratch.rules.splice( 0, scratch.rules.length ); | ||
unbindForNodeList( cy, scratch ); | ||
return; | ||
@@ -281,2 +342,6 @@ } | ||
return { | ||
apply: function(){ | ||
update( cy, [ rule ] ); | ||
}, | ||
disable: function(){ | ||
@@ -309,2 +374,6 @@ this.toggle( false ); | ||
if( rules.length === 0 ){ | ||
unbindForNodeList( cy, scratch ); | ||
} | ||
return this; | ||
@@ -311,0 +380,0 @@ } |
{ | ||
"name": "cytoscape-automove", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"description": "An extension for Cytoscape.js that automatically updates node positions based on specified rules", | ||
@@ -5,0 +5,0 @@ "main": "cytoscape-automove.js", |
@@ -58,2 +58,3 @@ cytoscape-automove | ||
// - a selector that matches the nodes | ||
// - a collection or array of nodes (very good for performance) | ||
nodesMatching: function( node ){ return false; }, | ||
@@ -88,2 +89,4 @@ | ||
```js | ||
rule.apply(); // manually apply a rule | ||
rule.enabled(); // get whether rule is enabled | ||
@@ -106,3 +109,7 @@ | ||
## Events | ||
- `automove` : Emitted on a node when its position is changed by a rule | ||
## Publishing instructions | ||
@@ -109,0 +116,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
21317
394
119
2