Socket
Socket
Sign inDemoInstall

cytoscape-expand-collapse

Package Overview
Dependencies
Maintainers
6
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cytoscape-expand-collapse - npm Package Compare versions

Comparing version 3.2.1 to 4.0.0

demo-edges-expand-collapse.html

71

gulpfile.js
var gulp = require('gulp');
var path = require('path');
var watch = require('gulp-watch');
var replace = require('gulp-replace');
var child_process = require('child_process');
var fs = require('fs');
var shell = require('gulp-shell');

@@ -26,42 +24,49 @@ var jshint = require('gulp-jshint');

var logError = function( err ){
var logError = function (err) {
notifier.notify({ title: 'cytoscape-expand-collapse', message: 'Error: ' + err.message });
gutil.log( gutil.colors.red('Error in watch:'), gutil.colors.red(err) );
gutil.log(gutil.colors.red('Error in watch:'), gutil.colors.red(err));
};
gulp.task('build', function(){
return browserify( browserifyOpts )
gulp.task('build', function () {
return browserify(browserifyOpts)
.bundle()
.on( 'error', logError )
.pipe( source('cytoscape-expand-collapse.js') )
.pipe( buffer() )
.pipe( derequire() )
.pipe( gulp.dest('.') )
.on('error', logError)
.pipe(source('cytoscape-expand-collapse.js'))
.pipe(buffer())
.pipe(derequire())
.pipe(gulp.dest('.'))
});
gulp.task('default', ['build'], function( next ){
gulp.task('default', ['build'], function (next) {
next();
});
gulp.task('publish', [], function( next ){
// watch for changes in files, run build immediately
gulp.task('dev', ['build'], function () {
watch('src/*.js', () => {
gulp.run('build');
});
});
gulp.task('publish', [], function (next) {
runSequence('confver', 'pkgver', 'push', 'tag', 'npm', next);
});
gulp.task('confver', ['version'], function(){
gulp.task('confver', ['version'], function () {
return gulp.src('.')
.pipe( prompt.confirm({ message: 'Are you sure version `' + version + '` is OK to publish?' }) )
;
.pipe(prompt.confirm({ message: 'Are you sure version `' + version + '` is OK to publish?' }))
;
});
gulp.task('version', function( next ){
gulp.task('version', function (next) {
var now = new Date();
version = process.env['VERSION'];
if( version ){
if (version) {
done();
} else {
exec('git rev-parse HEAD', function( error, stdout, stderr ){
exec('git rev-parse HEAD', function (error, stdout, stderr) {
var sha = stdout.substring(0, 10); // shorten so not huge filename
version = [ 'snapshot', sha, +now ].join('-');
version = ['snapshot', sha, +now].join('-');
done();

@@ -71,3 +76,3 @@ });

function done(){
function done() {
console.log('Using version number `%s` for building', version);

@@ -79,3 +84,3 @@ next();

gulp.task('pkgver', ['version'], function(){
gulp.task('pkgver', ['version'], function () {
return gulp.src([

@@ -85,6 +90,6 @@ 'package.json',

])
.pipe( replace(/\"version\"\:\s*\".*?\"/, '"version": "' + version + '"') )
.pipe(replace(/\"version\"\:\s*\".*?\"/, '"version": "' + version + '"'))
.pipe( gulp.dest('./') )
;
.pipe(gulp.dest('./'))
;
});

@@ -108,5 +113,5 @@

// http://www.jshint.com/docs/options/
gulp.task('lint', function(){
return gulp.src( 'cytoscape-*.js' )
.pipe( jshint({
gulp.task('lint', function () {
return gulp.src('cytoscape-*.js')
.pipe(jshint({
funcscope: true,

@@ -121,8 +126,8 @@ laxbreak: true,

laxcomma: true
}) )
}))
.pipe( jshint.reporter(jshStylish) )
.pipe(jshint.reporter(jshStylish))
.pipe( jshint.reporter('fail') )
;
.pipe(jshint.reporter('fail'))
;
});
MIT License
Copyright (c) 2017 iVis@Bilkent
Copyright (c) 2017 - present, iVis@Bilkent.

@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy

{
"name": "cytoscape-expand-collapse",
"version": "3.2.1",
"version": "4.0.0",
"description": "This extension provides an interface to expand-collapse nodes.",

@@ -34,2 +34,3 @@ "main": "src/index.js",

"gulp-util": "^3.0.6",
"gulp-watch": "^5.0.1",
"jshint-stylish": "^2.0.1",

@@ -36,0 +37,0 @@ "node-notifier": "^4.3.1",

@@ -6,5 +6,9 @@ cytoscape-expand-collapse

This extension provides an interface to expand/collapse nodes for better management of complexity of Cytoscape.js compound graphs, distributed under [The MIT License](https://opensource.org/licenses/MIT).
This extension provides an interface to expand/collapse nodes and edges for better management of complexity of Cytoscape.js compound graphs, distributed under [The MIT License](https://opensource.org/licenses/MIT).
![](https://github.com/iVis-at-Bilkent/cytoscape.js-expand-collapse/blob/master/expand-collapse-extension-demo.gif)
<p align="center">
<img src="expand-collapse-extension-demo.gif" height="240"/>
&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;
<img src="expand-collapse-extension-edge-demo.gif" height="240"/>
</p>

@@ -18,2 +22,3 @@ Please cite the following paper when using this extension:

Click [here](http://ivis-at-bilkent.github.io/cytoscape.js-expand-collapse/demo.html) (no undo and with custom cue image) or [here](http://ivis-at-bilkent.github.io/cytoscape.js-expand-collapse/demo-undoable.html) (undoable) or [here](http://ivis-at-bilkent.github.io/cytoscape.js-expand-collapse/demo-compounds-collapsed.html) (compounds initially collapsed) for a demo.
Click [here](http://ivis-at-bilkent.github.io/cytoscape.js-expand-collapse/demo-edges-expand-collapse.html) for undoable edges expand collapse demo.

@@ -92,2 +97,20 @@ ## API

`api.collapseEdges(edges,options)`
Collapse the given edges if all the given edges are between same two nodes and number of edges passed is at least 2. Does nothing otherwise.
` api.expandEdges(edges){ `
Expand the given collapsed edges
`api.collapseEdgesBetweenNodes(nodes, options)`
Collapse all edges between the set of given nodes.
`api.expandEdgesBetweenNodes(nodes)`
Expand all collapsed edges between the set of given nodes
`api.collapseAllEdges(options)`
Collapse all edges in the graph.
`api.expandAllEdges()`
Expand all edges in the graph.
## Events

@@ -104,3 +127,15 @@ Notice that following events are performed for *each* node that is collapsed/expanded. Also, notice that any post-processing layout is performed *after* the event.

`cy.edges().on("expandcollapse.beforecollapseedge", function(event) { var edge = this; ... })` Triggered before an edge is collapsed
`cy.edges().on("expandcollapse.aftercollapseedge", function(event) { var edge = this; ... })` Triggered after an edge is collapsed
`cy.edges().on("expandcollapse.beforeexpandedge", function(event) { var edge = this; ... })` Triggered before an edge is expanded
`cy.edges().on("expandcollapse.afterexpandedge", function(event) { var edge = this; ... })` Triggered after an edge is expanded
All these events can also be listened as [cytoscape.js core events](https://js.cytoscape.org/#cy.on)
e.g.
`cy.on("expandcollapse.afterexpandedge", function(event) { var elem = event.target; ... })`
## Default Options

@@ -124,2 +159,5 @@ ```javascript

expandCollapseCueSensitivity: 1, // sensitivity of expand-collapse cues
edgeTypeInfo: "edgeType", // the name of the field that has the edge type, retrieved from edge.data(), can be a function, if reading the field returns undefined the collapsed edge type will be "unknown"
groupEdgesOfSameTypeOnCollapse : false, // if true, the edges to be collapsed will be grouped according to their types, and the created collapsed edges will have same type as their group. if false the collapased edge will have "unknown" type.
allowNestedEdgeCollapse: true, // when you want to collapse a compound edge (edge which contains other edges) and normal edge, should it collapse without expanding the compound first
zIndex: 999 // z-index value of the canvas in which cue ımages are drawn

@@ -142,7 +180,28 @@ };

`ur.do("collapseEdges", { edges: eles, options: opts})` Equivalent of eles.collapseEdges(opts)
`ur.do("expandEdges", { edges: eles})` Equivalent of eles.expandEdges()
`ur.do("collapseEdgesBetweenNodes", { nodes: eles, options: opts})` Equivalent of eles.collapseEdgesBetweenNodes(opts)
`ur.do("expandEdgesBetweenNodes", { nodes: eles})` Equivalent of eles.expandEdgesBetweenNodes()
`ur.do("collapseAllEdges", {options: opts)}` Equivalent of cy.collapseAllEdges(opts)
`ur.do("expandAllEdges")`Equivalent of cy.expandAllEdges()
## Elements Style
* Collapsed nodes have 'cy-expand-collapse-collapsed-node' class.
* Meta edges have 'cy-expand-collapse-meta-edge' class.
* Meta edges (edges from/to collapsed nodes) have 'cy-expand-collapse-meta-edge' class.
* Collapsed edges have 'cy-expand-collapse-collapsed-edge' class.
* Collapsed edges data have 'directionType' field which can be either:
- 'unidirection' if all the edges that are collapsed into this edge have the same direction (all have same source and same target)
or
- 'bidirection' if the edges that are collapsed into this edge have different direction (different target and/or source)
* Collapsed edges data have a field that holds the type, the field name is as defined in options but if it is not defined in options or was defined as a function it will be named 'edgeType'
## Dependencies

@@ -193,3 +252,3 @@

* [Hasan Balci](https://github.com/hasanbalci), [Ugur Dogrusoz](https://github.com/ugurdogrusoz) of [i-Vis at Bilkent University](http://www.cs.bilkent.edu.tr/~ivis) and [Metin Can Siper](https://github.com/metincansiper) of the Demir Lab at [OHSU](http://www.ohsu.edu/)
* [Hasan Balci](https://github.com/hasanbalci), [Nasim Saleh](https://github.com/nasimsaleh), [Ugur Dogrusoz](https://github.com/ugurdogrusoz) of [i-Vis at Bilkent University](http://www.cs.bilkent.edu.tr/~ivis) and [Metin Can Siper](https://github.com/metincansiper) of the Demir Lab at [OHSU](http://www.ohsu.edu/)

@@ -196,0 +255,0 @@ ## Alumni

var debounce = require('./debounce');
var debounce2 = require('./debounce2');

@@ -6,6 +7,6 @@ module.exports = function (params, cy, api) {

var fn = params;
const CUE_POS_UPDATE_DELAY = 100;
var nodeWithRenderedCue;
var nodeWithRenderedCue, preventDrawing = false;
const getData = function(){
const getData = function () {
var scratch = cy.scratch('_cyExpandCollapse');

@@ -15,3 +16,3 @@ return scratch && scratch.cueUtilities;

const setData = function( data ){
const setData = function (data) {
var scratch = cy.scratch('_cyExpandCollapse');

@@ -28,7 +29,6 @@ if (scratch == null) {

init: function () {
var self = this;
var $canvas = document.createElement('canvas');
$canvas.classList.add("expand-collapse-canvas");
var $container = cy.container();
var ctx = $canvas.getContext( '2d' );
var ctx = $canvas.getContext('2d');
$container.append($canvas);

@@ -38,9 +38,9 @@

var offset = function(elt) {
var rect = elt.getBoundingClientRect();
var offset = function (elt) {
var rect = elt.getBoundingClientRect();
return {
top: rect.top + document.documentElement.scrollTop,
left: rect.left + document.documentElement.scrollLeft
}
return {
top: rect.top + document.documentElement.scrollTop,
left: rect.left + document.documentElement.scrollLeft
}
}

@@ -63,3 +63,3 @@

// refresh the cues on canvas resize
if(cy){
if (cy) {
clearDraws(true);

@@ -94,2 +94,3 @@ }

ctx.clearRect(0, 0, w, h);
nodeWithRenderedCue = null;
}

@@ -99,6 +100,6 @@

var children = node.children();
var collapsedChildren = node._private.data.collapsedChildren;
var hasChildren = children != null && children.length > 0;
var collapsedChildren = node.data('collapsedChildren');
var hasChildren = children != null && children != undefined && children.length > 0;
// If this is a simple node with no collapsed children return directly
if (!hasChildren && collapsedChildren == null) {
if (!hasChildren && !collapsedChildren) {
return;

@@ -112,12 +113,3 @@ }

var lineSize = options().expandCollapseCueLineSize;
var diff;
var expandcollapseStartX;
var expandcollapseStartY;
var expandcollapseEndX;
var expandcollapseEndY;
var expandcollapseRectSize;
var expandcollapseCenterX;
var expandcollapseCenterY;
var cueCenter;

@@ -127,13 +119,10 @@

var offset = 1;
var size = cy.zoom() < 1 ? rectSize / (2*cy.zoom()) : rectSize / 2;
var size = cy.zoom() < 1 ? rectSize / (2 * cy.zoom()) : rectSize / 2;
var nodeBorderWid = parseFloat(node.css('border-width'));
var x = node.position('x') - node.width() / 2 - parseFloat(node.css('padding-left'))
+ parseFloat(node.css('border-width')) + size + offset;
+ nodeBorderWid + size + offset;
var y = node.position('y') - node.height() / 2 - parseFloat(node.css('padding-top'))
+ parseFloat(node.css('border-width')) + size + offset;
+ nodeBorderWid + size + offset;
cueCenter = {
x : x,
y : y
};
cueCenter = { x: x, y: y };
} else {

@@ -149,23 +138,17 @@ var option = options().expandCollapseCuePosition;

lineSize = Math.max(lineSize, lineSize * cy.zoom());
diff = (rectSize - lineSize) / 2;
var diff = (rectSize - lineSize) / 2;
expandcollapseCenterX = expandcollapseCenter.x;
expandcollapseCenterY = expandcollapseCenter.y;
var expandcollapseCenterX = expandcollapseCenter.x;
var expandcollapseCenterY = expandcollapseCenter.y;
expandcollapseStartX = expandcollapseCenterX - rectSize / 2;
expandcollapseStartY = expandcollapseCenterY - rectSize / 2;
expandcollapseEndX = expandcollapseStartX + rectSize;
expandcollapseEndY = expandcollapseStartY + rectSize;
expandcollapseRectSize = rectSize;
var expandcollapseStartX = expandcollapseCenterX - rectSize / 2;
var expandcollapseStartY = expandcollapseCenterY - rectSize / 2;
var expandcollapseRectSize = rectSize;
// Draw expand/collapse cue if specified use an image else render it in the default way
if (isCollapsed && options().expandCueImage) {
var img=new Image();
img.src = options().expandCueImage;
ctx.drawImage(img, expandcollapseStartX, expandcollapseStartY, rectSize, rectSize);
drawImg(options().expandCueImage, expandcollapseStartX, expandcollapseStartY, rectSize, rectSize);
}
else if (!isCollapsed && options().collapseCueImage) {
var img=new Image();
img.src = options().collapseCueImage;
ctx.drawImage(img, expandcollapseStartX, expandcollapseStartY, rectSize, rectSize);
drawImg(options().collapseCueImage, expandcollapseStartX, expandcollapseStartY, rectSize, rectSize);
}

@@ -207,170 +190,143 @@ else {

node._private.data.expandcollapseRenderedCueSize = expandcollapseRectSize;
nodeWithRenderedCue = node;
}
{
cy.on('resize', data.eCyResize = function () {
sizeCanvas();
});
function drawImg(imgSrc, x, y, w, h) {
var img = new Image(w, h);
img.src = imgSrc;
img.onload = () => {
ctx.drawImage(img, x, y, w, h);
};
}
cy.on('expandcollapse.clearvisualcue', function() {
cy.on('resize', data.eCyResize = function () {
sizeCanvas();
});
if ( nodeWithRenderedCue ) {
clearDraws();
}
});
cy.on('expandcollapse.clearvisualcue', function () {
if (nodeWithRenderedCue) {
clearDraws();
}
});
cy.bind('zoom pan', data.eZoom = function () {
if ( nodeWithRenderedCue ) {
clearDraws();
}
});
var oldMousePos = null, currMousePos = null;
cy.on('mousedown', data.eMouseDown = function (e) {
oldMousePos = e.renderedPosition || e.cyRenderedPosition
});
// check if mouse is inside given node
var isInsideCompound = function(node, e){
if (node){
var currMousePos = e.position || e.cyPosition;
var topLeft = {
x: (node.position("x") - node.width() / 2 - parseFloat(node.css('padding-left'))),
y: (node.position("y") - node.height() / 2 - parseFloat(node.css('padding-top')))};
var bottomRight = {
x: (node.position("x") + node.width() / 2 + parseFloat(node.css('padding-right'))),
y: (node.position("y") + node.height() / 2+ parseFloat(node.css('padding-bottom')))};
cy.on('mouseup', data.eMouseUp = function (e) {
currMousePos = e.renderedPosition || e.cyRenderedPosition
});
if (currMousePos.x >= topLeft.x && currMousePos.y >= topLeft.y &&
currMousePos.x <= bottomRight.x && currMousePos.y <= bottomRight.y){
return true;
}
}
return false;
};
cy.on('remove', 'node', data.eRemove = function () {
clearDraws();
});
cy.on('mousemove', 'node', data.eMouseMove= function(e){
if(!isInsideCompound(nodeWithRenderedCue, e)){
clearDraws()
}
else if(nodeWithRenderedCue && !preventDrawing){
drawExpandCollapseCue(nodeWithRenderedCue);
}
});
var ur;
cy.on('select unselect', data.eSelect = function () {
if (nodeWithRenderedCue) {
clearDraws();
}
var isOnly1Selected = cy.$(':selected').length == 1;
var isOnly1SelectedCompundNode = cy.nodes(':parent').filter(':selected').length == 1 && isOnly1Selected;
var isOnly1SelectedCollapsedNode = cy.nodes('.cy-expand-collapse-collapsed-node').filter(':selected').length == 1 && isOnly1Selected;
if (isOnly1SelectedCollapsedNode || isOnly1SelectedCompundNode) {
drawExpandCollapseCue(cy.nodes(':selected')[0]);
}
});
cy.on('mouseover', 'node', data.eMouseOver = function (e) {
var node = this;
// clear draws if any
if (api.isCollapsible(node) || api.isExpandable(node)){
if ( nodeWithRenderedCue && nodeWithRenderedCue.id() != node.id() ) {
clearDraws();
}
drawExpandCollapseCue(node);
}
});
cy.on('tap', data.eTap = function (event) {
var node = nodeWithRenderedCue;
if (!node) {
return;
}
var expandcollapseRenderedStartX = node.data('expandcollapseRenderedStartX');
var expandcollapseRenderedStartY = node.data('expandcollapseRenderedStartY');
var expandcollapseRenderedRectSize = node.data('expandcollapseRenderedCueSize');
var expandcollapseRenderedEndX = expandcollapseRenderedStartX + expandcollapseRenderedRectSize;
var expandcollapseRenderedEndY = expandcollapseRenderedStartY + expandcollapseRenderedRectSize;
var oldMousePos = null, currMousePos = null;
cy.on('mousedown', data.eMouseDown = function(e){
oldMousePos = e.renderedPosition || e.cyRenderedPosition
});
cy.on('mouseup', data.eMouseUp = function(e){
currMousePos = e.renderedPosition || e.cyRenderedPosition
});
var cyRenderedPos = event.renderedPosition || event.cyRenderedPosition;
var cyRenderedPosX = cyRenderedPos.x;
var cyRenderedPosY = cyRenderedPos.y;
var opts = options();
var factor = (opts.expandCollapseCueSensitivity - 1) / 2;
cy.on('grab', 'node', data.eGrab = function (e) {
preventDrawing = true;
});
if ((Math.abs(oldMousePos.x - currMousePos.x) < 5 && Math.abs(oldMousePos.y - currMousePos.y) < 5)
&& cyRenderedPosX >= expandcollapseRenderedStartX - expandcollapseRenderedRectSize * factor
&& cyRenderedPosX <= expandcollapseRenderedEndX + expandcollapseRenderedRectSize * factor
&& cyRenderedPosY >= expandcollapseRenderedStartY - expandcollapseRenderedRectSize * factor
&& cyRenderedPosY <= expandcollapseRenderedEndY + expandcollapseRenderedRectSize * factor) {
if (opts.undoable && !ur) {
ur = cy.undoRedo({ defaultActions: false });
}
cy.on('free', 'node', data.eFree = function (e) {
preventDrawing = false;
});
if (api.isCollapsible(node)) {
clearDraws();
if (opts.undoable) {
ur.do("collapse", {
nodes: node,
options: opts
});
}
else {
api.collapse(node, opts);
}
}
else if (api.isExpandable(node)) {
clearDraws();
if (opts.undoable) {
ur.do("expand", { nodes: node, options: opts });
}
else {
api.expand(node, opts);
}
}
if (node.selectable()) {
node.unselectify();
cy.scratch('_cyExpandCollapse').selectableChanged = true;
}
}
});
cy.on('position', 'node', data.ePosition = function () {
if (nodeWithRenderedCue)
clearDraws();
});
cy.on('position', 'node', data.ePosition = debounce2(data.eSelect, CUE_POS_UPDATE_DELAY, clearDraws));
cy.on('remove', 'node', data.eRemove = function () {
clearDraws();
nodeWithRenderedCue = null;
});
cy.on('pan zoom', data.ePosition);
var ur;
cy.on('select', 'node', data.eSelect = function(){
if (this.length > cy.nodes(":selected").length)
this.unselect();
});
cy.on('expandcollapse.afterexpand expandcollapse.aftercollapse', 'node', data.eAfterExpandCollapse = function () {
var delay = 50 + params.animate ? params.animationDuration : 0;
setTimeout(() => {
if (this.selected()) {
drawExpandCollapseCue(this);
}
}, delay);
});
cy.on('tap', data.eTap = function (event) {
var node = nodeWithRenderedCue;
var opts = options();
if (node){
var expandcollapseRenderedStartX = node._private.data.expandcollapseRenderedStartX;
var expandcollapseRenderedStartY = node._private.data.expandcollapseRenderedStartY;
var expandcollapseRenderedRectSize = node._private.data.expandcollapseRenderedCueSize;
var expandcollapseRenderedEndX = expandcollapseRenderedStartX + expandcollapseRenderedRectSize;
var expandcollapseRenderedEndY = expandcollapseRenderedStartY + expandcollapseRenderedRectSize;
var cyRenderedPos = event.renderedPosition || event.cyRenderedPosition;
var cyRenderedPosX = cyRenderedPos.x;
var cyRenderedPosY = cyRenderedPos.y;
var factor = (opts.expandCollapseCueSensitivity - 1) / 2;
if ( (Math.abs(oldMousePos.x - currMousePos.x) < 5 && Math.abs(oldMousePos.y - currMousePos.y) < 5)
&& cyRenderedPosX >= expandcollapseRenderedStartX - expandcollapseRenderedRectSize * factor
&& cyRenderedPosX <= expandcollapseRenderedEndX + expandcollapseRenderedRectSize * factor
&& cyRenderedPosY >= expandcollapseRenderedStartY - expandcollapseRenderedRectSize * factor
&& cyRenderedPosY <= expandcollapseRenderedEndY + expandcollapseRenderedRectSize * factor) {
if(opts.undoable && !ur)
ur = cy.undoRedo({
defaultActions: false
});
if(api.isCollapsible(node))
if (opts.undoable){
ur.do("collapse", {
nodes: node,
options: opts
});
}
else
api.collapse(node, opts);
else if(api.isExpandable(node))
if (opts.undoable)
ur.do("expand", {
nodes: node,
options: opts
});
else
api.expand(node, opts);
}
}
});
}
// write options to data
data.hasEventFields = true;
setData( data );
setData(data);
},
unbind: function () {
// var $container = this;
var data = getData();
// var $container = this;
var data = getData();
if (!data.hasEventFields) {
console.log( 'events to unbind does not exist' );
return;
}
if (!data.hasEventFields) {
console.log('events to unbind does not exist');
return;
}
cy.trigger('expandcollapse.clearvisualcue');
cy.trigger('expandcollapse.clearvisualcue');
cy.off('mouseover', 'node', data.eMouseOver)
.off('mousemove', 'node', data.eMouseMove)
.off('mousedown', 'node', data.eMouseDown)
.off('mouseup', 'node', data.eMouseUp)
.off('free', 'node', data.eFree)
.off('grab', 'node', data.eGrab)
.off('position', 'node', data.ePosition)
.off('remove', 'node', data.eRemove)
.off('tap', 'node', data.eTap)
.off('add', 'node', data.eAdd)
.off('select', 'node', data.eSelect)
.off('free', 'node', data.eFree)
.off('zoom pan', data.eZoom)
.off('resize', data.eCyResize);
cy.off('mousedown', 'node', data.eMouseDown)
.off('mouseup', 'node', data.eMouseUp)
.off('remove', 'node', data.eRemove)
.off('tap', 'node', data.eTap)
.off('add', 'node', data.eAdd)
.off('position', 'node', data.ePosition)
.off('pan zoom', data.ePosition)
.off('select unselect', data.eSelect)
.off('expandcollapse.afterexpand expandcollapse.aftercollapse', 'node', data.eAfterExpandCollapse)
.off('free', 'node', data.eFree)
.off('resize', data.eCyResize);
},

@@ -381,19 +337,16 @@ rebind: function () {

if (!data.hasEventFields) {
console.log( 'events to rebind does not exist' );
console.log('events to rebind does not exist');
return;
}
cy.on('mouseover', 'node', data.eMouseOver)
.on('mousemove', 'node', data.eMouseMove)
.on('mousedown', 'node', data.eMouseDown)
cy.on('mousedown', 'node', data.eMouseDown)
.on('mouseup', 'node', data.eMouseUp)
.on('free', 'node', data.eFree)
.on('grab', 'node', data.eGrab)
.on('position', 'node', data.ePosition)
.on('remove', 'node', data.eRemove)
.on('tap', 'node', data.eTap)
.on('add', 'node', data.eAdd)
.on('select', 'node', data.eSelect)
.on('position', 'node', data.ePosition)
.on('pan zoom', data.ePosition)
.on('select unselect', data.eSelect)
.on('expandcollapse.afterexpand expandcollapse.aftercollapse', 'node', data.eAfterExpandCollapse)
.on('free', 'node', data.eFree)
.on('zoom pan', data.eZoom)
.on('resize', data.eCyResize);

@@ -407,7 +360,5 @@ }

return functions.init.apply(cy.container(), arguments);
} else {
throw new Error('No such function `' + fn + '` for cytoscape.js-expand-collapse');
}
throw new Error('No such function `' + fn + '` for cytoscape.js-expand-collapse');
return this;
};

@@ -5,6 +5,8 @@ function elementUtilities(cy) {

var topMostNodes = notCalcTopMostNodes ? nodes : this.getTopMostNodes(nodes);
topMostNodes.positions(function(ele, i){
var nonParents = topMostNodes.not(":parent");
// moving parents spoils positioning, so move only nonparents
nonParents.positions(function(ele, i){
return {
x: topMostNodes[i].position("x") + positionDiff.x,
y: topMostNodes[i].position("y") + positionDiff.y
x: nonParents[i].position("x") + positionDiff.x,
y: nonParents[i].position("y") + positionDiff.y
};

@@ -11,0 +13,0 @@ });

@@ -47,3 +47,3 @@ var boundingBoxUtilities = require('./boundingBoxUtilities');

if (single) {
this.endOperation(layoutBy);
this.endOperation(layoutBy, node);
}

@@ -99,3 +99,3 @@ },

*/
endOperation: function (layoutBy) {
endOperation: function (layoutBy, nodes) {
var self = this;

@@ -105,2 +105,6 @@ cy.ready(function () {

elementUtilities.rearrange(layoutBy);
if(cy.scratch('_cyExpandCollapse').selectableChanged){
nodes.selectify();
cy.scratch('_cyExpandCollapse').selectableChanged = false;
}
}, 0);

@@ -116,3 +120,3 @@

this.endOperation(options.layoutBy);
this.endOperation(options.layoutBy, nodes);

@@ -152,3 +156,3 @@ /*

this.simpleExpandGivenNodes(nodes, options.fisheye);
this.endOperation(options.layoutBy);
this.endOperation(options.layoutBy, nodes);
}

@@ -172,3 +176,3 @@

nodes.trigger("position"); // position not triggered by default when collapseNode is called
this.endOperation(options.layoutBy);
this.endOperation(options.layoutBy, nodes);

@@ -684,6 +688,150 @@ // Update the style

return collapsedChildren;
},
/* -------------------------------------- start section edge expand collapse -------------------------------------- */
collapseGivenEdges: function (edges, options) {
edges.unselect();
var nodes = edges.connectedNodes();
var edgesToCollapse = {};
// group edges by type if this option is set to true
if (options.groupEdgesOfSameTypeOnCollapse) {
edges.forEach(function (edge) {
var edgeType = "unknown";
if (options.edgeTypeInfo !== undefined) {
edgeType = options.edgeTypeInfo instanceof Function ? options.edgeTypeInfo.call(edge) : edge.data()[options.edgeTypeInfo];
}
if (edgesToCollapse.hasOwnProperty(edgeType)) {
edgesToCollapse[edgeType].edges = edgesToCollapse[edgeType].edges.add(edge);
if (edgesToCollapse[edgeType].directionType == "unidirection" && (edgesToCollapse[edgeType].source != edge.source().id() || edgesToCollapse[edgeType].target != edge.target().id())) {
edgesToCollapse[edgeType].directionType = "bidirection";
}
} else {
var edgesX = cy.collection();
edgesX = edgesX.add(edge);
edgesToCollapse[edgeType] = { edges: edgesX, directionType: "unidirection", source: edge.source().id(), target: edge.target().id() }
}
});
} else {
edgesToCollapse["unknown"] = { edges: edges, directionType: "unidirection", source: edges[0].source().id(), target: edges[0].target().id() }
for (var i = 0; i < edges.length; i++) {
if (edgesToCollapse["unknown"].directionType == "unidirection" && (edgesToCollapse["unknown"].source != edges[i].source().id() || edgesToCollapse["unknown"].target != edges[i].target().id())) {
edgesToCollapse["unknown"].directionType = "bidirection";
break;
}
}
}
var result = { edges: cy.collection(), oldEdges: cy.collection() }
var newEdges = [];
for (const edgeGroupType in edgesToCollapse) {
if (edgesToCollapse[edgeGroupType].edges.length < 2) {
continue;
}
edges.trigger('expandcollapse.beforecollapseedge');
result.oldEdges = result.oldEdges.add(edgesToCollapse[edgeGroupType].edges);
var newEdge = {};
newEdge.group = "edges";
newEdge.data = {};
newEdge.data.source = edgesToCollapse[edgeGroupType].source;
newEdge.data.target = edgesToCollapse[edgeGroupType].target;
newEdge.data.id = "collapsedEdge_" + nodes[0].id() + "_" + nodes[1].id() + "_" + edgeGroupType + "_" + Math.floor(Math.random() * Date.now());
newEdge.data.collapsedEdges = cy.collection();
edgesToCollapse[edgeGroupType].edges.forEach(function (edge) {
newEdge.data.collapsedEdges = newEdge.data.collapsedEdges.add(edge);
});
newEdge.data.collapsedEdges = this.check4nestedCollapse(newEdge.data.collapsedEdges, options);
var edgesTypeField = "edgeType";
if (options.edgeTypeInfo !== undefined) {
edgesTypeField = options.edgeTypeInfo instanceof Function ? edgeTypeField : options.edgeTypeInfo;
}
newEdge.data[edgesTypeField] = edgeGroupType;
newEdge.data["directionType"] = edgesToCollapse[edgeGroupType].directionType;
newEdge.classes = "cy-expand-collapse-collapsed-edge";
newEdges.push(newEdge);
cy.remove(edgesToCollapse[edgeGroupType].edges);
edges.trigger('expandcollapse.aftercollapseedge');
}
result.edges = cy.add(newEdges);
return result;
},
check4nestedCollapse: function(edges2collapse, options){
if (options.allowNestedEdgeCollapse) {
return edges2collapse;
}
let r = cy.collection();
for (let i = 0; i < edges2collapse.length; i++) {
let curr = edges2collapse[i];
let collapsedEdges = curr.data('collapsedEdges');
if (collapsedEdges && collapsedEdges.length > 0) {
r = r.add(collapsedEdges);
} else {
r = r.add(curr);
}
}
return r;
},
expandEdge: function (edge) {
edge.unselect();
var result = { edges: cy.collection(), oldEdges: cy.collection() }
var edges = edge.data('collapsedEdges');
if (edges !== undefined && edges.length > 0) {
edge.trigger('expandcollapse.beforeexpandedge');
result.oldEdges = result.oldEdges.add(edge);
cy.remove(edge);
result.edges = cy.add(edges);
edge.trigger('expandcollapse.afterexpandedge');
}
return result;
},
//if the edges are only between two nodes (valid for collpasing) returns the two nodes else it returns false
isValidEdgesForCollapse: function (edges) {
var endPoints = this.getEdgesDistinctEndPoints(edges);
if (endPoints.length != 2) {
return false;
} else {
return endPoints;
}
},
//returns a list of distinct endpoints of a set of edges.
getEdgesDistinctEndPoints: function (edges) {
var endPoints = [];
edges.forEach(function (edge) {
if (!this.containsElement(endPoints, edge.source())) {
endPoints.push(edge.source());
}
if (!this.containsElement(endPoints, edge.target())) {
endPoints.push(edge.target());
}
}.bind(this));
return endPoints;
},
//function to check if a list of elements contains the given element by looking at id()
containsElement: function (elements, element) {
var exists = false;
for (var i = 0; i < elements.length; i++) {
if (elements[i].id() == element.id()) {
exists = true;
break;
}
}
return exists;
}
/* -------------------------------------- end section edge expand collapse -------------------------------------- */
}
};
module.exports = expandCollapseUtilities;

@@ -234,2 +234,126 @@ ;

api.collapseEdges = function(edges,opts){
var result = {edges: cy.collection(), oldEdges: cy.collection()};
if(edges.length < 2) return result ;
if(edges.connectedNodes().length > 2) return result;
var options = getScratch(cy, 'options');
var tempOptions = extendOptions(options, opts);
return expandCollapseUtilities.collapseGivenEdges(edges, tempOptions);
};
api.expandEdges = function(edges){
var result = {edges: cy.collection(), oldEdges: cy.collection()}
if(edges === undefined) return result;
//if(typeof edges[Symbol.iterator] === 'function'){//collection of edges is passed
edges.forEach(function(edge){
var operationResult = expandCollapseUtilities.expandEdge(edge);
result.edges = result.edges.add(operationResult.edges);
result.oldEdges = result.oldEdges.add(operationResult.oldEdges);
});
/* }else{//one edge passed
var operationResult = expandCollapseUtilities.expandEdge(edges);
result.edges = result.edges.add(operationResult.edges);
result.oldEdges = result.oldEdges.add(operationResult.oldEdges);
} */
return result;
};
api.collapseEdgesBetweenNodes = function(nodes, opts){
var options = getScratch(cy, 'options');
var tempOptions = extendOptions(options, opts);
function pairwise(list) {
var pairs = [];
list
.slice(0, list.length - 1)
.forEach(function (first, n) {
var tail = list.slice(n + 1, list.length);
tail.forEach(function (item) {
pairs.push([first, item])
});
})
return pairs;
}
var nodesPairs = pairwise(nodes);
var result = {edges: cy.collection(), oldEdges: cy.collection()};
nodesPairs.forEach(function(nodePair){
var edges = nodePair[0].connectedEdges('[source = "'+ nodePair[1].id()+'"],[target = "'+ nodePair[1].id()+'"]');
if(edges.length >= 2){
var operationResult = expandCollapseUtilities.collapseGivenEdges(edges, tempOptions)
result.oldEdges = result.oldEdges.add(operationResult.oldEdges);
result.edges = result.edges.add(operationResult.edges);
}
}.bind(this));
return result;
};
api.expandEdgesBetweenNodes = function(nodes){
if(nodes.length <= 1) cy.collection();
var edgesToExpand = cy.collection();
function pairwise(list) {
var pairs = [];
list
.slice(0, list.length - 1)
.forEach(function (first, n) {
var tail = list.slice(n + 1, list.length);
tail.forEach(function (item) {
pairs.push([first, item])
});
})
return pairs;
}
//var result = {edges: cy.collection(), oldEdges: cy.collection()} ;
var nodesPairs = pairwise(nodes);
nodesPairs.forEach(function(nodePair){
var edges = nodePair[0].connectedEdges('.cy-expand-collapse-collapsed-edge[source = "'+ nodePair[1].id()+'"],[target = "'+ nodePair[1].id()+'"]');
edgesToExpand = edgesToExpand.union(edges);
}.bind(this));
//result.oldEdges = result.oldEdges.add(edgesToExpand);
//result.edges = result.edges.add(this.expandEdges(edgesToExpand));
return this.expandEdges(edgesToExpand);
};
api.collapseAllEdges = function(opts){
var options = getScratch(cy, 'options');
var tempOptions = extendOptions(options, opts);
function pairwise(list) {
var pairs = [];
list
.slice(0, list.length - 1)
.forEach(function (first, n) {
var tail = list.slice(n + 1, list.length);
tail.forEach(function (item) {
pairs.push([first, item])
});
})
return pairs;
}
return this.collapseEdgesBetweenNodes(cy.edges().connectedNodes(),opts);
/* var nodesPairs = pairwise(cy.edges().connectedNodes());
nodesPairs.forEach(function(nodePair){
var edges = nodePair[0].connectedEdges('[source = "'+ nodePair[1].id()+'"],[target = "'+ nodePair[1].id()+'"]');
if(edges.length >=2){
expandCollapseUtilities.collapseGivenEdges(edges, tempOptions);
}
}.bind(this)); */
};
api.expandAllEdges = function(){
var edges = cy.edges(".cy-expand-collapse-collapsed-edge");
var result = {edges:cy.collection(), oldEdges : cy.collection()};
var operationResult = this.expandEdges(edges);
result.oldEdges = result.oldEdges.add(operationResult.oldEdges);
result.edges = result.edges.add(operationResult.edges);
return result;
};
return api; // Return the API instance

@@ -273,2 +397,6 @@ }

expandCollapseCueSensitivity: 1, // sensitivity of expand-collapse cues
edgeTypeInfo : "edgeType", //the name of the field that has the edge type, retrieved from edge.data(), can be a function
groupEdgesOfSameTypeOnCollapse: false,
allowNestedEdgeCollapse: true,
zIndex: 999 // z-index value of the canvas in which cue ımages are drawn

@@ -275,0 +403,0 @@ };

@@ -80,2 +80,151 @@ module.exports = function (cy, api) {

function collapseEdges(args){
var options = args.options;
var edges = args.edges;
var result = {};
result.options = options;
if(args.firstTime){
var collapseResult = api.collapseEdges(edges,options);
result.edges = collapseResult.edges;
result.oldEdges = collapseResult.oldEdges;
result.firstTime = false;
}else{
result.oldEdges = edges;
result.edges = args.oldEdges;
if(args.edges.length > 0 && args.oldEdges.length > 0){
cy.remove(args.edges);
cy.add(args.oldEdges);
}
}
return result;
}
function collapseEdgesBetweenNodes(args){
var options = args.options;
var result = {};
result.options = options;
if(args.firstTime){
var collapseAllResult = api.collapseEdgesBetweenNodes(args.nodes, options);
result.edges = collapseAllResult.edges;
result.oldEdges = collapseAllResult.oldEdges;
result.firstTime = false;
}else{
result.edges = args.oldEdges;
result.oldEdges = args.edges;
if(args.edges.length > 0 && args.oldEdges.length > 0){
cy.remove(args.edges);
cy.add(args.oldEdges);
}
}
return result;
}
function collapseAllEdges(args){
var options = args.options;
var result = {};
result.options = options;
if(args.firstTime){
var collapseAllResult = api.collapseAllEdges(options);
result.edges = collapseAllResult.edges;
result.oldEdges = collapseAllResult.oldEdges;
result.firstTime = false;
}else{
result.edges = args.oldEdges;
result.oldEdges = args.edges;
if(args.edges.length > 0 && args.oldEdges.length > 0){
cy.remove(args.edges);
cy.add(args.oldEdges);
}
}
return result;
}
function expandEdges(args){
var options = args.options;
var result ={};
result.options = options;
if(args.firstTime){
var expandResult = api.expandEdges(args.edges);
result.edges = expandResult.edges;
result.oldEdges = expandResult.oldEdges;
result.firstTime = false;
}else{
result.oldEdges = args.edges;
result.edges = args.oldEdges;
if(args.edges.length > 0 && args.oldEdges.length > 0){
cy.remove(args.edges);
cy.add(args.oldEdges);
}
}
return result;
}
function expandEdgesBetweenNodes(args){
var options = args.options;
var result = {};
result.options = options;
if(args.firstTime){
var collapseAllResult = api.expandEdgesBetweenNodes(args.nodes,options);
result.edges = collapseAllResult.edges;
result.oldEdges = collapseAllResult.oldEdges;
result.firstTime = false;
}else{
result.edges = args.oldEdges;
result.oldEdges = args.edges;
if(args.edges.length > 0 && args.oldEdges.length > 0){
cy.remove(args.edges);
cy.add(args.oldEdges);
}
}
return result;
}
function expandAllEdges(args){
var options = args.options;
var result = {};
result.options = options;
if(args.firstTime){
var expandResult = api.expandAllEdges(options);
result.edges = expandResult.edges;
result.oldEdges = expandResult.oldEdges;
result.firstTime = false;
}else{
result.edges = args.oldEdges;
result.oldEdges = args.edges;
if(args.edges.length > 0 && args.oldEdges.length > 0){
cy.remove(args.edges);
cy.add(args.oldEdges);
}
}
return result;
}
ur.action("collapseEdges", collapseEdges, expandEdges);
ur.action("expandEdges", expandEdges, collapseEdges);
ur.action("collapseEdgesBetweenNodes", collapseEdgesBetweenNodes, expandEdgesBetweenNodes);
ur.action("expandEdgesBetweenNodes", expandEdgesBetweenNodes, collapseEdgesBetweenNodes);
ur.action("collapseAllEdges", collapseAllEdges, expandAllEdges);
ur.action("expandAllEdges", expandAllEdges, collapseAllEdges);
};

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc