Qtip not working with jquery and ajax in Cytoscape.js

459 Views Asked by At

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();
});

 });
1

There are 1 best solutions below

1
maxkfranz On

Structure your init like this:

let toJson = res => res.json();

let cy = new Cytoscape({
  elements: fetch('some/cytoscape/elements.json').then( toJson ),
  style: fetch('some/cytoscape/style.json').then( toJson ),
  // ...
});

cy.ready( () => {
  // specify qtips here, after the external data is loaded
} );

// or if you prefer promises, you can use a ready promise
// let readyPromise = new Promise( resolve => cy.ready(resolve) );

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 cy variable 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.