Dojo - How can I add checkbox as a column in my DataGrid - dojo

Im just a newbie in Dojo. I have a datagrid(which I just copy paste in another tutortial), what I need is a checkbox as a column in this DataGrid. How can I achieve that? Thanks in advance for any help.
Below is my full html code:
<!DOCTYPE html>
<html >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
<link rel="stylesheet"
href="http://ajax.googleapis.com/ajax/libs/dojo/1.7/dijit/themes/claro/claro.css">
#import "js/dojo/dojox/grid/resources/claroGrid.css";
/*Grid needs an explicit height by default*/
#gridDiv
{
left: 500px;
width: 600px;
height: 20em;
margin-left: 200px;
margin-top: 100px;
padding: 10px 10px 10px 10px;
border:3px solid black;
}
#progButtonNode
{
position: relative;
}
</style>
<script>dojoConfig = {async: true, parseOnLoad: false}</script>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7/dojo/dojo.js">
</script>
<SCRIPT SRC="js/requiredDojo.js" type="text/javascript"></SCRIPT>
<script>
var grid;
require(['dojo/_base/lang', 'dojox/grid/DataGrid', 'dojo/data/ItemFileWriteStore', 'dojo/dom', 'dojo/domReady!'],
function(lang, DataGrid, ItemFileWriteStore, dom){
/*set up data store*/
var data = {
identifier: "id",
items: []
};
var data_list = [
{ col1: "normal", col2: false, col3: 'But are not followed by two hexadecimal', col4: 29.91},
{ col1: "important", col2: false, col3: 'Because a % sign always indicates', col4: 9.33},
{ col1: "important", col2: false, col3: 'Signs can be selectively', col4: 19.34}
];
var rows = 60;
for(var i = 0, l = data_list.length; i < rows; i++){
data.items.push(lang.mixin({ id: i+1 }, data_list[i%l]));
}
var store = new ItemFileWriteStore({data: data});
/*set up layout*/
var layout = [[
{'name': 'NAME', 'field': 'id', 'width': '150px'},
{'name': 'DESC', 'field': 'col2', 'width': '150px'},
{'name': 'CODE', 'field': 'col3', 'width': '150px'},
{'name': 'IS ENABLE', 'field': 'col4', 'width': '150px'}
]];
/*create a new grid*/
grid = new dojox.grid.DataGrid({
id: 'grid',
store: store,
structure: layout,
rowSelector: '20px'});
/*append the new grid to the div*/
grid.placeAt("gridDiv");
/*Call startup() to render the grid*/
grid.startup();
});
</script>
</head>
<body class="claro">
<div id="gridDiv"></div>
</body>
</html>

try
{
'name': 'NAME', 'field': 'id', 'width': '150px',
type: dojox.grid.cells.Bool, editable: true
}
you can find more details #
http://dojotoolkit.org/reference-guide/1.9/dojox/grid/DataGrid.html#editing-cells

Related

Ag Grid, prevent column hide/show using the column menu

