Wiki Discussion: Generating Cytoscape.js graphs with SWI-Prolog

This is a topic to discuss the Wiki

Generating Cytoscape.js graphs with SWI-Prolog

1 Like

For those wanting to get a taste of creating Cytoscape.js graphs using SWI-Prolog read Convert facts to GraphViz dot file using DCGs then find and work the tutorials in the Cytoscape.js blog.

The tutorials seem to be dated and gloss over some needed points so they are not a straight forward following the tutorial, you will have to draw upon your knowledge of HTML, JavaScript, CSS, JSON and SVG to get them to work.

I have completed the first tutorial: Getting started with Cytoscape.js, and currently working through Visualizing Glycolysis with Cytoscape.js.


In searching for a way to use graphs more interactively ran across animations with D3. D3 has animations, and it appears Cytoscape.js might have something similar, but have not found a similar working example just yet.

Check out this D3 animation and then think about teaching Prolog to new users needing a visual animated example as an answer and you start to see how much these become useful.

Here is an example of a Cytoscape.js animation: https://js.cytoscape.org/demos/animated-bfs/


Related:

swish_cytoscape_js


Personal notes

The Cytoscape.js tutorial demo gives a very simple demonstration of what can be done with Cytoscape.js. The code in in a GitHub repository that is designed for adding custom elements systems and Stylesheets and/or layouts.


Note: Using background-image one has to be sensitive to: CORS header ‘Access-Control-Allow-Origin’ missing.
Cross-Origin Resource Sharing (CORS)


node.js - Useful for running JavaScript as a server.

node.js http-server is a simple, zero-configuration command-line http server. It is powerful enough for production usage, but it’s simple and hackable enough to be used for testing, local development, and learning.

Steps to test Cytoscape.js tutorials on a local machine. Think workaround to avoid CORS errors.

  1. Download and install node.js
    https://nodejs.org/en/download/
  2. Install http-server package
    npm install --global http-server
  3. Change to directory that is the root of the files for the web site
  4. Create batch file to set Windows Path and start http-server
SET PATH="C:\Program Files (x86)\nodejs";"C:\Users\<user>\AppData\Roaming\npm";"C:\Users\<user>\AppData\Roaming\npm\node_modules\http-server"
http-server --cors

Start http-server by running batch file
http_server.bat
Using Internet browser access web pages
http://127.0.0.1:8080

This is also useful for access individual image files to make sure they load and display, e.g.

http://127.0.0.1:8080/glucose.svg

[Mon Aug 24 2020 15:03:50 GMT-0400 (Eastern Daylight Time)]  "GET /glucose.svg" "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"

When running the Node.js http-server it will list actions and errors in the Windows console.

