Initializing cytoscape - cytoscape-web

being new to cytoscapeweb 2, i am following one of the provided example in order to learn how to use the API.
i cant make it work and firebug reports the following message:
Component returned failure code: 0x80004005 (NS_ERROR_FAILURE)
var n = this.nodesGroup.getBBox();
in my html document, the cytoscapeweb div is embedded in a jquery tab widget (just to provide context)
somewhere in my.html
<div id="tabs">
<ul>
<li>Interactors Selection</li>
<li>Interactome Builder</li>
</ul>
<div id="tabs-1">
<p>Tab 1 content</p>
</div>
<div id="tabs-2">
<p>Tab 2 content</p>
<div id="cy"></div>
</div>
</div>
and in foo.js
function cytoscapeInit() {
alert ("intializing cytoscape");
// create a mapper for node size
var nodeSizeMapper = {
continuousMapper: {
attr: {
name: "weight",
min: 0,
max: 100
},
mapped: {
min: 15,
max: 30
}
}
};
// call cytoscape web on the `cy` div
$("#cy").cytoscapeweb({
// define the elements in the graph
elements: {
nodes: [
{ data: { id: "a", weight: 43 }, classes: "foo" },
{ data: { id: "b", weight: 2 }, classes: "bar" },
{ data: { id: "c", weight: 88 }, classes: "foo bar" }
],
edges: [
{ data: { id: "ab", source: "a", target: "b", weight: 32 }, classes: "foo" },
{ data: { id: "bc", source: "b", target: "c", weight: 12 }, classes: "bar baz" },
{ data: { id: "ca", source: "c", target: "a", weight: 96 }, classes: "baz foo" },
{ data: { id: "ac", source: "a", target: "c", weight: 65 }, classes: "bar" }
]
},
// define the layout to use
layout: {
name: "preset",
positions: {
"a": { x: 30, y: 30 },
"b": { x: 125, y: 131 },
"c": { x: 200, y: 50 }
},
fit: false,
stop: function(){
cy.reset();
cy.center();
}
},
// define the visual style (like css) of the graph
style: {
selectors: {
"node":{
shape: "ellipse",
fillColor: "#888",
height: nodeSizeMapper,
width: nodeSizeMapper,
labelText: {
passthroughMapper: "id"
}
},
".yay": {
fillColor: "red",
lineColor: "red",
targetArrowColor: "red"
},
"edge": {
lineColor: "#ccc",
targetArrowColor: "#ccc",
width: {
continuousMapper: {
attr: {
name: "weight"
},
mapped: {
min: 2,
max: 5
}
}
},
targetArrowShape: "triangle"
},
"node:selected": {
fillColor: "#333"
},
"edge:selected":{
lineColor: "#666",
targetArrowColor: "#666"
}
}
},
// define the callback for when cytoscape web is ready
ready: function( cy ){
window.cy = cy;
}
});
Did i miss something obvious?
If so, all apologies.

(1) Don't put alerts in your code like that even when you're testing. It can break asynchronous code, like initialising Cytoscape Web or doing an AJAX call. Use console.log() instead.
(2) You're probably hiding the Cytoscape Web div, cy, with the tabs. You shouldn't be using display: none;, because the Cytoscape Web viewport will then be 0x0 px. Try something like position: absolute; left: -9999px; or similiar for hiding. This entails modifying whatever class name jQuery uses for hidden tabs (probably .ui-state-hidden or something similar).
(3) I'll look into making the renderer code more tolerant of hidden Cytoscape Web divs.

I have a better solution to this problem:
Execute jquery tab just after all of the graphs are loaded.
http://cytoscape.github.io/cytoscape.js/#core/events/cy.ready
for(var t = 0, tot=pageList.length; t<tot; t++) //draw graph for all pages
{
var currPage = pageList[t];
getData(currPage);
}
function getData(currPage)
{
//initiate graph, do stuff...
//graph ready
window[currPage + "Container"].ready(function(e)
{
if (currPage.indexOf(lastPage) != -1)//executetabsafterlastgraphisdrawn
{
setTabs();
}
});
}

Related

How do I get edges along with the nodes I filtered in Cytoscape.js?

I would like to know how I can get the edges along with all the nodes which I filtered based on a specific query?
I have seen this example on Cytoscape.js page:
https://js.cytoscape.org/#selectors
// get node j and the edges coming out from it
cy.elements('node#j, edge[source = "j"]');
Now I would like to do the same with a specific query attribute which all nodes have in common along with all edges.
I tried a query along the above idea like this:
const query = 'node[ nodeType = "Car"]';
graphElements = cy.elements(query);
This gives me all nodes with nodeType="Car" but with no edges.
How can I get ALL edges along with the selected nodes query?
In order to filter nodes with connected edges, you can use the .remove() function together with the .not() function, resulting in every node not in the provided collection to be deleted, along with every edge from and to a node not in the collection:
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: ":selected",
css: {
"background-color": "black",
"line-color": "black",
"target-arrow-color": "black",
"source-arrow-color": "black"
}
}
],
elements: {
nodes: [{
data: {
id: "n0"
}
},
{
data: {
id: "n1"
}
},
{
data: {
id: "n2"
}
},
{
data: {
id: "n3",
type: "car"
}
},
{
data: {
id: "n4"
}
},
{
data: {
id: "n5"
}
},
{
data: {
id: "n6"
}
},
{
data: {
id: "n7"
}
},
{
data: {
id: "n8"
}
},
{
data: {
id: "n9"
}
},
{
data: {
id: "n10"
}
},
{
data: {
id: "n11"
}
},
{
data: {
id: "n12",
type: "car"
}
},
{
data: {
id: "n13"
}
},
{
data: {
id: "n14"
}
},
{
data: {
id: "n15"
}
},
{
data: {
id: "n16"
}
}
],
edges: [{
data: {
source: "n0",
target: "n1"
}
},
{
data: {
source: "n1",
target: "n2"
}
},
{
data: {
source: "n1",
target: "n3"
}
},
{
data: {
source: "n2",
target: "n7"
}
},
{
data: {
source: "n2",
target: "n11"
}
},
{
data: {
source: "n2",
target: "n16"
}
},
{
data: {
source: "n3",
target: "n4"
}
},
{
data: {
source: "n3",
target: "n16"
}
},
{
data: {
source: "n4",
target: "n5"
}
},
{
data: {
source: "n4",
target: "n6"
}
},
{
data: {
source: "n6",
target: "n8"
}
},
{
data: {
source: "n8",
target: "n9"
}
},
{
data: {
source: "n8",
target: "n10"
}
},
{
data: {
source: "n11",
target: "n12"
}
},
{
data: {
source: "n12",
target: "n13"
}
},
{
data: {
source: "n13",
target: "n14"
}
},
{
data: {
source: "n13",
target: "n15"
}
}
]
},
layout: {
name: "dagre",
padding: 5
}
}));
cy.off("click");
cy.on("click", function(event) {
let filteredNodes = cy.nodes('node[ type = "car"]');
cy.nodes().not(filteredNodes.union(filteredNodes.successors())).remove();
});
body {
font: 14px helvetica neue, helvetica, arial, sans-serif;
}
#cy {
height: 100%;
width: 75%;
position: absolute;
left: 0;
top: 0;
float: left;
}
<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>
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<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>
Ok, I might have found an answer to this, apparently nodes and edges are handled separately. In order to include edges, there are several options which can be found on the Cytoscape.js page under traversing such as nodes.edgesWith(), nodes.edgesTo(), nodes.connectedEdges(), etc. etc.
So in order to for example filter by Nodes and corresponding Edges with Edge Successors as I need it in my case, it can be done the following:
// Filter all nodes by nodeType Car
const query = 'node[ nodeType = "Car"]';
let filteredNodes = cy.nodes(query);
// I only want to successors of all Nodes, so I add only those and combine
nodes and edges with union
const graphElements = filteredNodes.union(filteredNodes.successors());
// Apply changes on graph
cy.elements().remove();
cy.add( graphElements );
This is what I came up with, if anyone has something to optimize please let me know. I am still figuring out Cytoscape.js myself.