How could I prevent column hide/show using the column menu in Ag Grid?
E.g. let us take the example from over here.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Vue example</title>
<meta charSet="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<style media="only screen">
html, body, #app {
height: 100%;
width: 100%;
margin: 0;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
}
html {
position: absolute;
top: 0;
left: 0;
padding: 0;
overflow: auto;
}
body {
padding: 1rem;
overflow: auto;
}
</style>
<link rel="stylesheet" href="styles.css"/>
</head>
<body>
<div id="app">
<my-component>Loading Vue example…</my-component>
</div>
<script>
var appLocation = './';
var boilerplatePath = '';
var systemJsMap = {
"#ag-grid-community/core/dist/styles": "https://unpkg.com/#ag-grid-community/core#27.3.0/dist/styles",
"#ag-grid-community/vue": "https://unpkg.com/#ag-grid-community/vue#27.3.0/",
"ag-grid-community": "https://unpkg.com/ag-grid-community#27.3.0/",
"ag-grid-enterprise": "https://unpkg.com/ag-grid-enterprise#27.3.0/",
"ag-grid-vue": "https://unpkg.com/ag-grid-vue#27.3.0/"
};
var systemJsPaths = {
"#ag-grid-community/client-side-row-model": "https://unpkg.com/#ag-grid-community/client-side-row-model#27.3.0/dist/client-side-row-model.cjs.min.js",
"#ag-grid-community/core": "https://unpkg.com/#ag-grid-community/core#27.3.0/dist/core.cjs.min.js",
"#ag-grid-community/csv-export": "https://unpkg.com/#ag-grid-community/csv-export#27.3.0/dist/csv-export.cjs.min.js",
"#ag-grid-community/infinite-row-model": "https://unpkg.com/#ag-grid-community/infinite-row-model#27.3.0/dist/infinite-row-model.cjs.min.js",
"#ag-grid-enterprise/charts": "https://unpkg.com/#ag-grid-enterprise/charts#27.3.0/dist/charts.cjs.min.js",
"#ag-grid-enterprise/clipboard": "https://unpkg.com/#ag-grid-enterprise/clipboard#27.3.0/dist/clipboard.cjs.min.js",
"#ag-grid-enterprise/column-tool-panel": "https://unpkg.com/#ag-grid-enterprise/column-tool-panel#27.3.0/dist/column-tool-panel.cjs.min.js",
"#ag-grid-enterprise/core": "https://unpkg.com/#ag-grid-enterprise/core#27.3.0/dist/core.cjs.min.js",
"#ag-grid-enterprise/excel-export": "https://unpkg.com/#ag-grid-enterprise/excel-export#27.3.0/dist/excel-export.cjs.min.js",
"#ag-grid-enterprise/filter-tool-panel": "https://unpkg.com/#ag-grid-enterprise/filter-tool-panel#27.3.0/dist/filter-tool-panel.cjs.min.js",
"#ag-grid-enterprise/master-detail": "https://unpkg.com/#ag-grid-enterprise/master-detail#27.3.0/dist/master-detail.cjs.min.js",
"#ag-grid-enterprise/menu": "https://unpkg.com/#ag-grid-enterprise/menu#27.3.0/dist/menu.cjs.min.js",
"#ag-grid-enterprise/multi-filter": "https://unpkg.com/#ag-grid-enterprise/multi-filter#27.3.0/dist/multi-filter.cjs.min.js",
"#ag-grid-enterprise/range-selection": "https://unpkg.com/#ag-grid-enterprise/range-selection#27.3.0/dist/range-selection.cjs.min.js",
"#ag-grid-enterprise/rich-select": "https://unpkg.com/#ag-grid-enterprise/rich-select#27.3.0/dist/rich-select.cjs.min.js",
"#ag-grid-enterprise/row-grouping": "https://unpkg.com/#ag-grid-enterprise/row-grouping#27.3.0/dist/row-grouping.cjs.min.js",
"#ag-grid-enterprise/server-side-row-model": "https://unpkg.com/#ag-grid-enterprise/server-side-row-model#27.3.0/dist/server-side-row-model.cjs.min.js",
"#ag-grid-enterprise/set-filter": "https://unpkg.com/#ag-grid-enterprise/set-filter#27.3.0/dist/set-filter.cjs.min.js",
"#ag-grid-enterprise/side-bar": "https://unpkg.com/#ag-grid-enterprise/side-bar#27.3.0/dist/side-bar.cjs.min.js",
"#ag-grid-enterprise/sparklines": "https://unpkg.com/#ag-grid-enterprise/sparklines#27.3.0/dist/sparklines.cjs.min.js",
"#ag-grid-enterprise/status-bar": "https://unpkg.com/#ag-grid-enterprise/status-bar#27.3.0/dist/status-bar.cjs.min.js",
"#ag-grid-enterprise/viewport-row-model": "https://unpkg.com/#ag-grid-enterprise/viewport-row-model#27.3.0/dist/viewport-row-model.cjs.min.js"
};
</script>
<script src="https://unpkg.com/systemjs#0.19.47/dist/system.js">
</script>
<script src="systemjs.config.js">
</script>
<script>System.import('./main.js').catch(function(err) { console.error(err); });</script>
</body>
</html>
main.js:
import 'ag-grid-community/dist/styles/ag-grid.css';
import 'ag-grid-community/dist/styles/ag-theme-alpine.css';
import 'ag-grid-enterprise';
import { AgGridVue } from 'ag-grid-vue';
import Vue from 'vue';
const VueExample = {
template: `
<div style="height: 100%">
<div class="example-wrapper">
<div>
<span class="button-group">
<button v-on:click="showPivotModeSection()">Show Pivot Mode Section</button>
<button v-on:click="showRowGroupsSection()">Show Row Groups Section</button>
<button v-on:click="showValuesSection()">Show Values Section</button>
<button v-on:click="showPivotSection()">Show Pivot Section</button>
</span>
</div>
<ag-grid-vue
style="width: 100%; height: 100%;"
class="ag-theme-alpine"
:columnDefs="columnDefs"
#grid-ready="onGridReady"
:defaultColDef="defaultColDef"
:sideBar="sideBar"
:rowData="rowData"></ag-grid-vue>
</div>
</div>
`,
components: {
'ag-grid-vue': AgGridVue,
},
data: function () {
return {
columnDefs: [
{ headerName: 'Name', field: 'athlete', minWidth: 200 },
{ field: 'age', enableRowGroup: true },
{ field: 'country', minWidth: 200 },
{ field: 'year' },
{ field: 'date', suppressColumnsToolPanel: true, minWidth: 180 },
{ field: 'sport', minWidth: 200 },
{ field: 'gold', aggFunc: 'sum' },
{ field: 'silver', aggFunc: 'sum' },
{ field: 'bronze', aggFunc: 'sum' },
{ field: 'total', aggFunc: 'sum' },
],
gridApi: null,
columnApi: null,
defaultColDef: {
flex: 1,
minWidth: 100,
sortable: true,
enablePivot: true,
},
sideBar: null,
rowData: null,
};
},
created() {
this.sideBar = {
toolPanels: [
{
id: 'columns',
labelDefault: 'Columns',
labelKey: 'columns',
iconKey: 'columns',
toolPanel: 'agColumnsToolPanel',
toolPanelParams: {
suppressRowGroups: true,
suppressValues: true,
suppressPivots: true,
suppressPivotMode: true,
suppressColumnFilter: true,
suppressColumnSelectAll: true,
suppressColumnExpandAll: true,
},
},
],
defaultToolPanel: 'columns',
};
},
methods: {
showPivotModeSection() {
var columnToolPanel = this.gridApi.getToolPanelInstance('columns');
columnToolPanel.setPivotModeSectionVisible(true);
},
showRowGroupsSection() {
var columnToolPanel = this.gridApi.getToolPanelInstance('columns');
columnToolPanel.setRowGroupsSectionVisible(true);
},
showValuesSection() {
var columnToolPanel = this.gridApi.getToolPanelInstance('columns');
columnToolPanel.setValuesSectionVisible(true);
},
showPivotSection() {
var columnToolPanel = this.gridApi.getToolPanelInstance('columns');
columnToolPanel.setPivotSectionVisible(true);
},
onGridReady(params) {
this.gridApi = params.api;
this.gridColumnApi = params.columnApi;
const updateData = (data) => params.api.setRowData(data);
fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
.then((resp) => resp.json())
.then((data) => updateData(data));
},
},
};
new Vue({
el: '#app',
components: {
'my-component': VueExample,
},
});
style.css:
.example-wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
#myGrid {
flex: 1 1 0px;
width: 100%;
}
.button-group {
padding-bottom: 4px;
display: inline-block;
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
}
When I go to the Name's column menu I can hide/show the Age column. I do not want to be able to be able to do that. How could I prevent this functionality?
[![enter image description here][1]][1]
Are you using AG Grid standalone or with Adaptable?
If you are using Adaptable also as we are then they have functions you can provide which will set whether or not the Column menu should appear in a given column.
See: https://docs.adaptabletools.com/guide/reference-options-menu#showadaptablecolumnmenu
And for Column Menus generally see: https://docs.adaptabletools.com/guide/ui-column-menu

