cytoscape / cytoscape.js-edgehandles Goto Github PK
View Code? Open in Web Editor NEWEdge creation UI extension for Cytoscape.js
License: MIT License
Edge creation UI extension for Cytoscape.js
License: MIT License
Just filling a bug but I see you didn't update the version number yet, so seems normal
breaks on line 4432 when selecting a node
if( badSourceOrTarget ){ removeFromElements(i); continue; } // can't create this
var src = cy.getElementById( data.source );
var tgt = cy.getElementById( data.target );
src._private.edges.push( edge );
tgt._private.edges.push( edge );
then 2328 when trying to select another one
for( var i = 0; i < this.length; i++ ){
var ele = this[ i ];
var parent = cy.getElementById( ele._private.data.parent );
if( parent.size() > 0 ){
parents.push( parent );
}
}
Not having access to the class on add makes it hard for apps to differentiate "real" elements from edgehandles ghost/preview elements.
Usecase : Factoid needs this for the ux to be right when edgehandles is used with automove
Currently we're able to use this extension to add edges from a compound node to a simple node but not vice versa (it doesn't always work for some reason)!
Because the draw mode doesn't use the handle anyway, it may as well not be shown.
Line 540 //var opts = Object.assign({}, defaults, params ); in IE10 not supportet.
Not recommended and not accurate anymore
Steps to recreate using defaults....
I'm getting this error, as in issue #61. I downloaded the latest release a few weeks ago, and it works, but the current latest isn't working. I also tried with other releases.
I'm pretty sure that the reason for crash is calling wrapping function with undefined cytoscape
and jQuery
as arguments. Browserify enforces strict mode everywhere - so it crushes on unknown variables.
I've managed to fix the crash by simply adding window.
before each of these arguments, but I'm not sure if that is a good solution for other ways to import this plugin.
All function can be called via cy.edgehandles('function-name'):
cy.edgehandles('enable') : enable the extension
cy.edgehandles('option', 'preview', false) : set individual option (e.g. 'preview')
cy.edgehandles('option', { /* options */ }) : set all options
cy.edgehandles('option', 'preview') : get option value (e.g. 'preview')
cy.edgehandles('destroy') : destroy the extension instance
cy.edgehandles('start', 'some-node-id') : start the handle drag state on node with specified id (e.g. 'some-node-id')
cy.edgehandles('drawon') : enable draw mode
cy.edgehandles('drawoff') : disable draw mode
Hello,
If I try to require and link the modules, as shown here:
var cytoscape = require('cytoscape');
var edgehandles = require('cytoscape-edgehandles');
var jquery = require('jquery');
edgehandles( cytoscape, jquery ); // register extension
i get Uncaught ReferenceError: cytoscape is not defined. It works when I import them global (I use webpack) however then I receive an Uncaught TypeError: $container.cytoscape is not a function when I try to:
cy.edgehandles(edgeConf);
I assume the current version broke something.
#48
detected error in $container.off(..).off(...).off(...) as function "off" should return "this" in order to queue them, as defined correctly in function "on".
Hi,
I am using this extension with semver ~2.10.2
. I realized that clickable html components are not working for me after v2.10.3 of this extension is released. If I switch the semver of this extension to 2.10.2
from ~2.10.2
then the problem disappears. As far as I see the problem is emerged with 4b015c7
edgeType="node"
loopAllowed=true
Scenario: Start edgehandles and release on the same node, and the intermediate node is placed on top of the source/target node. I think the intermediate node should be located off to the side of the source/target node.
When edgeType=flat
it makes a nice loop instead.
Currently it marks target nodes using mouse over timeout and draws edges to all of the target nodes marked. For diagram editor, it is more useful to draw one edge to the target node on mouse up event.
Maybe we can set hoverDelay to 0 to allow such behavior?
Both the context menu plugin and this plugin are awesome. What would be even more awesome is to have a drag-able handle be one of the items in the context menu--which would also provide support for touch devices. Basic interaction would be:
In my view this is a better flow than linking based on hover (edges are much harder to grab and not available on touch devices). It would be awesome if you can make these two plugins that compatible (maybe a 3rd plugin that links the two?).
Might not work but could be worthwhile for consistency
I played around with edgehandles and couldn't see the handles (everything worked, just no handles were drawn on the node). Eventually I discovered that the handles do appear on my web page, but outside the cytoscape layer canvases.
Edgehandles creates its own canvas, which it tries to place exactly over the cytoscape canvases. It injects its canvas into the DOM, as follows:
$container.append( $canvas );
For me, this leads to the canvas showing up below (in y coordinates) the cy element (and its layer canvases), instead of overlapping the cy element.
The reason seems to be that edgehandles appends the canvas to the container DIV, instead of the the canvas container DIV.
Changing the above line in cytoscape-edgehandles.js into this:
$container.find('.canvas-container').append($canvas);
together with a corresponding change in the CanvasRenderer
function in cytoscape.js (to add the 'canvas-container' class to the canvas container DIV) should fix this:
r.data.canvasContainer.setAttribute('class', 'canvas-container');
Have this been considered and rejected or would pull requests be welcome?
I'm thinking basically an option to not have this displayed on hover/mouseover, but rather all the time?
e.g. edgehandles.start
should be start.edgehandles
Maybe the events should be renamed to something like edgehandles-start
I am documenting this issue because I discovered it while working on #2. I believe I have a fix for both but I figured I should document this part too.
With edgehandles started from a source node, mouse button down, if you hover over one node, then leave that node and release somewhere on the background (even very far away from that node), the edge will be created to the last hovered node.
It seems this is because the "mouseout" event is not removing the "edgehandles-target" class. Adding this.removeClass("edgehandles-target");
to line 527 fixes the issue. I will post a patch.
This should also fix #2.
If so, is there an example I can look at? I have the cxt: true set but can't get mobile browsers to see the link hover.
See cytoscape/cytoscape.js#281
Use with new APIs to make "moving" edges convenient
If I call a extension function (e.g. cy.edgehandles('start', 'some-node-id') ) the node id is not forwarded to the start function. Instead, always the cy object is used as the only argument on the start function.
I'm working on a react/redux project which need one version without jquery, and I've started a project which is at
https://github.com/tongbin/cytoscape.js-edgehandles
please let me know if there is any problems with it.
Consider three nodes: node A, child Node, and parent Node.
If I drag from nodeA to child node and release (to create an edge from node A to child node), sometimes an edge is also created from node A to parent node. Whether or not the edge from node A to parent node is created seems to depend on exactly where the mouseup happens on child node.
Separately, but possibly related to the location issue - there is some small misalignment between mouseup and the targetnode. Sometimes when mouseup is off to the side of the node, the edge is still created to the node. In my particular case this happens off to the left side only, not top or bottom or right.
But this doesn't explain why two edges are created.
I have the cy div set with position: absolute, which might be related to the location issue. I thought that was fixed in this version of the plugin (after separating from the cytoscapejs core)...?
When edgeType="node"
, two edges are created. One from sourceNode to intermediate node and one from intermediate node to targetNode. edgeParams
should have some way to specify different params for those two different edges.
When you try to add an edge the line you drag from source node constantly blinks. You can even find position where line becomes invisible. When you comment lines 290-292 - that is:
if( now - lastDrawLine < lineDrawRate ){
return;
}
line stops to blink and is drawn properly. Is this some kind of optimalisation?
For a parent node with many children nodes, if this parent node is relatively large, the edge handle shown at the top of the node is not always accessible without scrolling.
Would it be possible to add an option for users to specify where the edge handle is displayed? Specifically if we can have the option to display the handle where mouse is, that will be very useful.
Running the demo from release 1.2.0 results in a TypeError: cy is undefined
on lines https://github.com/cytoscape/cytoscape.js-edgehandles/blob/master/cytoscape.js-edgehandles.js#L161 and https://github.com/cytoscape/cytoscape.js-edgehandles/blob/master/cytoscape.js-edgehandles.js#L169 when pressing the buttons "Draw mode on" and "Draw mode off" respectively.
This is with Firefox 32.0 under Ubuntu 14.04.
It would be great to be able to specify a selector to limit which nodes get the edgeHandles behavior. Unless I'm missing something that functionality is not currently available right>?
When attempting to install edgehandles via bower, I get an error message using this command.
bower install cytoscape-edgehandles --save
bower ENOTFOUND Package cytoscape-edgehandles not found
To automatically highlight or add some visual effect when mouse over a target node to which an edge is allowed to be drawn. (see my pull request canAccept() enhancement).
Hi!
I've found out that when Cytoscape resizes its canvas there are places I cannot use edge handles to create connections. It seems we are missing resizing after cy.resize() :)
We need to add:
cy.on( 'resize', function() {
$container.trigger( 'cyedgehandles.resize' );
});
on line 417 ;)
Edgehandles works fine on web browser. But it doesn't work on mobile browser. Is there any solution for support mobile web browser? Can I bind new cytoscape's event listener with edgehandles? e.g: double tap
The hard-coded z-index of 999 on the edgehandles canvas element causes stacking/layout issues.
Example: the graph is used inside of a component that has an action bar with drop-down menus. When cytoscape-edgehandles is initiated the canvas element is rendered above everything including the drop-downs. The drop-down actions are no longer functional because the canvas captures the pointer events.
I have a couple of suggested fixes if there is a way to submit a PR.
Thanks for the plugin!
I think 2.6.0 broke the extension - completely unchanged code stopped working between 2.5.0 and 2.6.0.
Initialisation works just fine, but when trying to actually drag out an edge to connect you start to drag the node instead. Regressing to 2.5.0 restores expected behaviour.
I'll look into this on monday unless someone has a solid idea on why already, but I'm guessing the jQuery-like shim now used instead has some slight incompatibility with how events used to be handled (based on skimming the commits in 30 seconds, treat accordingly. )
Stop event not fired in next initialization sequence, only complete is fired when edge is created. Stop not fired not when edge created, not when just handle released
cy.edgehandles({ toggleOffOnLeave: true, handleSize: 0, cxt: true });
cy.edgehandles('drawon');
cy.on('cyedgehandles.stop', 'node', function(e) {
console.log('stop');
});
cy.on('cyedgehandles.complete', 'node', function(e) {
console.log('complete');
})
It is possible to add multiple edges between the same two nodes.
How can I disable this, so I am sure a user can never add the same edge multiple times?
can this library support multiple handles?
I would like to be able to have a node which has X number of handles to a node because in my graph nodes can only support X number of edges
Just came across this and after a bit of testing I think i've found what seems to be the cause of the issue. As you can see below when using node shapes other than circle when you reduce the border-width to 0 then when you are dragging the edge you occasionally get the arrow flipping around which way it is facing. You can easily recreate this with the demo.html in the repo by simply adding 'shape': 'rectangle' to the node style.
I take <div id="cy"></div>
position is relative and I scroll down the scroll bar (it's not on top). I cannot connect 2 nodes together.
I think we have a problem with "mdownHandler" function about calculated height and top offset page.
Could you consider this issue.
Thanks
Is there a way to specify multiple positions for the handle as per node? For example if the node has css class 'x' the handlePosition: 'left middle | right middle', and if the node has css class 'y' the handlePosition: 'top middle | top bottom'
Essentially I'm talking about two questions/suggestions:
Can this be done?
When i tried to integrate Edgehandles with Cytoscape, it showed an error:
Uncaught TypeError: cy.edgehandles is not a function
I was pretty sure doing it the right way:
This is my HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title></title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
</head>
<body>
<section>
<div class="container">
<div class="row">
<div class="col-xs-12 match-container">
<!-- <canvas id="canvas" width=300 height=300></canvas> -->
<div id="canvas"></div>
<div class="col-xs-4 no-padding">
<div id="0" class="draggable">0</div>
<div id="1" class="draggable">1</div>
<div id="2" class="draggable">2</div>
</div>
<div id="wrap2" class="col-xs-4 col-xs-offset-4 no-padding">
<div id="0r" class="draggable right">0</div>
<div id="1r" class="draggable right">1</div>
<div id="2r" class="draggable right">2</div>
</div>
</div>
</div>
</div>
</section>
<script src="js/jquery.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/cytoscape.min.js"></script>
<script src="js/cytoscape-edgehandles.js"></script>
<script src="js/script.js"></script>
</body>
</html>
This is the JS:
var cy = cytoscape({
container: document.getElementById('canvas'), // container to render in
elements: [ // list of graph elements to start with
{ // node a
data: { id: 'a',class: 'node' }
},
{ // node b
data: { id: 'b',class: 'node' }
},
{ // edge ab
data: { id: 'ab', source: 'a', target: 'b' }
},
{ // node a
data: { id: 'c',class: 'node' }
},
{ // node b
data: { id: 'd',class: 'node' }
},
{ // node a
data: { id: 'e',class: 'node' }
},
{ // node b
data: { id: 'f',class: 'node' }
}
],
style: [ // the stylesheet for the graph
{
selector: 'node',
style: {
'background-color': '#666',
'label': 'data(id)'
}
},
{
selector: 'edge',
style: {
'width': 3,
'line-color': '#ccc',
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle'
}
}
],
layout: {
name: 'grid',
cols: 2
},
zoomingEnabled: false,
userZoomingEnabled: false,
autoungrabify: true,
panningEnabled: false,
userPanningEnabled: false,
});
var defaults = {
preview: true, // whether to show added edges preview before releasing selection
stackOrder: 4, // Controls stack order of edgehandles canvas element by setting it's z-index
handleSize: 10, // the size of the edge handle put on nodes
handleColor: '#ff0000', // the colour of the handle and the line drawn from it
handleLineType: 'ghost', // can be 'ghost' for real edge, 'straight' for a straight line, or 'draw' for a draw-as-you-go line
handleLineWidth: 1, // width of handle line in pixels
handleIcon: false, // Pass an Image-object to use as icon on handle. Icons are resized according to zoom and centered in handle.
handleOutlineColor: '#000000', // the colour of the handle outline
handleOutlineWidth: 0, // the width of the handle outline in pixels
handleNodes: 'node', // selector/filter function for whether edges can be made from a given node
handlePosition: 'middle top', // sets the position of the handle in the format of "X-AXIS Y-AXIS" such as "left top", "middle top"
hoverDelay: 150, // time spend over a target node before it is considered a target selection
cxt: false, // whether cxt events trigger edgehandles (useful on touch)
enabled: true, // whether to start the extension in the enabled state
toggleOffOnLeave: false, // whether an edge is cancelled by leaving a node (true), or whether you need to go over again to cancel (false; allows multiple edges in one pass)
edgeType: function( sourceNode, targetNode ) {
// can return 'flat' for flat edges between nodes or 'node' for intermediate node between them
// returning null/undefined means an edge can't be added between the two nodes
return 'flat';
},
loopAllowed: function( node ) {
// for the specified node, return whether edges from itself to itself are allowed
return false;
},
nodeLoopOffset: -50, // offset for edgeType: 'node' loops
nodeParams: function( sourceNode, targetNode ) {
// for edges between the specified source and target
// return element object to be passed to cy.add() for intermediary node
return {};
},
edgeParams: function( sourceNode, targetNode, i ) {
// for edges between the specified source and target
// return element object to be passed to cy.add() for edge
// NB: i indicates edge index in case of edgeType: 'node'
return {};
},
start: function( sourceNode ) {
// fired when edgehandles interaction starts (drag on handle)
},
complete: function( sourceNode, targetNodes, addedEntities ) {
// fired when edgehandles is done and entities are added
},
stop: function( sourceNode ) {
// fired when edgehandles interaction is stopped (either complete with added edges or incomplete)
},
cancel: function( sourceNode, renderedPosition ){
// fired when edgehandles are cancelled ( incomplete - nothing has been added ) - renderedPosition is where the edgehandle was released
}
};
cy.edgehandles( defaults );
console.log(cy);
What did I do wrong?
Thanks in advance!`
Would it be at all possible for this extension to allow for self-directed edges?
cytoscape-edgehandles.js:623 Uncaught TypeError: Cannot read property 'id' of null(…)
When handleLineType = ghost and I start creating egde from source node then release mouse button while still moving the mouse - somewhere between the nodes or out of canvas. Throws an error
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.