[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/13bpg.svg" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19041"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/glucose.svg" Error (404): "Not found"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/g6p.svg" Error (404): "Not found"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/f6p.svg" Error (404): "Not found"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/f16bp.svg" Error (404): "Not found"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/2pg.svg" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19041"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/pep.svg" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19041"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/gadp.svg" Error (404): "Not found"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/13bpg.svg" Error (404): "Not found"
[Tue Aug 25 2020 07:46:34 GMT-0400 (Eastern Daylight Time)]  "GET /assets/pyruvate.svg" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19041"

Remember to press F12 key when running the Internet browser to see any errors. This is where the CORS errors are reported.


Chrome Internet browser

Chrome Dev Tools

How to Completely Disable Cache in Google Chrome

Google Chrome - Clear cache & cookies

Open Chrome debugger in separate window (ref)

View Page Resources With Chrome DevTools
such as HTML, CSS, JavaScript, JSON. (ref)


SVG node background tutorial
http://embed.plnkr.co/wLuoon/

To see image height and width of an image in Chrome: Image Size Info - Browser Extension

JavaScript Errors - Throw and Try to Catch

Create SVG file by drawing.
Online tool: Method Draw
Application: Inkscape

Scalable Vector Graphics (SVG) 1.1 (Second Edition)

Should you use or learn jQuery in 2020?

Alignment constraints with guidelines

https://cdnjs.com/libraries/cytoscape

Web Open Font Format

JSONLint - The JSON Validator

Why are there warnings about DevTools failed to load source map?
See: Use a source map

Cytoscape.js can import/export the elements as JSON (cy.json()) and supports two different formats (ref)

  1. array of collections
  2. array of elements

NB The nodes for a graph are AFAIK not accessible from from an Internet Browser console. They are obviously accessible in from JavaScript of the source document.

To export the cytoscape graph as JSON

  1. Create a button in the HTML body tag
<input type='button' id='advance' value='Export'>
  1. Add a listener event for the button. This goes within document.addEventListener("DOMContentLoaded", function ()
document.addEventListener("DOMContentLoaded", function () {
var toJSONButton = document.getElementById('advance');
    toJSONButton.addEventListener('click', function () {
        var result = toJsonButton();
    });
}
  1. Add handler for listener. This goes within document.addEventListener("DOMContentLoaded", function ()
document.addEventListener("DOMContentLoaded", function () {
    function toJsonButton() {
        var cyFlatJson = cy.json(true);
        var cyGroupJson = cy.json(false);
        console.log(JSON.stringify(cyFlatJson));
        console.log(JSON.stringify(cyGroupJson));
    }
});

Clicking on the Export button will write two strings to the browser console. The browser console is accessible by clicking F12 in an open Internet browser.


GitHub repositories
Topics: Cytoscape.js

cytoscape/cytoscape.js
plotly/dash-cytoscape - Has some interesting ideas and examples. Uses Python with Cytoscape.js

i-Vis at Bilkent - i-Vis Research Lab at Bilkent University
Has many repositories related to Cytoscape.js - The code is worth studying for examples.

Newt Pathway Viewer & Editor - Newt is a free, web based, open source viewer and editor for pathways in Systems Biological Graphical Notation (SBGN) and Simple Interaction Format (SIF). It was written with a series of libraries and extensions based on Cytoscape.js with utmost customization in mind. (Think Visio).
http://web.newteditor.org/ - Press F12 to see code.

demonray/cyeditor - A visual flow chart editor based on cytoscape.js. (Think Visio).

upsetjs/cytoscape.js-bubblesets

lukasy09/NeuralNetworkTool


Using Fetch

A basic fetch request is really simple to set up. Have a look at the following code:

fetch('http://example.com/movies.json')
  .then(response => response.json())
  .then(data => console.log(data));

JavaScript read JSON from URL


HTML

Best Practices In Modern Web Design: The Ultimate Round-Up
HTML <script> defer Attribute

Meta

HTTP headers

Viewport
Useful HTML Meta Tags


JavaScript

The Modern JavaScript Tutorial

Functions (MDN) (w3Schools) (javascript.info)

Arrow function expressions (MDN) (w3schools) (javascript.info)
Promise (MDN) (javascript.info) (pouchdb) (Promises/A+)
Promises chaining (MDN) (javascript.info) (medium.com)

image

Image (ref)
The future of JavaScript isn’t what it used to be


Papers:

A Technique for Drawing Directed Graphs (ref)
Visualisation of state machines using the Sugiyama
framework (ref)


JSON

Sites for testing JSON
Using JSON with SWI-Prolog

TypeScript

Type definitions for Cytoscape.js 3.1 (ref)

Online editor

CodeMirror - used by codepen.io

__

StackOverflow Cytoscape.js Q&A

What is the difference between D3.js and Cytoscape.js?
CytoscapeJS background color grey
I can’t get cytoscape.js to display my chart at all
Conditional styling for cytoscape
How to make cytoscape-ctxmenu.js applicable on nodes with condition?
Different behaviour for leaf nodes cytoscape
Show edge id on click
Find selected nodes/edges in cytoscape.js “on(‘unselect’)” event
Show dependet edge(s) when user click on node
How to draw an edge between two node in cytoscape with mouse drag drop
How do I reference ID as a variable in cytoscape.js
Cytoscape: show node/edge attributes in table when clicking on it
Set link behind background image and make it clickable Cytoscape.js
Add diffrenet href to some nodes in cytoscape.js
Rendering a family tree with d3 or cytoscape
How to listen to drag event of CytoscapeJS node (including only the one directly under the cursor/finger)
How to totally disable elements events?
Is there any example or sample code for the find and filter feature in Cytoscape JS
Is is possible to have a bidirectional edge in Cytoscape.js?
What javascript include files are needed to get layout extensions to work in cytoscape?
Use Algrebraic Operation in Cytoscape Selector Style Sheet
Cytoscape.js : right click event on nodes
see the list of event listeners currently attached
Filtering graph by connectivity to a specific node in cytoscape.js
Changing color when node is selected in Cytoscape JS
Cytoscape js how to get all edges (text label) when clicked on a node
CytoscapeJS background color grey
How to highlight neighbouring nodes in Cytoscape.js
How to highlight the path between two nodes in CYTOSCAPE JS
Content and Label on a Node - Cytoscape

2 Likes

@CapelliC

FYI

If you had not posted a reference to Cytoscape.js many months back I would not have been using it today. Thanks! :smiley:

Feel free to edit and add to the Wiki page. I don’t know how much more you know about using Cytoscape.js than me, but if you know much more, feel free to take the lead on this and rewrite the Wiki as you see fit or start a separate one.

This is some prototype code along the way for the proof of concept. It still requires a few manual steps but since prototype code is useful for converting into tutorials because it works and doesn’t drop all of the moving parts in the final version it is posted here.

Use: Create module.jorunal - Collect a set of facts that can make a graph (nodes and edges) and save to a file using library(persistency).
File: persist module facts.pl

:- module(persist_module_facts,[
        init/0,
        list_predicates_import_from/1,
        list_predicate_import_from/1,
        list_imports/1
    ]).

% -----------------------------------------------------------------------------

:- use_module(library(persistency)).

:- persistent
    predicates_import_from(import_module:atom,export_module:atom),
    predicate_import_from(import_module:atom,export_module:atom,predicate_indicator:compound),
    imports(import_module:atom,export_module:atom).

:- initialization(main).

main :-
    db_attach('module.journal', []),
    init.

add_predicates_import_from(Import_module,Export_module) :-
    (
        predicates_import_from(Import_module,Export_module), !
    ;
        assert_predicates_import_from(Import_module,Export_module)
    ).

add_predicate_import_from(Import_module,Export_module,Name/Arity) :-
    (
        predicate_import_from(Import_module,Export_module,Name/Arity), !
    ;
        assert_predicate_import_from(Import_module,Export_module,Name/Arity)
    ).

add_imports(Import_module,Export_module) :-
    (
        imports(Import_module,Export_module), !
    ;
        assert_imports(Import_module,Export_module)
    ).

init_imported_from :-
    forall(
            predicate_property(Import_module:Predicate, imported_from(Export_module)),
            (
                add_predicates_import_from(Import_module,Export_module),
                functor(Predicate,Name,Arity),
                add_predicate_import_from(Import_module,Export_module,Name/Arity)
            )
        ).

init_import_module :-
    forall(
            (
                current_module(Import_module),
                import_module(Import_module,Export_module)
            ),
            add_imports(Import_module,Export_module)
        ).

init :-
    init_imported_from,
    init_import_module.

list_predicates_import_from(predicates_import_from(Import_module,Export_module)) :-
    predicates_import_from(Import_module,Export_module).

list_predicate_import_from(predicate_import_from(Import_module,Export_module,Predicate)) :-
    predicate_import_from(Import_module,Export_module,Predicate).

list_imports(imports(Import_module,Export_module)) :-
    imports(Import_module,Export_module).

Example run:

?- working_directory(_,'C:/Users/Groot/Documents').
true.

?- ['persist module facts'].
true.

?- halt.

halt. is needed to write the facts out to the file module.jorunal

Use: Create elements.js - Convert the facts from the persistent file and format them for use with Cytoscape.js. Cytoscape.js can read the elements (nodes and edges) as JSON and by packing the JSON into a JavaScript variable the code to use it can hopefully become boilerplate code.
File: Cytoscape.js elements - DCG generator.pl

:- module('Cytoscape.js elements - DCG generator',[
      predicates_import_from/2,
      predicate_import_from/3,
      imports/2,
      write_elements_var/1
   ]).

% -----------------------------------------------------------------------------

:- use_module(library(persistency)).
:- use_module(library(fileutils)).

:- set_prolog_flag(double_quotes, codes).

:- persistent
    predicates_import_from(import_module:atom,export_module:atom),
    predicate_import_from(import_module:atom,export_module:atom,predicate_indicator:compound),
    imports(import_module:atom,export_module:atom).

:- initialization(db_attach('C:/Users/Groot/Documents', [])).

write_elements_var(Filepath) :-
   nodes(Nodes),
   edges(Edges),
   cytoscape_js_elements(Nodes,Edges,Elements_var),
   with_output_to_file(Filepath,write(Elements_var)).

nodes(Nodes) :-
   setof(node(A),B^predicates_import_from(A,B),From),
   setof(node(B),A^predicates_import_from(A,B),To),
   ord_union(From,To,Nodes), !.

edges(Edges) :-
   setof(edge(A,B),predicates_import_from(A,B),Edges).

cytoscape_js_elements(Nodes,Edges,Elements_var) :-
   phrase(elements_var(Nodes,Edges),Codes,[]),
   string_codes(Elements_var,Codes).

% The JSON is passed as the JavaScript variable Elements.
elements_var(Nodes,Edges) -->
   "// Elements is JSON\n// See: https://js.cytoscape.org/#notation/elements-json\nvar Elements = ",
   elements(Nodes,Edges),
   ";".

% This starts the JSON part.
elements(Nodes,Edges) -->
   "{\n",
   "\tnodes: [\n",
   nodes_first(Nodes),
   "\n\t]",
   ",\n",
   "\tedges: [\n",
   edges_first(Edges),
   "\n\t]\n",
   "}".

nodes_first([H|T]) -->
   node(H),
   nodes_rest(T).

nodes_rest([H|T]) -->
   ",\n",
   node(H),
   nodes_rest(T).
nodes_rest([]) --> [].

node(node(Id)) -->
   { string_codes(Id,Id_codes) },
   "\t\t{ data: { id: \"",
   Id_codes,
   "\" } }".

edges_first([H|T]) -->
   edge(H),
   edges_rest(T).

edges_rest([H|T]) -->
   ",\n",
   edge(H),
   edges_rest(T).
edges_rest([]) --> [].

edge(edge(From,To)) -->
   {
      string_codes(From,From_codes),
      string_codes(To,To_codes)
   },
   "\t\t{ data: { source: \"",
   From_codes,
   "\", target: \"",
   To_codes,
   "\" } }".

Example run:

?- working_directory(_,'C:/Users/Groot/Documents').
true.

?- ['Cytoscape.js elements - DCG generator'].
true.

?- write_elements_var('elements.js').
true.

Cytoscape.js is JavaScript run in HTML.

File: index.html

<!DOCTYPE html>
<html>
    <head>
        <title>Cytoscape.js - Basic example for Prolog facts. Uses layout extension <span style="font-weight:bold">cola</span></title>
        <link rel="stylesheet" href="style.css">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.15.2/cytoscape.min.js" integrity="sha512-PqivlaNWoXvHYlvku80fbWO/yBiRmGhISj5uVdAodyqsGprDcVZy6aecJDVNE0fIIE/YeiOzp5yJTR5ZjFlR4Q==" crossorigin="anonymous"></script>
        <script src="https://unpkg.com/webcola@3.3.8/WebCola/cola.min.js"></script>
        <script src="https://unpkg.com/cytoscape-cola@2.2.3/cytoscape-cola.js"></script>
        <script src="script.js"></script>
        <script src='elements.js'></script>
        <script src='style.js'></script>
        <script src='layout.js'></script>
        </head>
    <body>
        <div id="cy"></div>
    </body>
</html>

File: style.css

#cy {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0px;
    left: 0px;
}

File: script.js

document.addEventListener("DOMContentLoaded", function () {
    var cy = cytoscape(
        {
            container: document.getElementById('cy'),
            elements: Elements,
            style: Style,
            layout: Layout
        }
    );
});

File: style.js

// Style is JSON
// Think CSS converted to JSON
var Style = [
    {
        "selector": "node",
        "style": {
            "label": "data(id)"
        }
    },
    {
        "selector": "edge",
        "style": {
            'curve-style': 'haystack',
        }
    }
];

File: layout.js

// Layout is JSON
var Layout = {
    name: 'cola'
}

To see the graph just open index.html with an Internet browser.
In Windows 10 I just double click on index.html within File Explorer.

I know it is not pretty but it was not meant to be pretty at this point, it is a proof of concept.

1 Like

Another example.

This one passes the data as JSON and not as JSON wrapped with a JavaScript variable. This is important because JSON is much easier to validate as input when being accepted for use on a web site. With SWI-Prolog the validation of the JSON can be done with DCGs and quasi-quotations. (ref)

Uses
a. JavaScript promises.
b. JavaScript fetch

This has two buttons that will display data in the Internet browser console. F12 for Chrome, FireFox or Edge.

  1. Show the same JSON data used by cytoscpae()
  2. Demonstrates how to select values from the Cytoscape.js objects using JavaScript array map

This is just code for demonstration purposes; it has not been enhanced for production use.

Since this code uses JavaScript fetch, a server is required to pass the files to the Internet browser. If you are on Windows and install node.js you can start the server by clicking on http_server.lnk, then access the page as noted by the node.js startup messages.

Details

You will need to create http_server.lnk with the properties

Target: C:\Windows\System32\cmd.exe /k "http_server.bat"
Start in: Clear field so it is empty

http_server.bat

SET PATH=%ProgramFiles(x86)%\nodejs;%AppData%\npm
http-server --cors

index.html

<!DOCTYPE html>
<html>
    <head>
        <title>Cytoscape.js - Example - pass data as JSON</title>
        <link rel="stylesheet" href="style.css">
        <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.15.2/cytoscape.min.js" integrity="sha512-PqivlaNWoXvHYlvku80fbWO/yBiRmGhISj5uVdAodyqsGprDcVZy6aecJDVNE0fIIE/YeiOzp5yJTR5ZjFlR4Q==" crossorigin="anonymous"></script>
        <script src="script.js" defer="defer"></script>
    </head>

    <body>
        <div id="cy"></div>
        <input type='button' id='showJson' value='Show JSON'>
        <input type='button' id='showPositions' value='Show Positions'>
    </body>

</html>

style.css

#cy {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0px;
    left: 0px;
}
#showJson {
    font-size: 40px;
    font-weight: bold;
    width: 10%;
    height: 5%;
    position: absolute;
    top: 5%;
    right: 80%;
}
#showPositions {
    font-size: 40px;
    font-weight: bold;
    width: 10%;
    height: 5%;
    position: absolute;
    top: 15%;
    right: 80%;
}