double click on nodes in cytoscape.js is not working

I have a problem with this plugin. I want to double click on nodes and the id of nodes should be displayed in console. I added the link of this extension from https://github.com/fixpoint/cytoscape-dblclick and followed by this post Cytoscape js - Call a function whenever a node is clicked, but still is not working.
Is anybody have any idea why it is not working, it would be nice if you share it.
You can see my code:
$(function() {
var elements = {
nodes: [
],
edges: [
]
};
function randomNumber(a) {
return Math.floor(Math.random() * (a));
}
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
ready: function() {},
style: [{
selector: "node", //edge
style: {
content: "data(id)",
shape: "roundrectangle", //square, circle
"text-valign": "center",
"text-halign": "center",
height: "60px", //new
width: "100px", //new
//padding: "10px", //new
"text-wrap": 'wrap', //new
color: "#fff",
"background-color": "#11479e",
// "background-color": "data(faveColor)"
}
},
{
//arrows
selector: "edge",
style: {
"curve-style": "taxi",
//'background-color': '#008000',
width: 4,
"target-arrow-shape": "triangle",
"line-color": "#9dbaea",
"target-arrow-color": "#9dbaea"
}
}
],
});
cy.dblclick();
cy.on('dblclick', function(evt) {
console.log('dblclick');
cy.animate({
fit: {
eles: evt.target,
padding: 10,
},
});
});
cy.on('dblclick:timeout', function(evt) {
console.log('dblclick:timeout');
});
var ab = 12;
for (var i = 0; i < ab; i++) {
//elements.nodes.push({ "data": { "id": i } });
cy.add([{
group: "nodes",
data: {
id: i
}
}
])
}
var cb = 20;
for (var i = 0; i < cb; i++) {
cy.add([{
group: "edges",
data: {
source: randomNumber(ab),
target: randomNumber(ab)
}
}])
}
cy.layout({
name: "dagre", //dagre, grid
directed: true,
nodeDimensionsIncludeLabels: true,
boxSelectionEnabled: true,
autounselectify: true,
zoomingEnabled: true,
userZoomingEnabled: true,
styleEnabled: true
}).run();
cy.elements().qtip({
content: function() {
return 'Text, Test ' + this.id()
},
position: {
my: 'center left', //top center
at: 'center right' //bottom center
},
style: {
classes: 'qtip-bootstrap', //qtip-dark
tip: {
width: 16,
height: 10
}
}
});
// });
}); //end
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
<!DOCTYPE>
<html>
<head>
<title>cytoscape-panzoom.js demo</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<link href="cytoscape.js-panzoom.css" rel="stylesheet" type="text/css" />
<link href="font-awesome-4.0.3/css/font-awesome.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<!-- partial -->
<script src="https://js.cytoscape.org/js/cytoscape.min.js"></script>
<script src="https://cdn.rawgit.com/cpettitt/dagre/v0.7.4/dist/dagre.min.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
<!-- qtip Links -->
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-qtip/2.7.0/cytoscape-qtip.js"></script>
<!-- for testing with local version of cytoscape.js -->
<!-- <script src="../cytoscape.js/build/cytoscape.js"></script> -->
<script src="https://unpkg.com/cytoscape-dblclick/dist/index.js"></script>
<script src="cytoscape-panzoom.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
Just follow the post you already linked and log the node information instead of fitting the graph to the clicked node. Also, your demo had some static scripts in the header, I removed them for that reason. That way, the qtip works again too:
$(function() {
var elements = {
nodes: [
],
edges: [
]
};
function randomNumber(a) {
return Math.floor(Math.random() * (a));
}
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
ready: function() {},
style: [{
selector: "node", //edge
style: {
content: "data(id)",
shape: "roundrectangle", //square, circle
"text-valign": "center",
"text-halign": "center",
height: "60px", //new
width: "100px", //new
//padding: "10px", //new
"text-wrap": 'wrap', //new
color: "#fff",
"background-color": "#11479e",
// "background-color": "data(faveColor)"
}
},
{
//arrows
selector: "edge",
style: {
"curve-style": "taxi",
//'background-color': '#008000',
width: 4,
"target-arrow-shape": "triangle",
"line-color": "#9dbaea",
"target-arrow-color": "#9dbaea"
}
}
],
});
cy.dblclick();
cy.on('dblclick', function(evt) {
console.log(evt.target.id());
});
var ab = 12;
for (var i = 0; i < ab; i++) {
//elements.nodes.push({ "data": { "id": i } });
cy.add([{
group: "nodes",
data: {
id: i
}
}
])
}
var cb = 20;
for (var i = 0; i < cb; i++) {
cy.add([{
group: "edges",
data: {
source: randomNumber(ab),
target: randomNumber(ab)
}
}])
}
cy.layout({
name: "dagre", //dagre, grid
directed: true,
nodeDimensionsIncludeLabels: true,
boxSelectionEnabled: true,
autounselectify: true,
zoomingEnabled: true,
userZoomingEnabled: true,
styleEnabled: true
}).run();
cy.elements().qtip({
content: function() {
return 'Text, Test ' + this.id()
},
position: {
my: 'center left', //top center
at: 'center right' //bottom center
},
style: {
classes: 'qtip-bootstrap', //qtip-dark
tip: {
width: 16,
height: 10
}
}
});
// });
}); //end
body {
font-family: helvetica;
font-size: 14px;
}
#cy {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 999;
}
h1 {
opacity: 0.5;
font-size: 1em;
}
<!DOCTYPE>
<html>
<head>
<title>cytoscape-panzoom.js demo</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<!--<link href="cytoscape.js-panzoom.css" rel="stylesheet" type="text/css" />-->
<!--<link href="font-awesome-4.0.3/css/font-awesome.css" rel="stylesheet" type="text/css" />-->
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<!-- partial -->
<script src="https://js.cytoscape.org/js/cytoscape.min.js"></script>
<script src="https://cdn.rawgit.com/cpettitt/dagre/v0.7.4/dist/dagre.min.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
<!-- qtip Links -->
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-qtip/2.7.0/cytoscape-qtip.js"></script>
<!-- for testing with local version of cytoscape.js -->
<!-- <script src="../cytoscape.js/build/cytoscape.js"></script> -->
<script src="https://unpkg.com/cytoscape-dblclick/dist/index.js"></script>
<!--<script src="cytoscape-panzoom.js"></script>-->
</head>
<body>
<div id="cy"></div>
</body>
</html>

