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()
}
}
")).