cytoscape-expand-collapse
Advanced tools
Comparing version 3.2.1 to 4.0.0
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"/> | ||
        | ||
<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; |
128
src/index.js
@@ -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
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
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
1870288
26
4419
251
3
1
14