How can I make the label of an edge displayed just in the middle position?

I'm trying to make the label displayed in the middle position, say source --<sometext>--> target.
I'm reading the official document but I can't find an answer.
Can this be implemented?
as you can see here, there is a simple solution to this provided by cytoscape:
window.cy = cytoscape({
container: document.getElementById('cy'),
layout: {
name: 'grid',
cols: 2
},
style: [{
"selector": "node[label]",
"style": {
"label": "data(label)"
}
},
{
"selector": "edge[label]",
"style": {
"label": "data(label)",
"width": 3,
"text-background-opacity": 1,
"text-background-color": "#fff"
}
},
{
"selector": ".autorotate",
"style": {
"edge-text-rotation": "autorotate",
}
}
],
elements: [{
data: {
id: 'one'
}
},
{
data: {
id: 'two'
}
}, {
data: {
source: 'one',
target: 'two',
label: 'autorotate (move my nodes)'
},
classes: 'autorotate'
}
]
});
body {
font-family: helvetica, sans-serif;
font-size: 14px;
}
#cy {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: 999;
}
<html>
<head>
<title>Labels demo</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1">
<script src="https://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>

Cytoscape.js: Overlapping edge labels in multigraph

There are several posts about edge or edge label overlaps in Cytoscape.js but the answers given there, like smaller labels and more spaced out nodes, don't help for a multigraph, i.e. a graph where two nodes can have multiple edges between them.
Is there a way to spread out edge labels even if they all belong to edges between the same two nodes? The edge pairs occur both in the same direction and in the reverse one.
As my graph is verly large, I would prefer a solution with haystack edges as the performance is already low.
Well you can rotate the text with "text-rotation": "autorotate" in the labels css. You can also define the "text-margin-x/y" for each node itself, but how do you plan on defining the position for each and every label? Lets assume, you did that perfectly: you would still need to do a reposition event after moving just one node, because the offsets will be off by then:
var cy = (window.cy = cytoscape({
container: document.getElementById("cy"),
boxSelectionEnabled: false,
autounselectify: true,
style: [{
selector: "node",
css: {
content: "data(id)",
"text-valign": "center",
"text-halign": "center",
height: "60px",
width: "60px",
"border-color": "black",
"border-opacity": "1",
"border-width": "10px"
}
},
{
selector: "$node > node",
css: {
"padding-top": "10px",
"padding-left": "10px",
"padding-bottom": "10px",
"padding-right": "10px",
"text-valign": "top",
"text-halign": "center",
"background-color": "#bbb"
}
},
{
selector: "edge",
css: {
"target-arrow-shape": "triangle"
}
},
{
selector: "edge[label]",
css: {
"label": "data(label)",
"text-rotation": "autorotate",
"text-margin-x": "data(xalign)",
"text-margin-y": "data(yalign)"
}
},
{
selector: ":selected",
css: {
"background-color": "black",
"line-color": "black",
"target-arrow-color": "black",
"source-arrow-color": "black"
}
}
],
layout: {
name: "circle"
}
}));
var info = [{
name: "Peter",
next_op_name: "Claire"
},
{
name: "Claire",
next_op_name: "Mike"
},
{
name: "Mike",
next_op_name: "Rosa"
},
{
name: "Rosa",
next_op_name: "Peter"
}
];
cy.ready(function() {
var array = [];
// iterate over info once
for (var i = 0; i < info.length; i++) {
array.push({
group: "nodes",
data: {
id: info[i].name, // id is name!!!
label: info[i].name
}
});
array.push({
group: "edges",
data: {
id: "e" + i,
source: info[i].name,
target: info[i].next_op_name,
label: "e" + i,
xalign: (i == 0 || i == 1 ? '15px' : '-15px'),
yalign: (i == 0 || i == 3 ? '15px' : '-15px')
}
});
}
cy.add(array);
cy.layout({
name: "circle"
}).run();
});
cy.on("mouseover", "node", function(event) {
var node = event.target;
node.qtip({
content: "hello",
show: {
event: event.type,
ready: true
},
hide: {
event: "mouseout unfocus"
}
},
event
);
});
cy.on("tapdrag", "node", function(event) {
// update all relevant labels
var labels = event.target.connectedEdges();
for (var i = 0; i < labels.length; i++) {
// render with the right positions?
}
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 75%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<head>
<meta charset=utf-8 />
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.17/cytoscape.min.js"></script>
<!-- qtip imports -->
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-qtip/2.7.0/cytoscape-qtip.js"></script>
<!-- dagre imports -->
<script src="https://unpkg.com/dagre#0.7.4/dist/dagre.js"></script>
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-dagre/1.5.0/cytoscape-dagre.js"></script>
</head>
<body>
<div id="cy"></div>
</body>
</html>
The problem breaks down to this: the task seems simple, but keeping track of the positions of all nodes and the edges aaaaand your rendered labels is a sisyphean task.

How to set QTip to always show tooltips in Cytoscape.js

I'm looking for a way of getting QTip to concurrently display tooltips for each node in a Cytoscape.js graph, such that they are always displayed and anchored to the nodes in the graph without the user having to click or mouseover the node.
I got close with the code below:
$(document).ready(function(){
cy.nodes().qtip({
content: function(){ return 'Station: ' + this.id() +
'</br> Next Train: ' + this.data('nextTrain') +
'</br> Connections: ' + this.degree();
},
hide: false,
show: {
when: false,
ready: true
}
})
})
The above code displays tooltips on $(document).ready, but they are all located at one node in the Cytoscape graph and they disappear when I zoom in or pan at all.
The goal is to have tooltips anchored to each node in my graph such that when I zoom in and pan around they remain fixed to that node. I'm not sure if there is an easier way to do this just using Cytoscape (i.e., multi-feature labelling).
I'm using Qtip2, jQuery-2.0.3 and the most recent release of cytoscape.js
Any help is much appreciated.
EDIT: If you want to create these elements automatically, use a function and a loop to iterate over cy.nodes():
var makeTippy = function (nodeTemp, node) {
return tippy(node.popperRef(), {
html: (function () {
let div = document.createElement('div');
// do things in div
return div;
})(),
trigger: 'manual',
arrow: true,
placement: 'right',
hideOnClick: false,
multiple: true,
sticky: true
}).tooltips[0];
};
var nodes = cy.nodes();
for (var i = 0; i < nodes.length; i++) {
var tippy = makeTippy(nodes[i]);
tippy.show();
}
If you want a sticky qTip, I would instead recommend the cytoscape extension for popper.js and specificly the tippy version (sticky divs):
document.addEventListener('DOMContentLoaded', function() {
var cy = window.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();
});
body {
font-family: helvetica neue, helvetica, liberation sans, arial, sans-serif;
font-size: 14px
}
#cy {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 1;
}
h1 {
opacity: 0.5;
font-size: 1em;
font-weight: bold;
}
/* makes sticky faster; disable if you want animated tippies */
.tippy-popper {
transition: none !important;
}
<!DOCTYPE>
<html>
<head>
<title>Tippy > qTip</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="cytoscape-popper.js"></script>
<script src="https://unpkg.com/tippy.js#2.0.9/dist/tippy.all.js"></script>
<link rel="stylesheet" href="https://unpkg.com/tippy.js#2.0.9/dist/tippy.css" />
<script src="https://cdn.jsdelivr.net/npm/cytoscape-popper#1.0.2/cytoscape-popper.js"></script>
</head>
<body>
<h1>cytoscape-popper tippy demo</h1>
<div id="cy"></div>
</body>
</html>
I think popper is just easier to handle when having the divs 'stick around'