Giter Club home page Giter Club logo

cytoscape.js-node-editing's Introduction

cytoscape-node-editing

Description

A Cytoscape.js extension to provide certain node editing functionality as follows:

  • grapples to resize nodes,
  • a visual cue to resize node to its label, and
  • ability to move selected nodes with arrow keys (accelerator keys Alt and Shift result in slower and faster moves, respectively), distributed under The MIT License.

Please cite the following paper when using this extension:

U. Dogrusoz , A. Karacelik, I. Safarli, H. Balci, L. Dervishi, and M.C. Siper, "Efficient methods and readily customizable libraries for managing complexity of large networks", PLoS ONE, 13(5): e0197238, 2018.

Demo

Click here (simple) or here (undoable) for demos

Default Options

            cy.nodeEditing({
                padding: 5, // spacing between node and grapples/rectangle
                undoable: true, // and if cy.undoRedo exists
    
                grappleSize: 8, // size of square dots
                grappleColor: "green", // color of grapples
                inactiveGrappleStroke: "inside 1px blue",               
                boundingRectangleLineDash: [4, 8], // line dash of bounding rectangle
                boundingRectangleLineColor: "red",
                boundingRectangleLineWidth: 1.5,
                zIndex: 999,
    
                minWidth: function (node) {
                    var data = node.data("resizeMinWidth");
                    return data ? data : 15;
                }, // a function returns min width of node
                minHeight: function (node) {
                    var data = node.data("resizeMinHeight");
                    return data ? data : 15;
                }, // a function returns min height of node

                // Getters for some style properties the defaults returns ele.css('property-name')
                // you are encouraged to override these getters
                getCompoundMinWidth: function(node) { 
                  return node.css('min-width'); 
                },
                getCompoundMinHeight: function(node) { 
                  return node.css('min-height'); 
                },
                getCompoundMinWidthBiasRight: function(node) {
                  return node.css('min-width-bias-right');
                },
                getCompoundMinWidthBiasLeft: function(node) { 
                  return node.css('min-width-bias-left');
                },
                getCompoundMinHeightBiasTop: function(node) {
                  return node.css('min-height-bias-top');
                },
                getCompoundMinHeightBiasBottom: function(node) { 
                  return node.css('min-height-bias-bottom');
                },

                // These optional functions will be executed to set the width/height of a node in this extension
                // Using node.css() is not a recommended way (http://js.cytoscape.org/#eles.style) to do this. Therefore,
                // overriding these defaults so that a data field or something like that will be used to set node dimentions
                // instead of directly calling node.css() is highly recommended (Of course this will require a proper 
                // setting in the stylesheet).
                setWidth: function(node, width) { 
                    node.css('width', width);
                },
                setHeight: function(node, height) {
                    node.css('height', height);
                },
    
                isFixedAspectRatioResizeMode: function (node) { return node.is(".fixedAspectRatioResizeMode") },// with only 4 active grapples (at corners)
                isNoResizeMode: function (node) { return node.is(".noResizeMode, :parent") }, // no active grapples
                isNoControlsMode: function (node) { return node.is(".noControlsMode") }, // no controls - do not draw grapples
    
                cursors: { // See http://www.w3schools.com/cssref/tryit.asp?filename=trycss_cursor
                    // May take any "cursor" css property
                    default: "default", // to be set after resizing finished or mouseleave
                    inactive: "not-allowed",
                    nw: "nw-resize",
                    n: "n-resize",
                    ne: "ne-resize",
                    e: "e-resize",
                    se: "se-resize",
                    s: "s-resize",
                    sw: "sw-resize",
                    w: "w-resize"
                },

                // enable resize content cue according to the node
                resizeToContentCueEnabled: function (node) {
                  return true;
                },
                // handle resize to content with given function
                // default function resizes node according to the label
                resizeToContentFunction: undefined,
                // select position of the resize to content cue
                // options: 'top-left', 'top-right', 'bottom-left', 'bottom-right'
                resizeToContentCuePosition: 'bottom-right',
                // relative path of the resize to content cue image
                resizeToContentCueImage: '/node_modules/cytoscape-node-editing/resizeCue.svg',
                enableMovementWithArrowKeys: true,
                autoRemoveResizeToContentCue: false,
             });

API

var api = cy.nodeEditing('get') To get the extension instance after initialization.

api.refreshGrapples() Refresh rendered node grapples if any. It is an expensive operation and is supposed to be called in rare cases (When it is really needed).

api.removeGrapples() Remove grapples while node is selected. This is useful when a node is selected but no need to show grapples.

Dependencies

  • Cytoscape.js ^3.2.0
  • jquery ^1.7.0 || ^2.0.0 || ^3.0.0
  • konva ^7.0.3
  • cytoscape-undo-redo ^1.0.10 (optional)