Generate an array of charts

I want to generate an array of charts and insert them into the DOM.
(I want to use these charts as templates and insert them at the right time)
like that:
Var array = [];
array[0].kendoChart ({// .........});
array[1].kendoChart ({// .........});
array.forEach (function (el) {
$('body').append(el);
})
Tell me how to be?
I would keep an array of the data used to generate the charts, and then generate them at the time of insert.
In HTML provide a container for the charts to be inserted (could be body as in your example):
<div id="chartsContainer" ></div>
Then in script have an array of the data needed to generate the multiple charts, e.g. :
var charts = [
{
chartid: "id1", title: "Chart 1",
data: [{ x: "item1", y: 2}, { x: "item2", y: 4},{ x: "item3", y: 1}]
},
{
chartid: "id2", title: "Chart 2",
data: [{ x: "item1", y: 8}, { x: "item2", y: 3},{ x: "item3", y: 7},{ x: "item4", y: 2}]
},
{
chartid: "id3", title: "Chart 3",
data: [{ x: "item1", y: 1}, { x: "item2", y: 2},{ x: "item3", y: 4} ]
},
];
Finally loop through the array, insert DIVs in the container and create a chart in each DIV:
$("#chartsContainer").empty();
var arrayLength = charts.length;
for (var i = 0; i < arrayLength; i++) {
var div = $('<div id="' + charts[i].chartid + '"></div>');
$("#chartsContainer").append(div);
div.kendoChart({
theme: "Flat",
chartArea: { height: 200 },
dataSource: {data: charts[i].data },
title: { text: charts[i].title},
seriesDefaults: {type: "column"},
series: [{field: "y" }],
categoryAxis: {
field: "x",
majorGridLines: {visible: false },
}
});
}
Working DEMO

Highcharts-ng with multiple series draw chart incorrectly

I have two fiddles: no angular, and using angular. The one with the angular doesn't work correctly. It doesn't show dates in xAxis, and doesn't use percent for yAxis.
Is there something specific need to be done, to have that work with angular?
No angular html
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<div id="container" style="height: 400px; min-width: 310px"></div>
Angular html
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<div ng-app="myApp">
<div ng-controller="myctrl">
<highchart id="chart1" config="ipo" class="span9"></highchart>
</div>
</div>
Not angular javascript
$(function () {
function createChart() {
$('#container').highcharts('StockChart', {
rangeSelector: {
selected: 4
},
yAxis: {
labels: {
formatter: function () {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: [{
name: 'IPO',
data: [[1381881600000, 20.34], [1381968000000, 20.43], [1382054400000, 20.72]]
}, {
name: 'SPX',
data: [[1381881600000, 1721.54], [1381968000000, 1733.15], [1382054400000, 1744.5]]
}]
});
}
createChart();
});
Angular javascript
var myApp = angular.module('myApp', ['highcharts-ng']);
myApp.controller('myctrl', BindingCode);
myApp.factory("Factory", Factory);
function ipo() {
this.chartConfig = {
rangeSelector: {
selected: 4
},
yAxis: {
labels: {
formatter: function () {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}]
},
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
series: [{
name: 'IPO',
data: [[1381881600000, 20.34], [1381968000000, 20.43], [1382054400000, 20.72]]
}, {
name: 'SPX',
data: [[1381881600000, 1721.54], [1381968000000, 1733.15], [1382054400000, 1744.5]]
}]
}
}
function BindingCode($scope,Factory) {
$scope.ipo = Factory.CreateChart();
$scope.ipo = $scope.ipo.chartConfig;
}
function Factory() {
return {
CreateChart: function () {
return new ipo();
}
}
}
Not angular screenshot
Angular screenshot
The problem is that not all the highchart options go into the top-level JSON configuration.
From the FAQ:
Why doesn't my plot options/tooltip/drilldown/other feature work?
At least half of all issues filed are due to this. Before you file an
issue read this! A common error is to put other Highcharts options
directly into the chartConfig. In general if the Highcharts option you
want isn't listed above you probably want to put it in
chartConfig.options.
In your case, you need to move pretty everything except 'series' into an options object.
chartConfig = {
options : {
rangeSelector: {
selected: 4
},
type: "line",
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}],
plotOptions: {
series: {
compare: 'percent'
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b> ({point.change}%)<br/>',
valueDecimals: 2
},
yAxis: {
labels: {
formatter: function () {
return (this.value > 0 ? ' + ' : '') + this.value + '%';
}
},
}
},
series: [{
name: 'IPO',
data: [[1381881600000, 20.34], [1381968000000, 20.43], [1382054400000, 20.72]]
}, {
name: 'SPX',
data: [[1381881600000, 1721.54], [1381968000000, 1733.15], [1382054400000, 1744.5]]
}]
}
Updated fiddle
https://jsfiddle.net/mgwkzob3/1/

kendo Chart labels- clickable?

In the example: http://jsbin.com/AreqameT/1/edit Can the labels below the bar chart made clickable in kendo charts?
The text "Sales and Contracting" and other labels should be made clickable. Can this be done?
JS code:
$("#chart").kendoChart({
legend: {
position: "bottom"
},
seriesDefaults: {
labels:{
visible:true,
template: '#=kendo.format("{0:0}", value)#'
}
},
series: [
{
type: "verticalBullet",
currentField: "score",
targetField: "average",
labels: {
visible: true,
template: '#alert(1)#"'
},
target: {
color: "transparent",
border: {
width: 2,
dashType: "dot",
color: "#444"
},
line: {
width: 0
}
},
data: [
{
score: 93.7,
average: 65.2
}, {
score: 80.2,
average: 22.2
}, {
score: 60.8,
average: 35.2
}, {
score: 82.1,
average: 45.2
}, {
score: 74.2,
average: 55.2
}
]
}
],
categoryAxis: {
labels: { rotation: -45 },
categories: ["Sales & Contracting", "Implementation & Training", "Functionality & Upgrades", "Service & Support", "General"],
line: {
visible: false
},
color: "#444",
axisCrossingValue: [0, 0, 100, 100]
},
tooltip: {
visible: false
}
}).data("kendoChart");
HTML code:
<body>
<div id="chart"></div>
</body>
Thanks in advance.
Using a newer version of Kendo (your jsBin uses a 2013 version... update to 2014.2) you can use categoryAxis.labels.template to add a link to your labels.
categoryAxis: {
labels: {
rotation: -45,
template: '<a xlink:href="http://www.google.com">#: value #</a>'
},
(note the addition of xlink: in the tag)
To better explain, the labels are actually part of an SVG image, not plain HTML. However, SVG supports links: http://www.w3.org/TR/SVG/linking.html#Links
For some reason the older 2013 version of Kendo seem to remove the link from the template though. I tried it with 2014.2.716 and it seemed to work.
Your Jsbin eg not working. Attach a event axisLabelClick or legendItemClick
axisLabelClick: function(e) {
console.log(e.axis.type, e.value);
}
legendItemClick: function(e) {
console.log(e.axis.type, e.value);
}
this might work

cant add notes to categoryAxis with kendo charts

Is there a possibility to add notes on the categoryAxis in a Kendo Chart.
As seen in the documentation it should be possible, but even after setting every single option i dont see any notes. I couldn't find any example of somebody doing that. Has anybody managed or used this feature?
my try on jsFiddle
categoryAxis: {
field: "age",
justified: true,
majorGridLines: {
visible: false
},
minorGridLines: {
visible: false
},
min: 10,
max: 30,
labels: {
step: 5
},
notes: {
data: [{
value: { age: 15 },
position: "top",
icon: {
visible: true,
size: 16,
type: "circle",
background: "#585858",
border: {
color: "#FFFFFF"
}
},
line: {
length: 16
},
label: {
visible: false,
text: " "
}
}]
}
}
Thank you
The value property for notes on the categoryAxis appears to represent each category value.
Here's an example notes configuration:
notes: {
label: {
template: "Value: #: value #"
},
icon: {
visible: true,
size: 16,
type: "circle",
background: "#585858",
border: {
color: "#FFFFFF"
}
},
line: {
length: 16
},
data: [{ value: 1}, { value: 5 },{ value: 10 }, { value: 15 }, { value: 20 }]
}
Check out this updated fiddle.

Resources