script.js

Promise.all([
    fetch('/elements.json'),
    fetch('/style.json'),
    fetch('/layout.json')
]).then(function (responses) {
    return Promise.all(responses.map(function (response) {
        return response.json();
    }));
}).then(data => {
    cy = cytoscape(
        {
            container: document.getElementById('cy'),
            elements: data[0],
            style: data[1],
            layout: data[2]
        }
    );
    return cy
}).then(cy => {
    let showJsonButton = document.getElementById('showJson');
    showJsonButton.addEventListener('click', function () {
        console.log('Elements:');
        console.log( cy.elements().jsons() );   // Gets all elements - JSON
        console.log('Styles:');
        console.log( cy.style().json() );       // Gets all styles - JSON
        console.log('Layout:');
        console.log(cy.options().layout);       // Gets layout
    });

    let showPositionsButton = document.getElementById('showPositions');
    showPositionsButton.addEventListener('click', function () {
        let positions = cy.nodes().map(node => node.position());
        console.log('Positions:');
        console.log(positions);
    });
}).catch(function (error) {
    console.log(error);
});

elements.json

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

style.json

[
    {
        "selector": "node",
        "style": {
            "label": "data(id)"
        }
    },
    {
        "selector": "edge",
        "style": {
            "curve-style": "haystack"
        }
    }
]