Usage instructions

Download the library:

  • via npm: npm install cytoscape-node-editing,
  • via bower: bower install cytoscape-node-editing, or
  • via direct download in the repository (probably from a tag).

require() the library as appropriate for your project:

CommonJS:

var cytoscape = require('cytoscape');
var nodeEditing = require('cytoscape-node-editing');
var konva = require('konva');

nodeEditing( cytoscape, jQuery, konva ); // register extension

AMD:

require(['cytoscape', 'cytoscape-node-editing', 'jquery', 'konva'], function( cytoscape, nodeEditing, jQuery, konva ){
  nodeEditing( cytoscape, jQuery, konva ); // register extension
});

Plain HTML/JS has the extension registered for you automatically, because no require() is needed.

Emitted Events

cy.on("nodeediting.resizestart", function(e, type, node){ })

cy.on("nodeediting.resizeend", function(e, type, node){ })

cy.on("nodeediting.resizedrag", function(e, type, node){ })

cy.on("nodeediting.resizetocontent", function(e, node){ })

type param can be topleft, topcenter, topright, centerright, bottomright, bottomcenter, bottomleft, centerleft

node param corresponds to currently resizing node.

Build targets

  • npm run build : Build ./src/** into cytoscape-edge-editing.js in production environment and minimize the file.
  • npm run build:dev : Build ./src/** into cytoscape-edge-editing.js in development environment without minimizing the file.

Publishing instructions

This project is set up to automatically be published to npm and bower. To publish:

  1. Build the extension : npm run build
  2. Commit the build : git commit -am "Build for release"
  3. Bump the version number and tag: npm version major|minor|patch
  4. Push to origin: git push && git push --tags
  5. Publish to npm: npm publish .
  6. If publishing to bower for the first time, you'll need to run bower register cytoscape-node-editing https://github.com/iVis-at-Bilkent/cytoscape.js-node-editing.git

Team

cytoscape.js-node-editing's People

Contributors

ahmetcandiroglu avatar hasanbalci avatar istemi-bahceci avatar kimxogus avatar kinimesi avatar mafar avatar metincansiper avatar mrsfy avatar msalihaltun avatar nasimsaleh avatar royludo avatar ugurdogrusoz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cytoscape.js-node-editing's Issues

Define peer dependencies

jquery, oCanvas and cytoscape should be peer dependencies for this extension. However, I thik that adding new peer dependencies may require publishing version 3.0.0 (because this changes may not be backward compatible). It seems that we can add these peer dependencies when we have some other not backward compatible api changes and so we decided to publish the version 3.0.0.

steals keydown events?

Hi,
I am using this: https://www.npmjs.com/package/vue2-editor
but the spacekey is not working in that editor when I set this option to true in the node-editing:
enableMovementWithArrowKeys: true
Btw, the same issue with the edge-editing and the option
moveSelectedAnchorsOnKeyEvents

I am not sure in which application the error is, but at least good to know for others having a similar problem

"Cannot read property 'value' of undefined" in latest Cytoscape

Registering this plugin in latest cytoscape appears to work at first, with the node handles being present upon node selection, but attempting to use the handles to resize the node throws the following error:

core.js:5847 ERROR TypeError: Cannot read property 'value' of undefined
    at Rect.eMouseDown (cytoscape-node-resize.js:638)

This behavior is present in your own hosted demo as well.

Filter nodes to which resizing grapples should appear

Hi,
I want to hide grapples for some nodes. is it possible ?
I know there is isNoResizeMode option but it disables resizing.
I want some nodes based on ```data()```` that when clicked , there should be no grapples visible.
Is it possible via cytoscape style?

NodeEditing is not a function in React

Hi,

when I try to use the node editing feature inside the cytoscape instance, I always get the following:

this.nodeEditing is not a function TypeError: this.nodeEditing is not a function

I import the package like this:

import nodeEditing from 'cytoscape-node-editing'; cytoscape.use( nodeEditing );

and call the function in my useEffect() inside the ready function like this:

this.nodeEditing({ zIndex:999, resizeToContentCueImage: ""});

Is there something wrong with the import?

Thanks in advance

Performance problem

Selection seems to be extremely slow with the introduction of this extension in ChiSE (e.g. try Select All Nodes of This Type for macromolecules of the default sample pathway).

The drag and drop function is invalid

-.Google.Chrome.2024-04-12.10-25-14.mp4

When I tried to drag and change the node size, I found it invalid, and after dragging, the reseizeend callback was not executed and no node on the page could be moved

5B5E39FA-1867-4478-A72F-01BAF3595E12

Usage in React

I would like to import this extension into React but have continually been getting TypeErrors. Is it possible to import this and if so what is the correct syntax?

Cannot move child node within Compound Node after resizing.

Hi,

When a compound node that has a single child get's resized, it's no longer possible to move the child node freely within the compound node. The child node becomes 'sticky' to a position within the compound node.

Could you please confirm if this is intended behavior? If yes, is there a workaround to make the child node move freely within the parent?

Here is a small video demonstrating the issue.

Screen.Recording.2021-07-27.at.00.13.01.mov

Here is the modified section of demo.html file from this repository if you would like to reproduce the issue.

document.addEventListener('DOMContentLoaded', function(){

	var cy = window.cy = cytoscape({
		container: document.getElementById('cy'),

		style: [
			{
				selector: 'node',
				style: {
					'content': 'data(name)',
					'textValign': 'center',
					'width': '50px',
					'height': '50px'
				}
			},
			{
				selector: ':parent',
				style: {
					'textValign': 'bottom'
				}
			}
		],

		layout: { name: 'preset'},
		
		wheelSensitivity: 0.1,

		elements: {
			nodes: [
				{ data: {id: 'p', name: 'Parent'}},
				{ data: { id: 'j', parent: 'p', name: 'Child1' }, position: {x: 100, y: 100}},
				{ data: { id: 'k', name: 'Orphan1' }, position: {x: 100, y: 200} }
			]
		}
	});

	cy.nodeEditing({
		resizeToContentCueImage: 'resizeCue.svg',
		autoRemoveResizeToContentCue: true,
		isNoResizeMode: function(n) {
          return n.is(".noResizeMode")
        },
	});

	cy.on("nodeediting.resizestart", function (e, type) {
		console.log(type);
	});

	cy.on("nodeediting.resizeend", function (e, type) {
		document.body.style.cursor = 'initial';
	});

});

If you need any further info, please let me know.

cy.json (); height and width do not change

Dear Team,
when I resize node with cytoscape-node-editing grapples the height and width data are not up-to-date. After using grapples, I try to read the current data, for example with below code:
document.getElementById('save').addEventListener('click', function() { json = cy.json(); console.log('Nodes:', cy.nodes().jsons()); console.log('Edges:', cy.edges().jsons( ));
but I can always see the data before resizing.
cy-git
Could you please check it ?

Remove jquery dependency

I want to know if you have planned to remove jquery dependency.

I have been working with this library for years and I made the necessary changes to eliminate the dependency, there are not many since jquery is only used to do an extend, find and create dom elements and apply styles.

Are you already working to remove the dependency? I have been using the library without jquery for a long time and I would like to thank you in some way for your work with this improvement so If you want I can make a pull request.

Error registering extension: nodeEditing is not a function

Hi I'm having a bit of trouble registering this extension, underneath is the browser reporting that nodeEditing is not a function.
not-a-function

For the imports and extension registering, I've followed as close as possible to the Doku
imports
Since there's no ES way possible to register this extension, I've used the JS way, but it should be no problem (I've tested the JS way with other extensions also).

I've installed the dependencies by npm, Konva version "^8.3.14", "cytoscape": "^3.23.0" and jquery 3.6.1. I've also tried importing konva and jquery from different .js files, all combinations reproduce this same error.

node.data('width') and node.data('height') are not changing upon node resize

I think that when a node is resized with this extension node.css('width') and node.css('height') are changing but node.data('width') and node.data('height') are not changing. I think that users may expect that upon node resize both css and data are changing.
As an example in the following node resize extension 'https://github.com/jhonatandarosa/cytoscape.js-noderesize' data changes upon node resize and then css changes as parallel to data with the following code segments:

                    // This code segement defines the style that resized nodes will have
                    cy.style().selector('.noderesize-resized').css({
                        'width': 'data(width)',
                        'height': 'data(height)',
                    });

                    // This is called when node is resized
                    node.addClass('noderesize-resized');

How about having such a structure?

Ineffective extension options

boundingRectangle and zIndex options are not effective (They aren't used in the extension code). They can be removed from options totally or their functionality can be implemented.

Intercepting click events?

Hello,

I am trying to use your very nice node-resize facility, but I've noticed one significant issue with it, at least for me.

It seems to prevent "click" events from being seen by a modal dialog I've created. Specifically, with your extension activated, the dialog can be raised but any click within the dialog's fields is not seen by the dialog object. Rather those events seem to target the underlying canvas.

Without your extension activated, this does not happen; the dialog behaves normally.

  1. why does this occur?
  2. can I prevent its occurrence and continue to use the extension?

Thank you.

Cordially,

Paul

cytoscape not defined

Hi,

Looks like there is a similar error with this extension, as there was with iVis-at-Bilkent/cytoscape.js-context-menus#5

When I require cytoscape-node-resize, I get the following error..

cytoscape-node-resize.js:681Uncaught ReferenceError: cytoscape is not defined
(anonymous function) @ cytoscape-node-resize.js:681
2976 @ cytoscape-node-resize.js:684
webpack_require @ bootstrap 7cf81ac…:50
2383 @ app.js:12
webpack_require @ bootstrap 7cf81ac…:50
0 @ analysisCentre.entry.js:29
webpack_require @ bootstrap 7cf81ac…:50
webpackJsonpCallback @ bootstrap 7cf81ac…:21
(anonymous function) @ analysisCentre.bundle.js?v=8467:1

Cytoscape window initialization code seems to be broken

I think that the global initialization code is broken for JSPM:

if (typeof cytoscape !== 'undefined' || typeof jQuery !== "undefined" || typeof oCanvas !== "undefined") { // expose to global cytoscape (i.e. window.cytoscape)
        register(cytoscape, jQuery, oCanvas);
    }

When importing as:

import * as ocanvas from 'ocanvas';

import * as nodeResize from 'cytoscape-node-resize';
import * as cytoscape from 'cytoscape';

via the JSPM configuration:

    "npm:[email protected]": {
      "child_process": "github:jspm/[email protected]",
      "fs": "github:jspm/[email protected]",
      "path": "github:jspm/[email protected]",
      "process": "github:jspm/[email protected]",
      "cytoscape": "npm:[email protected]"
    },

I get a cytoscape is undefined error. When I make the window initialization code conjunctive:

    if (typeof cytoscape !== 'undefined' && typeof jQuery !== "undefined" && typeof oCanvas !== "undefined") { // expose to global cytoscape (i.e. window.cytoscape)
        register(cytoscape, jQuery, oCanvas);
    }

Everything works

Resize grapples are drawn on unresizable nodes and vise versa

This bug was introduced after replacing ocanvas with konva #13

How to reproduce:

Unresizable grapples on resizable nodes:

  1. Select a complex.
  2. Collapse it.
    The collapsed node is resizable, but unresizable grapples are drawn on it.
    screenshot_20170614_152345

Resizable grapples on unresizable nodes:

  1. Collapse a complex without selecting it.
  2. Then expand the collapsed node.
    The expanded node is unresizable, but resizable grapples are drawn on it.
    screenshot_20170614_152142

This bug was found by @hasanbalci

possible to conditionally disable the node-editing function for a particular node?

I want to disable the ability to resize a node if the map is zoomed out far enough, so as to prevent accidental resizing. I tried to implement this using the isNoControlsMode function provided during initialization:
isNoControlsMode: function(node){
var z = cy.zoom();
var cyW = cy.container().clientWidth;
var cyH = cy.container().clientHeight;
var nW = node.width();
var nH = node.height();
if((nW*nH*z)/(cyW*cyH) < .0005 ){
return true
}
return false
}
This approach works sometimes, but for some reason it is very finnicky. I'm wondering if this is the correct approach for such a problem/if I am misusing is isNoControlsMode function?

Cytoscape dependency

In the documentation it writes that the cytoscape's version is 2.7.0 or higher, while in the package.json the dependency is 3.0.0 or higher

Rename extension

Rename it from "cytoscape.js-node-resize" to "cytoscape.js-node-editing" as it already covers non-resize related functionality (move by arrows). README has already been revised to reflect this change.

React, node module, drawImage error

Hi, I'm having some issues using your extention with npm and React.

I have created this example: https://codesandbox.io/s/yngv6q
Note that the same issue is present on my machine.

Everytime try to resize an element, this error appears

image

I've tried many different library version combinations, nothing works.

Thanks in advance.

Panning artifact during resize

When resizing if the user clicks outside the boundaries of the node shape, then a filled gray rectangle is drawn to provide panning effect. This is kind of misleading.

Ability to move diagonal with arrow keys

This extension will not support going in diagonal directions (e.g. bottom-right) as it favors the first key that's pressed. Let's modify the code to support this.

Redraw issues (artifacts)

When using the extension demo, select an arbitrary node and zoom in and out quickly using the mouse wheel. You'll see artifacts like this:
node-resize-redraw-problem

Option for disabling arrow keys?

Hi, can we add an option like moveWithArrowKeys, that disables arrow key movement when set to false?

Other apps might want to bind the arrow keys to other functions

Cursors for grapples

It'd be great if the cursor changed on grapples and the user could custom define their own cursors as well.

Change triggered event names

In this extension events are triggered currently on 'resizestart', 'resizedrag' and 'resizeend'. It would be better to change these event names in a way that they include the extension name as well (To do not have any conflict with the other extensions).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.