I am trying to dynamically load a Cytoscape JSON elements file and display qtip text when a node in the network is clicked. This exact same code works when I hard code the network in the code so there is nothing wrong with the cyjs file or the qtip part of the code. Somehow the qtip is not working with ajax and jquery.
Any help would be appreciated! Thank you!
$(function() {
$.get('demo.cyjs', function( data ) {
$('#cy').cytoscape({
layout: {
name: 'concentric',
concentric: function( node ){
return node.degree();
},
levelWidth: function( nodes ){
return 2;
}
},
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(name)',
'text-valign': 'bottom',
'color': 'white',
'font-size': 10,
'background-color': 'data(faveColor)'
})
.selector('edge')
.css({
'target-arrow-shape': 'none',
'curve-style':'haystack',
'line-color':'data(faveColor)',
'line-style': 'data(style)',
'haystack-radius': 0,
'width':'data(Ratio)'
})
.selector(':selected')
.css({
'background-color': 'grey',
'target-arrow-color': 'grey',
'source-arrow-color': 'grey',
'border-width': 3,
'border-color': '#333'
})
.selector('.faded')
.css({
'opacity': 1,
'text-opacity': 0
}),
elements : JSON.parse(data),
});
})
cy.nodes().forEach(function(n){
var a = n.data('ensembl_id');
var p=n.data('primes_id');
var e=n.data('ncbi_id');
var u=n.data('uniprot_id');
n.qtip({
content: [
{
name: 'ENSEMBL',
url: 'http://www.ensembl.org/Homo_sapiens/Gene/Summary?db=core;g='+ a
},
{
name: 'UniProt',
url: 'http://www.uniprot.org/uniprot/'+ u
},
{
name: 'NCBI',
url: 'https://www.ncbi.nlm.nih.gov/gene/' + e
}
].map(function( link ){
return '<a target="_blank" href="' + link.url + '">' + link.name + '</a>';
}).join('<br />\n'),
position: {
my: 'top center',
at: 'bottom center'
},
style: {
classes: 'qtip-bootstrap',
tip: {
width: 16,
height: 8
}
}
});
});
$('#config-toggle').on('click', function(){
$('body').toggleClass('config-closed');
cy.resize();
});
});
This is my updated code. I have initialised cy element in the body tag
<div id="cy"></div>
$(function() {
let toJson = res => res.json();
let cy = new cytoscape({
layout: {
name: 'concentric',
concentric: function( node ){
return node.degree();
},
levelWidth: function( nodes ){
return 2;
}
},
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(name)',
'text-valign': 'bottom',
'color': 'white',
'font-size': 10,
'background-color': 'data(faveColor)'
})
.selector('edge')
.css({
'target-arrow-shape': 'none',
'curve-style':'haystack',
'line-color':'data(faveColor)',
'line-style': 'data(style)',
'haystack-radius': 0,
'width':'data(Ratio)'
})
.selector(':selected')
.css({
'background-color': 'grey',
'target-arrow-color': 'grey',
'source-arrow-color': 'grey',
'border-width': 3,
'border-color': '#333'
})
.selector('.faded')
.css({
'opacity': 1,
'text-opacity': 0
}),
elements: fetch('demo.cyjs').then( toJson ),
});
cy.ready( () => {
var a = n.data('ensembl_id');
var p=n.data('primes_id');
var e=n.data('ncbi_id');
var u=n.data('uniprot_id');
n.qtip({
content: [
{
name:'PrimesDB',
url:'http://primesdb.org/molecules/view/'+ p
},
{
name: 'ENSEMBL',
url: 'http://www.ensembl.org/Homo_sapiens/Gene/Summary?db=core;g='+ a
},
{
name: 'UniProt',
url: 'http://www.uniprot.org/uniprot/'+ u
},
{
name: 'NCBI',
url: 'https://www.ncbi.nlm.nih.gov/gene/' + e
}
].map(function( link ){
return '<a target="_blank" href="' + link.url + '">' + link.name + '</a>';
}).join('<br />\n'),
position: {
my: 'top center',
at: 'bottom center'
},
style: {
classes: 'qtip-bootstrap',
tip: {
width: 16,
height: 8
}
}
});
});
$('#config-toggle').on('click', function(){
$('body').toggleClass('config-closed');
cy.resize();
});
});
Structure your init like this:
You're not waiting for the elements to load from your JSON file, so there are no elements in the graph when you do your
forEach(). It's often easier to let Cytoscape handle the loading of the elements and the stylesheet for you. Just specify promises in place of in-line objects/JSON.I also don't see any
cyvariable in your code.Anything in the
cy.ready()callback will execute only after the data from init has loaded properly. A side benefit is that you can easily separate your stylesheet into a new JSON file, keeping your code shorter and making it easier to switch between stylesheets.