cytoscape-expand-collapse
Advanced tools
Comparing version 4.0.0 to 4.1.0
{ | ||
"name": "cytoscape-expand-collapse", | ||
"version": "4.0.0", | ||
"version": "4.1.0", | ||
"description": "This extension provides an interface to expand-collapse nodes.", | ||
"main": "src/index.js", | ||
"main": "cytoscape-expand-collapse.js", | ||
"spm": { | ||
"main": "src/index.js" | ||
"main": "cytoscape-expand-collapse.js" | ||
}, | ||
"scripts": { | ||
"build": "echo 'node version must be 10!' && gulp build", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
@@ -28,3 +29,3 @@ }, | ||
"gulp": "^3.9.0", | ||
"gulp-derequire": "^2.1.0", | ||
"gulp-derequire": "^3.0.0", | ||
"gulp-jshint": "^1.11.2", | ||
@@ -31,0 +32,0 @@ "gulp-prompt": "^0.1.2", |
@@ -20,4 +20,3 @@ cytoscape-expand-collapse | ||
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. | ||
Click [here](http://ivis-at-bilkent.github.io/cytoscape.js-expand-collapse/demo/demo.html) (no undo and with custom cue image) or [here](http://ivis-at-bilkent.github.io/cytoscape.js-expand-collapse/demo/demo-undoable.html) (undoable) or [here](http://ivis-at-bilkent.github.io/cytoscape.js-expand-collapse/demo/demo-compounds-collapsed.html) (compounds initially collapsed) for a demo. | ||
@@ -114,2 +113,8 @@ ## API | ||
`api.loadJson(jsonStr)` | ||
Load elements from JSON string. | ||
`api.saveJson(elems, filename)` | ||
Saves elements in JSON format to a file. Default value for `elems` is all the elements. Default value for `filename` is 'expand-collapse-output.json' | ||
## Events | ||
@@ -248,3 +253,3 @@ 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. | ||
* [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/) | ||
* [Hasan Balci](https://github.com/hasanbalci), [Nasim Saleh](https://github.com/nasimsaleh), [Yusuf Canbaz](https://github.com/canbax), [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/) | ||
@@ -251,0 +256,0 @@ ## Alumni |
@@ -211,4 +211,7 @@ var debounce = require('./debounce'); | ||
cy.on('remove', 'node', data.eRemove = function () { | ||
clearDraws(); | ||
cy.on('remove', 'node', data.eRemove = function (evt) { | ||
const node = evt.target; | ||
if (node == nodeWithRenderedCue) { | ||
clearDraws(); | ||
} | ||
}); | ||
@@ -221,8 +224,11 @@ | ||
} | ||
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]); | ||
var selectedNodes = cy.nodes(':selected'); | ||
if (selectedNodes.length !== 1) { | ||
return; | ||
} | ||
var selectedNode = selectedNodes[0]; | ||
if (selectedNode.isParent() || selectedNode.hasClass('cy-expand-collapse-collapsed-node')) { | ||
drawExpandCollapseCue(selectedNode); | ||
} | ||
}); | ||
@@ -284,2 +290,4 @@ | ||
cy.on('afterUndo afterRedo', data.eUndoRedo = data.eSelect); | ||
cy.on('position', 'node', data.ePosition = debounce2(data.eSelect, CUE_POS_UPDATE_DELAY, clearDraws)); | ||
@@ -289,11 +297,2 @@ | ||
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); | ||
}); | ||
// write options to data | ||
@@ -322,5 +321,5 @@ data.hasEventFields = true; | ||
.off('select unselect', data.eSelect) | ||
.off('expandcollapse.afterexpand expandcollapse.aftercollapse', 'node', data.eAfterExpandCollapse) | ||
.off('free', 'node', data.eFree) | ||
.off('resize', data.eCyResize); | ||
.off('resize', data.eCyResize) | ||
.off('afterUndo afterRedo', data.eUndoRedo); | ||
}, | ||
@@ -343,5 +342,5 @@ rebind: function () { | ||
.on('select unselect', data.eSelect) | ||
.on('expandcollapse.afterexpand expandcollapse.aftercollapse', 'node', data.eAfterExpandCollapse) | ||
.on('free', 'node', data.eFree) | ||
.on('resize', data.eCyResize); | ||
.on('resize', data.eCyResize) | ||
.on('afterUndo afterRedo', data.eUndoRedo); | ||
} | ||
@@ -348,0 +347,0 @@ }; |
@@ -452,3 +452,3 @@ var boundingBoxUtilities = require('./boundingBoxUtilities'); | ||
// If there is no sibling call expand node base function here else it is to be called one of fishEyeViewMoveNode() calls | ||
if (siblings.length == 0) { | ||
if (siblings.length == 0 && node.same(nodeToExpand)) { | ||
this.expandNodeBaseFunction(nodeToExpand, single, layoutBy); | ||
@@ -493,4 +493,3 @@ } | ||
if (!single || !animate) { | ||
node._private.position.x = newPosition.x; | ||
node._private.position.y = newPosition.y; | ||
node.position(newPosition); // at this point, position should be updated | ||
} | ||
@@ -732,3 +731,8 @@ else { | ||
newEdge.data.target = edgesToCollapse[edgeGroupType].target; | ||
newEdge.data.id = "collapsedEdge_" + nodes[0].id() + "_" + nodes[1].id() + "_" + edgeGroupType + "_" + Math.floor(Math.random() * Date.now()); | ||
var id1 = nodes[0].id(); | ||
var id2 = id1; | ||
if (nodes[1]) { | ||
id2 = nodes[1].id(); | ||
} | ||
newEdge.data.id = "collapsedEdge_" + id1 + "_" + id2 + "_" + edgeGroupType + "_" + Math.floor(Math.random() * Date.now()); | ||
newEdge.data.collapsedEdges = cy.collection(); | ||
@@ -735,0 +739,0 @@ |
229
src/index.js
@@ -1,2 +0,1 @@ | ||
; | ||
(function () { | ||
@@ -14,2 +13,3 @@ 'use strict'; | ||
var cueUtilities = require("./cueUtilities"); | ||
var saveLoadUtils = null; | ||
@@ -26,3 +26,3 @@ function extendOptions(options, extendBy) { | ||
} | ||
// evaluate some specific options in case of they are specified as functions to be dynamically changed | ||
@@ -32,7 +32,7 @@ function evalOptions(options) { | ||
var fisheye = typeof options.fisheye === 'function' ? options.fisheye.call() : options.fisheye; | ||
options.animate = animate; | ||
options.fisheye = fisheye; | ||
} | ||
// creates and returns the API instance for the extension | ||
@@ -43,8 +43,8 @@ function createExtensionAPI(cy, expandCollapseUtilities) { | ||
function handleNewOptions( opts ) { | ||
function handleNewOptions(opts) { | ||
var currentOpts = getScratch(cy, 'options'); | ||
if ( opts.cueEnabled && !currentOpts.cueEnabled ) { | ||
if (opts.cueEnabled && !currentOpts.cueEnabled) { | ||
api.enableCue(); | ||
} | ||
else if ( !opts.cueEnabled && currentOpts.cueEnabled ) { | ||
else if (!opts.cueEnabled && currentOpts.cueEnabled) { | ||
api.disableCue(); | ||
@@ -54,4 +54,27 @@ } | ||
function isOnly1Pair(edges) { | ||
let relatedEdgesArr = []; | ||
for (let i = 0; i < edges.length; i++) { | ||
const srcId = edges[i].source().id(); | ||
const targetId = edges[i].target().id(); | ||
const obj = {}; | ||
obj[srcId] = true; | ||
obj[targetId] = true; | ||
relatedEdgesArr.push(obj); | ||
} | ||
for (let i = 0; i < relatedEdgesArr.length; i++) { | ||
for (let j = i + 1; j < relatedEdgesArr.length; j++) { | ||
const keys1 = Object.keys(relatedEdgesArr[i]); | ||
const keys2 = Object.keys(relatedEdgesArr[j]); | ||
const allKeys = new Set(keys1.concat(keys2)); | ||
if (allKeys.size != keys1.length || allKeys.size != keys2.length) { | ||
return false; | ||
} | ||
} | ||
} | ||
return true; | ||
} | ||
// set all options at once | ||
api.setOptions = function(opts) { | ||
api.setOptions = function (opts) { | ||
handleNewOptions(opts); | ||
@@ -61,5 +84,5 @@ setScratch(cy, 'options', opts); | ||
api.extendOptions = function(opts) { | ||
api.extendOptions = function (opts) { | ||
var options = getScratch(cy, 'options'); | ||
var newOptions = extendOptions( options, opts ); | ||
var newOptions = extendOptions(options, opts); | ||
handleNewOptions(newOptions); | ||
@@ -72,6 +95,6 @@ setScratch(cy, 'options', newOptions); | ||
var opts = {}; | ||
opts[ name ] = value; | ||
opts[name] = value; | ||
var options = getScratch(cy, 'options'); | ||
var newOptions = extendOptions( options, opts ); | ||
var newOptions = extendOptions(options, opts); | ||
@@ -163,3 +186,3 @@ handleNewOptions(newOptions); | ||
return nodes.filter(function (ele, i) { | ||
if(typeof ele === "number") { | ||
if (typeof ele === "number") { | ||
ele = i; | ||
@@ -176,3 +199,3 @@ } | ||
return nodes.filter(function (ele, i) { | ||
if(typeof ele === "number") { | ||
if (typeof ele === "number") { | ||
ele = i; | ||
@@ -183,3 +206,3 @@ } | ||
}; | ||
// Get the children of the given collapsed node which are removed during collapse operation | ||
@@ -195,3 +218,3 @@ api.getCollapsedChildren = function (node) { | ||
*/ | ||
api.getCollapsedChildrenRecursively = function(node) { | ||
api.getCollapsedChildrenRecursively = function (node) { | ||
var collapsedChildren = cy.collection(); | ||
@@ -205,8 +228,8 @@ return expandCollapseUtilities.getCollapsedChildrenRecursively(node, collapsedChildren); | ||
*/ | ||
api.getAllCollapsedChildrenRecursively = function(){ | ||
api.getAllCollapsedChildrenRecursively = function () { | ||
var collapsedChildren = cy.collection(); | ||
var collapsedNodes = cy.nodes(".cy-expand-collapse-collapsed-node"); | ||
var j; | ||
for (j=0; j < collapsedNodes.length; j++){ | ||
collapsedChildren = collapsedChildren.union(this.getCollapsedChildrenRecursively(collapsedNodes[j])); | ||
for (j = 0; j < collapsedNodes.length; j++) { | ||
collapsedChildren = collapsedChildren.union(this.getCollapsedChildrenRecursively(collapsedNodes[j])); | ||
} | ||
@@ -216,7 +239,7 @@ return collapsedChildren; | ||
// This method forces the visual cue to be cleared. It is to be called in extreme cases | ||
api.clearVisualCue = function(node) { | ||
api.clearVisualCue = function (node) { | ||
cy.trigger('expandcollapse.clearvisualcue'); | ||
}; | ||
api.disableCue = function() { | ||
api.disableCue = function () { | ||
var options = getScratch(cy, 'options'); | ||
@@ -229,3 +252,3 @@ if (options.cueEnabled) { | ||
api.enableCue = function() { | ||
api.enableCue = function () { | ||
var options = getScratch(cy, 'options'); | ||
@@ -238,8 +261,8 @@ if (!options.cueEnabled) { | ||
api.getParent = function(nodeId) { | ||
if(cy.getElementById(nodeId)[0] === undefined){ | ||
api.getParent = function (nodeId) { | ||
if (cy.getElementById(nodeId)[0] === undefined) { | ||
var parentData = getScratch(cy, 'parentData'); | ||
return parentData[nodeId]; | ||
} | ||
else{ | ||
else { | ||
return cy.getElementById(nodeId).parent(); | ||
@@ -249,34 +272,34 @@ } | ||
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; | ||
api.collapseEdges = function (edges, opts) { | ||
var result = { edges: cy.collection(), oldEdges: cy.collection() }; | ||
if (edges.length < 2) return result; | ||
if (!isOnly1Pair(edges)) return result; | ||
var options = getScratch(cy, 'options'); | ||
var tempOptions = extendOptions(options, opts); | ||
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; | ||
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); | ||
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){ | ||
api.collapseEdgesBetweenNodes = function (nodes, opts) { | ||
var options = getScratch(cy, 'options'); | ||
var tempOptions = extendOptions(options, opts); | ||
var tempOptions = extendOptions(options, opts); | ||
function pairwise(list) { | ||
@@ -295,19 +318,25 @@ var 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){ | ||
// for self-loops | ||
nodesPairs.push(...nodes.map(x => [x, x])); | ||
var result = { edges: cy.collection(), oldEdges: cy.collection() }; | ||
nodesPairs.forEach(function (nodePair) { | ||
const id1 = nodePair[1].id(); | ||
var edges = nodePair[0].connectedEdges('[source = "' + id1 + '"],[target = "' + id1 + '"]'); | ||
// edges for self-loops | ||
if (nodePair[0].id() === id1) { | ||
edges = nodePair[0].connectedEdges('[source = "' + id1 + '"][target = "' + id1 + '"]'); | ||
} | ||
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)); | ||
} | ||
}.bind(this)); | ||
return result; | ||
}; | ||
api.expandEdgesBetweenNodes = function(nodes){ | ||
if(nodes.length <= 1) cy.collection(); | ||
api.expandEdgesBetweenNodes = function (nodes) { | ||
var edgesToExpand = cy.collection(); | ||
@@ -326,51 +355,38 @@ function pairwise(list) { | ||
} | ||
//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); | ||
// for self-loops | ||
nodesPairs.push(...nodes.map(x => [x, x])); | ||
nodesPairs.forEach(function (nodePair) { | ||
const id1 = nodePair[1].id(); | ||
var edges = nodePair[0].connectedEdges('.cy-expand-collapse-collapsed-edge[source = "' + id1 + '"],[target = "' + id1 + '"]'); | ||
// edges for self-loops | ||
if (nodePair[0].id() === id1) { | ||
edges = nodePair[0].connectedEdges('[source = "' + id1 + '"][target = "' + id1 + '"]'); | ||
} | ||
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(){ | ||
api.collapseAllEdges = function (opts) { | ||
return this.collapseEdgesBetweenNodes(cy.edges().connectedNodes(), opts); | ||
}; | ||
api.expandAllEdges = function () { | ||
var edges = cy.edges(".cy-expand-collapse-collapsed-edge"); | ||
var result = {edges:cy.collection(), oldEdges : cy.collection()}; | ||
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); | ||
result.edges = result.edges.add(operationResult.edges); | ||
return result; | ||
}; | ||
api.loadJson = function (jsonStr) { | ||
saveLoadUtils.loadJson(jsonStr); | ||
}; | ||
api.saveJson = function (elems, filename) { | ||
saveLoadUtils.saveJson(elems, filename); | ||
}; | ||
return api; // Return the API instance | ||
@@ -380,3 +396,3 @@ } | ||
// Get the whole scratchpad reserved for this extension (on an element or core) or get a single property of it | ||
function getScratch (cyOrEle, name) { | ||
function getScratch(cyOrEle, name) { | ||
if (cyOrEle.scratch('_cyExpandCollapse') === undefined) { | ||
@@ -387,3 +403,3 @@ cyOrEle.scratch('_cyExpandCollapse', {}); | ||
var scratch = cyOrEle.scratch('_cyExpandCollapse'); | ||
var retVal = ( name === undefined ) ? scratch : scratch[name]; | ||
var retVal = (name === undefined) ? scratch : scratch[name]; | ||
return retVal; | ||
@@ -393,3 +409,3 @@ } | ||
// Set a single property on scratchpad of an element or the core | ||
function setScratch (cyOrEle, name, val) { | ||
function setScratch(cyOrEle, name, val) { | ||
getScratch(cyOrEle)[name] = val; | ||
@@ -417,4 +433,4 @@ } | ||
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 | ||
edgeTypeInfo: "edgeType", //the name of the field that has the edge type, retrieved from edge.data(), can be a function | ||
groupEdgesOfSameTypeOnCollapse: false, | ||
@@ -431,3 +447,3 @@ allowNestedEdgeCollapse: true, | ||
var api = createExtensionAPI(cy, expandCollapseUtilities); // creates and returns the API instance for the extension | ||
saveLoadUtils = require("./saveLoadUtilities")(cy, api); | ||
setScratch(cy, 'api', api); | ||
@@ -440,7 +456,7 @@ | ||
// if the cue is not enabled unbind cue events | ||
if(!options.cueEnabled) { | ||
if (!options.cueEnabled) { | ||
cueUtilities('unbind', cy, api); | ||
} | ||
if ( options.ready ) { | ||
if (options.ready) { | ||
options.ready(); | ||
@@ -458,3 +474,2 @@ } | ||
}; | ||
@@ -471,6 +486,6 @@ if (typeof module !== 'undefined' && module.exports) { // expose as a commonjs module | ||
if (typeof cytoscape !== 'undefined') { // expose to global cytoscape (i.e. window.cytoscape) | ||
register(cytoscape); | ||
if (typeof cytoscape !== 'undefined') { // expose to global cytoscape (i.e. window.cytoscape) | ||
register(cytoscape); | ||
} | ||
})(); |
Sorry, the diff of this file is too big to display
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
1890730
5682
256
24