layout.json

{
    "name": "grid"
}
1 Like

A most simple single page JSON data exchange example, to be further expanded for interactivity.

/*  File:    cyajax.pl
    Author:  Carlo
    Created: Sep 13 2020
    Purpose: feeding CytoscapeJS with AJAX/JSON
*/

:- module(cyajax, []).

:- use_module(library(http/http_server)).
:- use_module(library(http/http_json)).
:- use_module(library(http/http_log)).
:- use_module(library(ugraphs)).

% when `make` just reload http://localhost:8081 to get changes
:- initialization (
       Port=8081,
       catch(http_stop_server(Port,[]),_,true),
       http_server([port(Port)])
   ).

:- http_handler(root(.),
                http_redirect(moved,location_by_id(home_page)),
                []).
:- http_handler(root(home),home_page,[]).

:- http_handler(root(run_cyajax),run_cyajax,[]).

home_page(_Request) :-
    reply_html_page(
        [ title('cyajax test'),
          \cy_cdn
        ],
        [ div([
            input([id=run_cyajax,type=button,value='run cyajax']),
            div([id=host_cy],'host cy')
          ]),
          \css,
          \js
        ]).

example_graph(1,
  [1-[2,3],2-[3,4,5],3-[1,2],4-[1,3],5-[4,5]]).

