Coder Social home page Coder Social logo

cytoscape.js-popper's Introduction

cytoscape-popper

DOI

Description

Popper allows you to dynamically align a div, e.g. a tooltip, to another element in the page. This extension allows you to use any popper library on Cytoscape elements. This allows you to create DOM elements positioned on or around Cytoscape elements. It is useful for tooltips and overlays, for example.

Integration examples:

Migration from v2

Since Popper.js has become @floating-ui (https://floating-ui.com/docs/migration) and the API has changed a lot it becomes harder to support both versions (for example TippyJS, that supports only the previous version), so instead of depending on a specific external version this extension allows users to use any Popper library with providing popperFactory function during initializing.

See FloatingUI or Popper.js sections.

Dependencies

  • Cytoscape.js ^3.2.0

Usage instructions

Download the library:

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

Import the library as appropriate for your project:

ES import:

import cytoscape from 'cytoscape';
import cytoscapePopper from 'cytoscape-popper';

function popperFactory(ref, content, opts) {
  // See integration sections
}

cytoscape.use( cytoscapePopper(popperFactory) );

CommonJS require:

let cytoscape = require('cytoscape');
let cytoscapePopper = require('cytoscape-popper');

function popperFactory(ref, content, opts) {
   // See integration sections
}

cytoscape.use( cytoscapePopper(popperFactory) ); // register extension

AMD:

require(['cytoscape', 'cytoscape-popper'], function( cytoscape, popper ){
  function popperFactory(ref, content, opts) {
     // See integration sections
  }
  // register extension
  popper(popperFactory)(cytoscape);
});

API

This extension exposes popper() and popperRef() functions and provided popperFactory(). These functions are defined for both the core and for elements, so you can call cy.popper() or ele.popper() for example.

Each function takes an options object, as follows:

cy.popper( options ) or ele.popper( options ) : Make a PopperInstance for the specified core Cytoscape instance or the specified element. This is useful for positioning a div relative to or on top of a core instance or element.

cy.popperRef( options ) or ele.popperRef( options ) : Make a PopperInstance for the specified core Cytoscape instance or the specified element. A Popper virtual element is useful only for positioning, as it represent the target rather than the content. This is useful for cases where you want to create a new Popper instance manually via Popper constructor createPopper() or where you need to pass a popperRef object to another library like Tippy.js.

  • options
    • content : The HTML content of the popper. May be a DOM Element reference or a function that returns one.
    • renderedPosition : A function that can be used to override the rendered Cytoscape position of the Popper target. This option is mandatory when using Popper on the core. For an element, the centre of its bounding box is used by default.
    • renderedDimensions : A function that can be used to override the rendered Cytoscape bounding box dimensions considered for the popper target (i.e. cy or ele). It defines only the effective width and height (bb.w and bb.h) of the Popper target. This option is more often useful for elements rather than for the core.
    • popper : The PopperOptions object. These options are used in provided popperFactory.

Usage with @floating-ui

Initializing

import cytoscape from 'cytoscape';
import cytoscapePopper from 'cytoscape-popper';
import {
  computePosition,
  flip,
  shift,
  limitShift,
} from '@floating-ui/dom';

function popperFactory(ref, content, opts) {
   // see https://floating-ui.com/docs/computePosition#options
   const popperOptions = {
       // matching the default behaviour from Popper@2
       // https://floating-ui.com/docs/migration#configure-middleware
       middleware: [
           flip(),
           shift({limiter: limitShift()})
       ],
       ...opts,
   }

   function update() {
       computePosition(ref, content, popperOptions).then(({x, y}) => {
           Object.assign(content.style, {
               left: `${x}px`,
               top: `${y}px`,
           });
       });
   }
   update();
   return { update };
}

cytoscape.use(cytoscapePopper(popperFactory));

popper() example

// create a basic popper on the first node
let popper1 = cy.nodes()[0].popper({
  content: () => {
    let div = document.createElement('div');

    div.innerHTML = 'Popper content';

    document.body.appendChild(div);

    return div;
  }
});

// create a basic popper on the core with custom options
let popper2 = cy.popper({
  content: () => {
    let div = document.createElement('div');

    div.innerHTML = 'Popper content';

    document.body.appendChild(div);

    return div;
  },
  renderedPosition: () => ({ x: 100, y: 200 }),
  popper: {
      placement: 'bottom',
  } // @flaoting-ui options (https://floating-ui.com/docs/middleware)
});

popperRef() example

// create a basic popper ref for the first node
let popperRef1 = cy.nodes()[0].popperRef();

// create a basic popper ref on the core
let popperRef2 = cy.popperRef({
  renderedPosition: () => ({ x: 200, y: 300 })
});

Sticky popper() example

let node = cy.nodes().first();

let popper = node.popper({
  content: () => {
    let div = document.createElement('div');

    div.innerHTML = 'Sticky Popper content';

    document.body.appendChild( div );

    return div;
  }
});

let update = () => {
  popper.update();
};

node.on('position', update);

cy.on('pan zoom resize', update);

Usage with Popper.js (deprecated)

Initializing

import cytoscape from 'cytoscape';
import cytoscapePopper from 'cytoscape-popper';
import { createPopper } from '@popperjs/core';

cytoscape.use(cytoscapePopper(createPopper));

popper() example

// create a basic popper on the first node
let popper1 = cy.nodes()[0].popper({
  content: () => {
    let div = document.createElement('div');

    div.innerHTML = 'Popper content';

    document.body.appendChild(div);

    return div;
  },
  popper: {} // my popper options here
});

// create a basic popper on the core
let popper2 = cy.popper({
  content: () => {
    let div = document.createElement('div');

    div.innerHTML = 'Popper content';

    document.body.appendChild(div);

    return div;
  },
  renderedPosition: () => ({ x: 100, y: 200 }),
  popper: {} // my popper options here
});

popperRef() example

// create a basic popper ref for the first node
let popperRef1 = cy.nodes()[0].popperRef();

// create a basic popper ref on the core
let popperRef2 = cy.popperRef({
  renderedPosition: () => ({ x: 200, y: 300 })
});

Sticky popper() example

let node = cy.nodes().first();

let popper = node.popper({
  content: () => {
    let div = document.createElement('div');

    div.innerHTML = 'Sticky Popper content';

    document.body.appendChild( div );

    return div;
  }
});

let update = () => {
  popper.update();
};

node.on('position', update);

cy.on('pan zoom resize', update);

Usage with Tippy.js

This extension can also be used to enable Tippy.js tooltip functionality with Cytoscape. Any version of Tippy that is compatible with Popper v2 is compatible with this extension.

Initializing

import cytoscape from 'cytoscape';
import popper from 'cytoscape-popper';
import tippy from 'tippy.js';

function tippyFactory(ref, content){
   // Since tippy constructor requires DOM element/elements, create a placeholder
   var dummyDomEle = document.createElement('div');

   var tip = tippy( dummyDomEle, {
       getReferenceClientRect: ref.getBoundingClientRect,
       trigger: 'manual', // mandatory
       // dom element inside the tippy:
       content: content,
       // your own preferences:
       arrow: true,
       placement: 'bottom',
       hideOnClick: false,
       sticky: "reference",

       // if interactive:
       interactive: true,
       appendTo: document.body // or append dummyDomEle to document.body
   } );

   return tip;
}

cytoscape.use(cytoscapePopper(tippyFactory));

The creation of many Tippy instances at once has performance implications, especially for large graphs. Create each instance on demand, e.g. on tap. Use destroy() instead of hide() where possible.

let node = cy.nodes().first();

var tip = node.popper({
   content: () => {
      let content = document.createElement('div');

      content.innerHTML = 'Tippy content';

      return content;
   },
});

tip.show();

Refer to Tippy.js documentation for more details.

Typescript

This extension exports empty PopperInstance and PopperOptions interfaces allows to extend them according to the final Popper implementation.

@floating-ui example:

import { ComputePositionConfig } from '@floating-ui/dom';

declare module 'cytoscape-popper' {
  interface PopperOptions extends ComputePositionConfig {
  }
  interface PopperInstance {
    update(): void;
  }
}

Build targets

  • npm run test : Run Mocha tests in ./test
  • npm run build : Build ./src/** into cytoscape-popper.js
  • npm run watch : Automatically build on changes with live reloading (N.b. you must already have an HTTP server running)
  • npm run dev : Automatically build on changes with live reloading with webpack dev server
  • npm run lint : Run eslint on the source

N.b. all builds use babel, so modern ES features can be used in the src.

Publishing instructions

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

  1. Build the extension : npm run build:release
  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-popper https://github.com/cytoscape/cytoscape.js-popper.git
  7. Make a new release for Zenodo.

cytoscape.js-popper's People

Contributors

adamstruck avatar atrue avatar d2fong avatar dependabot[bot] avatar docvolz avatar dsabsay avatar hmtinc avatar jean-zombie avatar lcparsons avatar maxkfranz avatar rasca 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar

cytoscape.js-popper's Issues

Demo throws TypeError

The demo shows a graph, but not everything seems to be working as intended. Console shows

TypeError: Popper is undefined cytoscape-popper.js:319:5
TypeError: cy.nodes(...)[0].popper is not a function cytoscape.js-popper:260:17

Popper inside a cytoscape node

Is it possible to place the popper inside the node? I want to customize cytoscape nodes by the HTML overlay. I think that Popper.js is good solution for it. But how can i do that?

Tooltips move on scroll

Tooltips move away from their reference on page scroll. Do you know if there is a way to disable this?

Here is a minimal example based on your demo:

<!DOCTYPE>

<html>

<head>
	<title>cytoscape-popper.js tippy demo</title>

	<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
	<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>

  <script src="https://unpkg.com/popper.js"></script>
	<script src="https://unpkg.com/[email protected]/cytoscape-popper.js"></script>

	<script src="https://unpkg.com/[email protected]/dist/tippy.all.js"></script>
	<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/tippy.css" />

	<style>
		#cy {
      height: 250px;
      width: 75%;
      margin: 5px auto;
      border-style: solid;
      border-color: #D3D3D3;
      border-width: thin;
		}
	</style>

	<script>
		document.addEventListener('DOMContentLoaded', function () {

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

				style: [
					{
						selector: 'node',
						style: {
							'content': 'data(id)'
						}
					},

					{
						selector: 'edge',
						style: {
							'curve-style': 'bezier',
							'target-arrow-shape': 'triangle'
						}
					}
				],

				elements: {
					nodes: [
						{ data: { id: 'a' } },
						{ data: { id: 'b' } }
					],
					edges: [
						{ data: { source: 'a', target: 'b' } }
					]
				},

				layout: {
					name: 'grid'
				}
			});

			var a = cy.getElementById('a');
			var b = cy.getElementById('b');

			var makeTippy = function(node, text){
				return tippy( node.popperRef(), {
					html: (function(){
						var div = document.createElement('div');

						div.innerHTML = text;

						return div;
					})(),
					trigger: 'manual',
					arrow: true,
					placement: 'bottom',
					hideOnClick: false,
					multiple: true,
					sticky: true
				} ).tooltips[0];
			};

			var tippyA = makeTippy(a, 'foo');

			tippyA.show();

			var tippyB = makeTippy(b, 'bar');

			tippyB.show();
		});
	</script>
</head>

<body>
  <div>
	  <div id="cy" style="height: 250px; width: 75%"></div>
  </div>
  </br></br>  
  <div>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas lacinia, nisi ut consequat iaculis, augue quam viverra libero, id sodales ipsum elit vel magna. Aliquam ac justo ut nulla varius porttitor a sodales est. Fusce sed bibendum lacus. In hendrerit mi a pretium suscipit. Sed quis arcu blandit, faucibus neque ut, consequat risus. Integer pharetra molestie hendrerit. Ut efficitur nulla quis dui pellentesque, vitae iaculis libero elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean mollis massa quis sapien porttitor scelerisque.
</br></br>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas lacinia, nisi ut consequat iaculis, augue quam viverra libero, id sodales ipsum elit vel magna. Aliquam ac justo ut nulla varius porttitor a sodales est. Fusce sed bibendum lacus. In hendrerit mi a pretium suscipit. Sed quis arcu blandit, faucibus neque ut, consequat risus. Integer pharetra molestie hendrerit. Ut efficitur nulla quis dui pellentesque, vitae iaculis libero elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean mollis massa quis sapien porttitor scelerisque.
 </br></br>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas lacinia, nisi ut consequat iaculis, augue quam viverra libero, id sodales ipsum elit vel magna. Aliquam ac justo ut nulla varius porttitor a sodales est. Fusce sed bibendum lacus. In hendrerit mi a pretium suscipit. Sed quis arcu blandit, faucibus neque ut, consequat risus. Integer pharetra molestie hendrerit. Ut efficitur nulla quis dui pellentesque, vitae iaculis libero elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean mollis massa quis sapien porttitor scelerisque.
</br></br>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas lacinia, nisi ut consequat iaculis, augue quam viverra libero, id sodales ipsum elit vel magna. Aliquam ac justo ut nulla varius porttitor a sodales est. Fusce sed bibendum lacus. In hendrerit mi a pretium suscipit. Sed quis arcu blandit, faucibus neque ut, consequat risus. Integer pharetra molestie hendrerit. Ut efficitur nulla quis dui pellentesque, vitae iaculis libero elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean mollis massa quis sapien porttitor scelerisque.
</br></br>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas lacinia, nisi ut consequat iaculis, augue quam viverra libero, id sodales ipsum elit vel magna. Aliquam ac justo ut nulla varius porttitor a sodales est. Fusce sed bibendum lacus. In hendrerit mi a pretium suscipit. Sed quis arcu blandit, faucibus neque ut, consequat risus. Integer pharetra molestie hendrerit. Ut efficitur nulla quis dui pellentesque, vitae iaculis libero elementum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean mollis massa quis sapien porttitor scelerisque.
  </div>
</body>

</html>

CPU Usage remains high for very large graph

I'm plotting a tree using cytoscape.js in Angular which uses cytoscape-popper to show some web component when a node is tapped. As long as the number of nodes are small lets say below 100, there is not much difference in the cpu usage after the popper appears. But for a graph with around 1000 nodes and 20 edges, after tapping a node, the cpu usage spikes from 30-35% to 80-90% and remains constant indefinitely, until the component and cytoscape instance are destroyed. I have also noticed it adds around 5000 event listeners for the same. What could be the reason for the high cpu usage ?

Below is snapshot before tapping the node:
before tap

After popper apppears:
after tap

Not able to use tippy with cytoscape

I am trying to use tippy with cytoscape and popper however I am getting "TS2693: 'Tippy' only refers to a type, but is being used as a value here." while building.

I am using ,

"tippy.js": "^4.0.0",
"cytoscape-popper": "^1.0.4",
"cytoscape": "^3.9.1",
"popper.js": "^1.14.7",
"typescript": "^3.5.3",

Following the documentation I wrote following code

import {Tippy} from "../node_modules/tippy.js/index";
// Also tried ..
// import tippy from 'tippy.js';
import PopperJs from 'popper.js';
import popper from 'cytoscape-popper';
cytoscape.use( popper );

this.cy.edges().on('mouseover', function(e) {
      var hoveredNode = e.target;

      let ref = hoveredNode.popperRef(); // used only for positioning

      let toolTip = new Tippy(ref, { // tippy options:
        content: () => {
          let content = <HTMLDivElement>document.createElement('div');

          content.innerHTML = 'Tippy content';

          return content;
        },
        trigger: 'manual' // probably want manual mode
      });
      toolTip.show();
     
    });

Could you please let me know why I am getting
"TS2693: 'Tippy' only refers to a type, but is being used as a value here."
while building?

Update Tippy example for v5

The v5 release of Tippy no longer accepts "plain objects", so the example with popperRef results in:

tippy() was passed a plain object which is no longer supported as an argument.

It would be great if the example could be updated to work with Tippy v5 (assuming it is still possible).

(Accessorily, I hope this issue will help others when they encounter the above error message; it took me a while to realize it was due to the new Tippy release, and not something else in my build.)

Edges?

Can this attach items to edges?

Tippy click trigger doesn't work

On the demo-tippy.html file, if we change the tippy trigger from 'manual' to 'click' or any other type of trigger, the tips don't show up.

only first popper visible when hideOnClick: true

I'm create popper with tippy.js using this code

let node = cy.getElementById(nextProps.selectedNode);
let tip = MakeTippy(node,nextProps.selectedNode);
tip.show();
//Meteor.setTimeout(function() {
//    tip.hide();
// }, 1500); 

MakeTippy() is the same as MakeTippy() function in "demo-tippy.html" file.
When hideOnClick: true , only first popper occurs in canvas. After first popper disappears, next ones not occur in canvas.

After the first popper, poppers occur with div which has some properties at below

class="tippy-tooltip " and "data-state="hidden"

when change this data-state to visible on devtools , poppers became visible.


Also when i change "hideOnClick: false" and comment out this line;

//Meteor.setTimeout(function() { tip.hide(); }, 1500);
I can see new poppers after old ones hide.

Bugged tooltip style

Hi guys!
I'm trying to add tooltip to my graph using the Tippy.js extension on React, but this is the final rendering:
image

I want the default tooltip layout as seen in the demo on Cytoscape page:
image

What I missing in this case? (The code is bellow)

//package.json
"dependencies": {
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
    "cytoscape": "^3.17.1",
    "cytoscape-dagre": "^2.3.2",
    "cytoscape-node-html-label": "^1.2.1",
    "cytoscape-popper": "^2.0.0",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-scripts": "4.0.1",
    "web-vitals": "^0.2.4"
  }
// App.js
import React, { useEffect } from "react";

import cytoscape from "cytoscape";
import dagre from "cytoscape-dagre";
import popper from "cytoscape-popper";
import tippy, { sticky, roundArrow } from "tippy.js";

try {
  cytoscape.use(dagre); 
} catch (e) {}

try {
  cytoscape.use(popper);
} catch (e) {}

function App() {
  useEffect(() => {
    const tree = cytoscape({
      container: document.getElementById("graph"), // container to render in
      layout: { name: "dagre" },

      elements: {
        nodes: [
          {
            data: { id: "1", shape: 'ellipse' },
            classes: ["green"],
          },
          {
            data: { id: "2", shape: 'ellipse' },
            classes: ["green"],
          },
          {
            data: { id: "3", shape: 'round-rectangle' },
            classes: ["yellow"],
          },
          {
            data: { id: "4", shape: 'round-rectangle' },
            classes: ["yellow"],
          },
          {
            data: { id: "5", shape: 'round-rectangle' },
            classes: ["yellow"],
          },
          {
            data: { id: "6", shape: 'round-octagon' },
            classes: ["red"],
          },
          {
            data: { id: "7", shape: 'round-octagon' },
            classes: ["red"],
          },
          {
            data: { id: "8", shape: 'round-octagon' },
            classes: ["red"],
          },
          {
            data: { id: "9", shape: 'round-octagon' },
            classes: ["red"],
          },
          {
            data: { id: "10", shape: 'round-octagon' },
            classes: ["red"],
          },
          {
            data: { id: "11", shape: 'round-octagon' },
            classes: ["green"],
          },
          {
            data: { id: "12", shape: 'round-octagon' },
            classes: ["green"],
          },
        ],

        edges: [
          { data: { source: "1", target: "3" } },
          { data: { source: "1", target: "4" } },
          { data: { source: "1", target: "9" } },
          { data: { source: "2", target: "4" } },
          { data: { source: "2", target: "5" } },
          { data: { source: "3", target: "6" } },
          { data: { source: "3", target: "7" } },
          { data: { source: "4", target: "7" } },
          { data: { source: "4", target: "8" } },
          { data: { source: "5", target: "8" } },
          { data: { source: "5", target: "9" } },
          { data: { source: "5", target: "10" } },
        ],
      },

      style: [
        {
          selector: "node",
          style: {
            height: 30,
            width: 30,
            label: "105%",
            "border-width": 2,
            shape: "data(shape)",

            "font-size": 10,
            "font-weight": "bold",
            "text-valign": "center",
            "text-halign": "center",
          },
        },
        {
          selector: "edge",
          style: {
            width: 1,
            "line-color": "#2d3748",
            "target-arrow-shape": "none",
          },
        },

        {
          selector: ".red",
          style: {
            "background-color": "#e4d6c1",
            "border-color": "#b50d1a",
            color: "#b50d1a",
          },
        },
        {
          selector: ".yellow",
          style: {
            "background-color": "#f1e7c6",
            "border-color": "#c3a03b",
            color: "#c3a03b",
          },
        },
        {
          selector: ".green",
          style: {
            "background-color": "#d6e6df",
            "border-color": "#49906a",
            color: "#49906a",
          },
        },
      ],
    });

    const makeTippy = (ele, text) => {
      return tippy(document.createElement("div"), {
        getReferenceClientRect: ele.popperRef().getBoundingClientRect,
        trigger: "manual", // mandatory
        hideOnClick: false,
        content: function () {
          const div = document.createElement("div");

          div.innerHTML = text;

          return div;
        },

        placement: "bottom",
        sticky: "reference",
        plugins: [sticky],
        arrow: roundArrow,

        // if interactive:
        interactive: true,
        appendTo: tree.container(), // or append dummyDomEle to document.body
      });
    };

    const node = tree.getElementById("9");
    const tooltip = makeTippy(node, "Tooltip Test");
    tooltip.show();
  }, []);

  return <div id="graph" />;
}

export default App;

Issue while adding tooltip on node using popper extensions

image

I want to achieve a tooltip pop-up when hovering over a node using the Cytoscape library and its extensions in angular framework. I have attempted this using various options, including qtip function , cytopropper.js, and the tippy plugin. However, I keep encountering the same exception that states, 'The following property does not exist in nodesingular.'" .please help me out here @kozo2 @keiono @mes5k

Exporting graphs with popper with cy.png() or cy.jpg() doesn't return the popper-divs

Issue type

New feature

Environment info

Chrome, Firefox, IE

Cytoscape.js, Browser, Node.js version

latest

Current behaviour

Exporting a graph with cytoscape-popper divs inside just exports the nodes and edges without the poppers

Desired behaviour

Exporting a graph with cy.png() or cy.jpg() exports the nodes/edges/labels and popper-divs

Minimum steps to reproduce

Just build a graph with popper inside and try to export that graph as an image.
Codepen example

Organise core JS files

  • Move core/*.js to /src
  • Rename core/index.js to /src/index.js
  • Add a /src/collection.js file (collection API function)

Interactivity question

I am not able to figure out how to get an interactive tippy tooltip. Even in the supplied tippy demo, interactive: true seems to make the tooltips disappear and the console return TypeError: t is null. Commenting that out makes the tooltips appear again.

Placement on edges

Attaching popper to edges works like a charm, but the positioning of them is... strange.
I would like to have them in the middle, but they sometimes pop up much closer to one side than another. Is this something that needs to / can be specified in the creation?

Using non basic types causes crash

I'm not being able to use properties like offset or popperOptions inside of my Tippy object.

    if (node.data().name){
      let tip = Tippy(dummyDomEle, {
        trigger: 'manual',
        lazy: false,
        arrow: true,
        theme: 'material',
        placement: 'bottom',
        offset: [0, 10],
        content: () => {
          let content = document.createElement('div');
          content.innerHTML = node.data().name;
          return content;
        },
        onCreate: instance => { instance!.popperInstance!.reference = ref; } // needed for `ref` positioning
      });
      tip.show();
    }

Code like this causes the following error:

          TS2345: Argument of type '{ trigger: string; lazy: false; arrow: true; theme: string; placement: "bottom"; offset: number[]; content: () => HTMLDivElement; onCreate: (instance: Instance<Props>) => void; }' is not assignable to parameter of type 'Partial<Props>'.
      Types of property 'offset' are incompatible.
        Type 'number[]' is not assignable to type 'string | number | undefined'.
          Type 'number[]' is not assignable to type 'number'.

If I used popperOptions none of the attributes listed in the Popper documentation can be used, they all fail with "This is not an attribute of popperOptions".

I'm using typescript here, don't know if it could be related, and these are the versions of the other libs I'm using:

    "cytoscape": "^3.14.0",
    "cytoscape-cola": "^2.3.0",
    "cytoscape-popper": "^1.0.6",
    "popper": "^1.0.1",
    "tippy.js": "^5.2.1"
    "typescript": "~3.1.2",

Any idea of what might be happening?

Thanks!

Popper does not allow to remove the node

Hello. I have a video div that always follows the mouse. The remote participant's mouse appears as a node. A video is being played over this site. When the remote participant leaves the room, I delete his node. But since a video is tied to the node using a popper, I get an error. I tried to call destroy () method on popper but it doesn't work. How can I delete a node?

 // create popper
const playerNode = cy.$id(id)

  const playerPopper = playerNode.popper({
    content: () => {return mediaDiv},
    popper: { placement: 'top'}
  })

  playerPoppersRef.current[id] = playerPopper

  let update = () => playerPopper.update()
  playerNode.on('position', update)
  cy.on('pan zoom resize', update)

// further in the code
// Try remove node: Error
const playerNode = cy.$id(id)
cy.remove(playerNode)

Error: Cannot read property 'cy' of undefined (in cytoscape-popper.js:200)

Relative container needs renderedPosition() on each popper

We use a popup menu and an always-on small question mark through popper. The cytoscape canvas is in a relative positioned container (because of absolute placement of other element).

Popper placement is always exactly (x,y) off position, where (x,y) is the position of the cytoscape container.

So each element.popper(...) call needs a call to a "fix position" function like this:

 renderedPosition: el => {
          let clpos = this.clientpos();
          let elpos = el.renderedPosition();

          return {
            x: elpos.x - clpos.x,
            y: elpos.y - clpos.y
          };
        }

Where this.clientpos() is a function in the angular component that encapsulates cytoscape:

  private clientpos(el = this.canvas.nativeElement): { x: number, y: number } {
    let x = 0;
    let y = 0;

    while (el) {
      x += (el.offsetLeft - el.scrollLeft + el.clientLeft);
      y += (el.offsetTop - el.scrollTop + el.clientTop);
      el = el.offsetParent;
    }
    return {x: x, y: y};
  }

Maybe this could be fixed by using the client position of the position container in the calculations?

Regards, Jelmer

popper not hiding with the rest of the graph when panned out of view

Was wondering if this is a problem in the cy-popper integration, or if there is some setting I'm missing.

Here's the problem - the popper icon (the lightning bolt "badge" on each node) seems to have a different z-index as the graph - notice how the popper isn't hidden like the rest of the graph when panned out of the viewing area.

large

Here's a snippet of the code:

const div = document.createElement('div');
div.className = 'glyphicon glyphicon-flash';
document.getElementById('cy')!.appendChild(div); // tried document.body.appendChild() - no difference
const popper = cyNode.popper({
   content: target => div,
   ... and the rest ...

This is the Kiali UI - a front end for Istio. The actual code right now is here: https://github.com/jmazzitelli/kiali-ui/blob/popper/src/components/CytoscapeLayout/graphs/GraphBadge.ts#L20-L69

Question

Sorry not sure where to ask this.
Is there documentation on how to use popper with react?
Or to use @tippy.js/react with cytoscape?

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.