ugraph_to_cy_elements(G,Elements) :-
    vertices(G,Vs),
    maplist([V,_{data:_{id:V}}]>>true,Vs,Nodes),
    edges(G,Es),
    maplist([Source-Target,
             _{data:_{id:EdgeId,source:Source,target:Target}}
            ]>>format(string(EdgeId),"~w->~w",[Source,Target])
            ,Es,Edges),
    append(Nodes,Edges,Elements).

run_cyajax(Request) :-
  http_read_json_dict(Request,Dict),
  example_graph(Dict.example,G),
  ugraph_to_cy_elements(G,Es),
  reply_json_dict(_{elements:Es,layout:cose}).

cy_cdn -->
    html(script([src=
      'https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.15.2/cytoscape.min.js'
    ],'')).

css --> html(style('

#host_cy {
  height: 400px;
  width: 400px;
  background-color: lime;
}

')).

js --> html(script("

window.onload = () => {

  const request = (url,json) => fetch(url,{
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(json)
  }).then(r => r.json())

  run_cyajax.onclick = async (ev) => {
    try {
      render_cy(await request('/run_cyajax', {example:1}))
    } catch(e) {
      alert(e.message)
    }
  }

  render_cy = (from_pl) => {
    var cy = {
        container: host_cy,
        style: [
            {   selector: 'node',
                style: {
                    'background-color': '#666',
                    'label': 'data(id)'
                }
            },
            {   selector: 'edge',
                style: {
                    'target-arrow-shape': 'triangle',
                    'width': 3,
                    'line-color': '#ddd',
                    'target-arrow-color': '#ddd',
                    'curve-style': 'bezier'
                }
            }
        ],
    }
    if (from_pl.elements)
      cy.elements = from_pl.elements
    cytoscape(cy).makeLayout({ name: from_pl.layout }).run()
  }
}

")).
2 Likes

Nice!

Result of running cyajax.pl by Carlo in this post