I want to create an ER (entity relationship diagram) with JavaScript and GoJS. I also want when mouse hoovers above a node to show a text with some Info about each node. I tried to use this example and here is my code:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ER diagram</title>
<meta name="description" content="Interactive entity-relationship diagram or data model diagram implemented by GoJS in JavaScript for HTML." />
<!-- Copyright 1998-2018 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/1.8.10/go-debug.js"></script>
<script id="code">
function init() {
var $ = go.GraphObject.make; // for conciseness in defining templates
myDiagram =
$(go.Diagram, "myDiagramDiv", // must name or refer to the DIV HTML element
{
initialContentAlignment: go.Spot.Left,
allowDelete: false,
allowCopy: false,
layout: $(go.ForceDirectedLayout),
"undoManager.isEnabled": true
});
function diagramInfo(model) {
return "A returned text for dispaly";
}
// provide a tooltip for the background of the Diagram, when not over any Part
myDiagram.toolTip =
$(go.Adornment, "Auto",
$(go.Shape, { fill: "#CCFFCC" }),
$(go.TextBlock, { margin: 4 },
// use a converter to display information about the diagram model
new go.Binding("text", "", diagramInfo))
);
var nodeHoverAdornment =
$(go.Adornment, "Spot",
{
background: "transparent",
// hide the Adornment when the mouse leaves it
mouseLeave: function(e, obj) {
var ad = obj.part;
ad.adornedPart.removeAdornment("mouseHover");
}
},
$(go.Placeholder,
{
background: "transparent", // to allow this Placeholder to be "seen" by mouse events
isActionable: true, // needed because this is in a temporary Layer
click: function(e, obj) {
var node = obj.part.adornedPart;
node.diagram.select(node);
}
})
);
// define several shared Brushes
var yellowgrad = $(go.Brush, "Linear", { 0: "rgb(254, 221, 50)", 1: "rgb(254, 182, 50)" });
var lightgrad = $(go.Brush, "Linear", { 1: "#E6E6FA", 0: "#FFFAF0" });
// the template for each attribute in a node's array of item data
var itemTempl =
$(go.Panel, "Horizontal",
$(go.Shape,
{ desiredSize: new go.Size(10, 10) },
new go.Binding("figure", "figure"),
new go.Binding("fill", "color")),
$(go.TextBlock,
{ stroke: "#333333",
font: "bold 14px sans-serif" },
new go.Binding("text", "name"))
);
// define the Node template, representing an entity
myDiagram.nodeTemplate =
$(go.Node, "Auto", // the whole node panel
{ selectionAdorned: true,
resizable: true,
layoutConditions: go.Part.LayoutStandard & ~go.Part.LayoutNodeSized,
fromSpot: go.Spot.AllSides,
toSpot: go.Spot.AllSides,
isShadowed: true,
shadowColor: "#C5C1AA" },
new go.Binding("location", "location").makeTwoWay(),
// whenever the PanelExpanderButton changes the visible property of the "LIST" panel,
// clear out any desiredSize set by the ResizingTool.
new go.Binding("desiredSize", "visible", function(v) { return new go.Size(NaN, NaN); }).ofObject("LIST"),
// define the node's outer shape, which will surround the Table
$(go.Shape, "Rectangle",
{ fill: lightgrad, stroke: "#756875", strokeWidth: 3 }),
$(go.Panel, "Table",
{ margin: 8, stretch: go.GraphObject.Fill },
$(go.RowColumnDefinition, { row: 0, sizing: go.RowColumnDefinition.None }),
// the table header
$(go.TextBlock,
{
row: 0, alignment: go.Spot.Center,
margin: new go.Margin(0, 14, 0, 2), // leave room for Button
font: "bold 16px sans-serif"
},
new go.Binding("text", "key")),
// the collapse/expand button
$("PanelExpanderButton", "LIST", // the name of the element whose visibility this button toggles
{ row: 0, alignment: go.Spot.TopRight }),
// the list of Panels, each showing an attribute
$(go.Panel, "Vertical",
{
name: "LIST",
row: 1,
padding: 3,
alignment: go.Spot.TopLeft,
defaultAlignment: go.Spot.Left,
stretch: go.GraphObject.Horizontal,
itemTemplate: itemTempl
},
new go.Binding("itemArray", "items"))
,{
toolTip: // define a tooltip for each node that displays the color as text
$(go.Adornment, "Auto",
$(go.Shape, { fill: "#FFFFCC" }),
$(go.TextBlock, { margin: 50 },
new go.Binding("text", "color"))
) // end of Adornment
}
) // end Table Panel
);
// define the Link template, representing a relationship
myDiagram.linkTemplate =
$(go.Link, // the whole link panel
{
selectionAdorned: true,
layerName: "Foreground",
reshapable: true,
routing: go.Link.AvoidsNodes,
corner: 5,
curve: go.Link.JumpOver
},
$(go.Shape, // the link shape
{ stroke: "#303B45", strokeWidth: 2.5 }),
$(go.TextBlock, // the "from" label
{
textAlign: "center",
font: "bold 14px sans-serif",
stroke: "#1967B3",
segmentIndex: 0,
segmentOffset: new go.Point(NaN, NaN),
segmentOrientation: go.Link.OrientUpright
},
new go.Binding("text", "text")),
$(go.TextBlock, // the "to" label
{
textAlign: "center",
font: "bold 14px sans-serif",
stroke: "#1967B3",
segmentIndex: -1,
segmentOffset: new go.Point(NaN, NaN),
segmentOrientation: go.Link.OrientUpright
},
new go.Binding("text", "toText"))
);
// create the model for the E-R diagram
var nodeDataArray = [
{ key: "tabA",
items: [ { name: "TabA Key", iskey: true, figure: "Decision", color: 'pink' } ] },
{ key: "tabB",
items: [ { name: "TabB Key", iskey: true, figure: "Decision", color: 'pink' },
{ name: "TabB attribute", iskey: true, figure: "Decision", color: 'lightblue' } ] },
{ key: "tabC",
items: [ { name: "TabC Key", iskey: true, figure: "Decision", color: 'pink' }] }
];
//Options [BpmnEventTimer,BpmnEventConditional,MagneticData,Cube1,Decision,TriangleUp]
var linkDataArray = [
{ from: "tabA", to: "tabB", text: "1", toText: "1" },
{ from: "tabB", to: "tabC", text: "1", toText: "2" }
];
myDiagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
}
</script>
</head>
<body onload="init()">
<div id="sample">
<div id="myDiagramDiv" style="background-color: white; border: solid 1px black; width: 50%; height: 600px;"></div>
</div>
</body>
</html>
As you can see It generates a text box on mouse hoover over a node but it does not display any text. Can anyone help on how to generate text and specifically different text for each node? I want to display a different (predetermined) description for each node in that text.
Thanks in advance for any answer.
Yes, you should be using tooltips as the standard mechanism for showing something upon a mouse hover: https://gojs.net/latest/intro/tooltips.html.
In your node template it appears that you have assigned a tooltip to a panel inside your node. That means it is data bound to the same data that the node is bound to.
However, your binding of new go.Binding("text", "color") would imply that there be a "color" property on your node data. When I look at the node data in the model, there does not seem to be any "color" property on the node. So the binding is not evaluated. Since you hadn't assigned an initial value to the TextBlock.text property, there's no string to be rendered.
There is such a property on the individual item data, but you didn't assign the tooltip in the itemTemplate.
After the suggestion of Walter Northwoods I added the tooltip in item template and here is the code where each node item has each own descriptive toolip
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ER diagram</title>
<meta name="description" content="Interactive entity-relationship diagram or data model diagram implemented by GoJS in JavaScript for HTML." />
<!-- Copyright 1998-2018 by Northwoods Software Corporation. -->
<meta charset="UTF-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/gojs/1.8.10/go-debug.js"></script>
<script id="code">
function init() {
var $ = go.GraphObject.make; // for conciseness in defining templates
myDiagram =
$(go.Diagram, "myDiagramDiv", // must name or refer to the DIV HTML element
{
initialContentAlignment: go.Spot.Left,
allowDelete: false,
allowCopy: false,
layout: $(go.ForceDirectedLayout),
"undoManager.isEnabled": true
});
function diagramInfo(model) {
return "A returned text for dispaly";
}
// provide a tooltip for the background of the Diagram, when not over any Part
myDiagram.toolTip =
$(go.Adornment, "Auto",
$(go.Shape, { fill: "#CCFFCC" }),
$(go.TextBlock, { margin: 4 },
// use a converter to display information about the diagram model
new go.Binding("text", "", diagramInfo))
);
var nodeHoverAdornment =
$(go.Adornment, "Spot",
{
background: "transparent",
// hide the Adornment when the mouse leaves it
mouseLeave: function(e, obj) {
var ad = obj.part;
ad.adornedPart.removeAdornment("mouseHover");
}
},
$(go.Placeholder,
{
background: "transparent", // to allow this Placeholder to be "seen" by mouse events
isActionable: true, // needed because this is in a temporary Layer
click: function(e, obj) {
var node = obj.part.adornedPart;
node.diagram.select(node);
}
})
);
// define several shared Brushes
var yellowgrad = $(go.Brush, "Linear", { 0: "rgb(254, 221, 50)", 1: "rgb(254, 182, 50)" });
var lightgrad = $(go.Brush, "Linear", { 1: "#E6E6FA", 0: "#FFFAF0" });
// the template for each attribute in a node's array of item data
var itemTempl =
$(go.Panel, "Horizontal",
$(go.Shape,
{ desiredSize: new go.Size(10, 10) },
new go.Binding("figure", "figure"),
new go.Binding("fill", "color")),
$(go.TextBlock,
{ stroke: "#333333",
font: "bold 14px sans-serif" },
new go.Binding("text", "name")),
{
toolTip: // define a tooltip for each node that displays the color as text
$(go.Adornment, "Auto",
$(go.Shape, { fill: "#FFFFCC" }),
$(go.TextBlock, { margin: 10 },
new go.Binding("text", "desc"))
) // end of Adornment
}
);
// define the Node template, representing an entity
myDiagram.nodeTemplate =
$(go.Node, "Auto", // the whole node panel
{ selectionAdorned: true,
resizable: true,
layoutConditions: go.Part.LayoutStandard & ~go.Part.LayoutNodeSized,
fromSpot: go.Spot.AllSides,
toSpot: go.Spot.AllSides,
isShadowed: true,
shadowColor: "#C5C1AA" },
new go.Binding("location", "location").makeTwoWay(),
// whenever the PanelExpanderButton changes the visible property of the "LIST" panel,
// clear out any desiredSize set by the ResizingTool.
new go.Binding("desiredSize", "visible", function(v) { return new go.Size(NaN, NaN); }).ofObject("LIST"),
// define the node's outer shape, which will surround the Table
$(go.Shape, "Rectangle",
{ fill: lightgrad, stroke: "#756875", strokeWidth: 3 }),
$(go.Panel, "Table",
{ margin: 8, stretch: go.GraphObject.Fill },
$(go.RowColumnDefinition, { row: 0, sizing: go.RowColumnDefinition.None }),
// the table header
$(go.TextBlock,
{
row: 0, alignment: go.Spot.Center,
margin: new go.Margin(0, 14, 0, 2), // leave room for Button
font: "bold 16px sans-serif"
},
new go.Binding("text", "key")),
// the collapse/expand button
$("PanelExpanderButton", "LIST", // the name of the element whose visibility this button toggles
{ row: 0, alignment: go.Spot.TopRight }),
// the list of Panels, each showing an attribute
$(go.Panel, "Vertical",
{
name: "LIST",
row: 1,
padding: 3,
alignment: go.Spot.TopLeft,
defaultAlignment: go.Spot.Left,
stretch: go.GraphObject.Horizontal,
itemTemplate: itemTempl
},
new go.Binding("itemArray", "items"))
) // end Table Panel
);
// define the Link template, representing a relationship
myDiagram.linkTemplate =
$(go.Link, // the whole link panel
{
selectionAdorned: true,
layerName: "Foreground",
reshapable: true,
routing: go.Link.AvoidsNodes,
corner: 5,
curve: go.Link.JumpOver
},
$(go.Shape, // the link shape
{ stroke: "#303B45", strokeWidth: 2.5 }),
$(go.TextBlock, // the "from" label
{
textAlign: "center",
font: "bold 14px sans-serif",
stroke: "#1967B3",
segmentIndex: 0,
segmentOffset: new go.Point(NaN, NaN),
segmentOrientation: go.Link.OrientUpright
},
new go.Binding("text", "text")),
$(go.TextBlock, // the "to" label
{
textAlign: "center",
font: "bold 14px sans-serif",
stroke: "#1967B3",
segmentIndex: -1,
segmentOffset: new go.Point(NaN, NaN),
segmentOrientation: go.Link.OrientUpright
},
new go.Binding("text", "toText"))
);
// create the model for the E-R diagram
var nodeDataArray = [
{ key: "tabA",
items: [ { name: "TabA Key", iskey: true, figure: "Decision", color: 'pink' , desc: "Tab A Key is tab A key" } ],
nodedesc: "Tab A desc" },
{ key: "tabB",
items: [ { name: "TabB Key", iskey: true, figure: "Decision", color: 'pink', desc: "Tab B Key is tab B key" },
{ name: "TabB attribute", iskey: true, figure: "Decision", color: 'lightblue', desc: "Tab B Attribute is tab B attr" } ],
nodedesc: "Tab B desc" },
{ key: "tabC",
items: [ { name: "TabC Key", iskey: true, figure: "Decision", color: 'pink' , desc: "Tab C Key is tab C key" } ],
nodedesc : "Tab C desc" }
];
//Options [BpmnEventTimer,BpmnEventConditional,MagneticData,Cube1,Decision,TriangleUp]
var linkDataArray = [
{ from: "tabA", to: "tabB", text: "1", toText: "1" },
{ from: "tabB", to: "tabC", text: "1", toText: "2" }
];
myDiagram.model = new go.GraphLinksModel(nodeDataArray, linkDataArray);
}
</script>
</head>
<body onload="init()">
<div id="sample">
<div id="myDiagramDiv" style="background-color: white; border: solid 1px black; width: 50%; height: 600px;"></div>
</div>
</body>
</html>
to simplify the answer - you need to add tooltip property to your nodeTemplate and bind data ( in this example im binding to nodeDataArray.key ), analogically to this:
yourDiagram.nodeTemplate = go.GraphObject.make(go.Node, 'Spot',
{
toolTip:
go.GraphObject.make(go.Adornment, "Spot",
{
background: "transparent"
},
go.GraphObject.make(go.Placeholder, {
padding: 5
}),
go.GraphObject.make(go.TextBlock,
{
alignment: go.Spot.Top,
alignmentFocus: go.Spot.Bottom,
stroke: "#0f1b54",
editable: true
},
new go.Binding("text", "key", function (tooltip_key) {
return tooltip_key
})),
)
},
Related
This is the node template I'm working with:
$(go.Node, "Auto",
{
deletable: false,
selectionAdorned: false
},
new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),
$(go.Shape, "Terminator",
{
fill: "#f8da07", strokeWidth: 2, minSize: new go.Size(90, 40), portId: "", cursor: "pointer", stroke: '#000000', fromLinkable: true,
toLinkable: false, fromLinkableSelfNode: false, toLinkableSelfNode: false, fromLinkableDuplicates: false, toLinkableDuplicates: false, fromMaxLinks: 1
},
new go.Binding("figure"),
new go.Binding("fill", "color"),
new go.Binding("fill", "isSelected", function(sel) {
return sel ? "#e1e1e1" : [selfColor];
}).ofObject()),
{
click: (e, obj) => {
clickNode(e, obj);
}
},
$(go.TextBlock,
{
stroke: "#000000", margin: 4, editable: false, font: "bold 12pt sans-serif", isMultiline: true
},
new go.Binding("text").makeTwoWay())
);
You can see that the default color for the node is #f8da07, but it is actually being written by the node self color property with the line "new go.Binding("fill", "color")".
And as it is, I have no way of knowing which one is the current color code of the node being selected.
I want to be able to change the color of the node to "#e1e1e1" when I select it, but I also want it to change back to the old color when not - (which is NOT "#f8da07").
Is there a proper way to do this?
Any help will be appreciated! Thanks
$(go.Shape,
{ fill: "#f8da07" }, // default color
new go.Binding("fill", "color"),
new go.Binding("fill", "isSelected", function(sel, shape) {
return sel ? "#e1e1e1" : shape.part.data.color || "#f8da07";
}).ofObject()),
How can I change the color to a node or edge that already exists on a layout (without deleting/adding it)?
I've got a layout of nodes with preselected positions which I want to change the color (nodes and also edges), but not of every node (or edge). I already tried
cy.style('background-color', 'color');
, that allows to change the color but it changes the color of every node.
I only want to change the style of one node.
Thanks a lot
Robert
Explanation:
Hi Robert, you are right, that cy.style() changes the style of the whole graph. What you probably didn't notice is, that you can specify really specifically, which element you want to execute this funtion on.
About cytoscape selectors:
If you want to select every element of a specific type, you can call this:
cy.elements(); // this returns all edges and nodes
cy.nodes(); // this returns all nodes
cy.edges(); // this returns all edges
If you want to get a specific group of elements or one in particular, you can perform a query like this:
cy.elements/nodes/edges('[selector =/!= "property"]'); // selector can be id and the property the actual id
Solution:
To get to the solution, here is what you can do:
cy.nodes('[id = "yourId"]').style('background-color', 'desiredColor');
Or binding it to an event, idk what your use-case is:
cy.unbind('click); // always unbind before binding an event to prevent binding it twiche/multiple times
cy.bind('click', 'node, edge', function(event) {
let target = event.target;
if (target.isEdge()) {
target.style('line-color', 'green');
} else {
target.style({
'background-color': 'white',
'border-color': 'blue'
});
}
});
Code example:
Here is a working example of this method:
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",
"background-color": "gray",
"border-opacity": "1",
"border-width": "10px"
}
},
{
selector: "edge",
css: {
"target-arrow-shape": "triangle"
}
},
{
selector: "edge[label]",
css: {
label: "data(label)",
"text-rotation": "autorotate",
"text-margin-x": "0px",
"text-margin-y": "0px"
}
},
{
selector: ":selected",
css: {
"background-color": "black",
"line-color": "black",
"target-arrow-color": "black",
"source-arrow-color": "black"
}
}
],
layout: {
name: "circle"
}
}));
var info = [{
name: "Peter",
next_op_name: "Claire"
},
{
name: "Claire",
next_op_name: "Mike"
},
{
name: "Mike",
next_op_name: "Rosa"
},
{
name: "Rosa",
next_op_name: "Peter"
}
];
cy.ready(function() {
var array = [];
// iterate over info once
for (var i = 0; i < info.length; i++) {
array.push({
group: "nodes",
data: {
id: info[i].name, // id is name!!!
label: info[i].name
}
});
array.push({
group: "edges",
data: {
id: "e" + i,
source: info[i].name,
target: info[i].next_op_name,
label: "e" + i
}
});
}
cy.add(array);
cy.layout({
name: "circle"
}).run();
});
cy.on("mouseover", "node", function(event) {
var node = event.target;
node.qtip({
content: "hello",
show: {
event: event.type,
ready: true
},
hide: {
event: "mouseout unfocus"
}
},
event
);
});
cy.unbind('click');
cy.bind('click', 'node, edge', function(event) {
let target = event.target;
if (target.isEdge()) {
target.style('line-color', 'green');
} else {
target.style({
'background-color': 'white',
'border-color': 'blue'
});
}
});
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://unpkg.com/cytoscape#3.3.0/dist/cytoscape.min.js"></script>
<!-- qtip imports -->
<script src="https://unpkg.com/jquery#3.3.1/dist/jquery.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.js"></script>
<link href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-qtip/2.7.0/cytoscape-qtip.js"></script>
<!-- dagre imports -->
<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>
NET MVC Core and I am trying to use Particles.js. I have already tried referencing a few tutorials, but am unable to solve this issue. This is how it normally looks like. https://vincentgarreau.com/particles.js/#default
I got this however, with big and super laggy buttons and also it does not occupy full screen nor does it have the hover action (whereby the circle moves away as the mouse approaches). The onclick circle works though. And the configuration shouldn't be wrong, as I downloaded the default one.
Update: Just before posting I managed to make it full screen. However, the big buttons and lagginess remains.
The following is my codes so far. I tried to search the id or class but due to the lack of documentation it is quite hard to find. Hope someone who knows it can help! Thank you very much :)
#{
ViewData["Title"] = "Home Page";
}
<div id="particles-js" style="background-color: rgb(0, 0, 0); background-image: url(""); background-size: cover; background-repeat: no-repeat; ba">
<canvas class="particles-js-canvas-el" style="width: 100%; height: 100%;"></canvas>
</div>
<script src="~/js/particles.js" data-turbolinks-track="reload" asp-append-version="true"></script>
<script>
particlesJS("particles-js", {
particles: {
number: {
value: 400,
density: {
enable: true,
value_area: 800
}
},
color: {
value: '#fff'
},
shape: {
type: 'circle',
stroke: {
width: 0,
color: '#ff0000'
},
polygon: {
nb_sides: 5
},
image: {
src: '',
width: 100,
height: 100
}
},
opacity: {
value: 1,
random: false,
anim: {
enable: false,
speed: 2,
opacity_min: 0,
sync: false
}
},
size: {
value: 20,
random: false,
anim: {
enable: false,
speed: 20,
size_min: 0,
sync: false
}
},
line_linked: {
enable: true,
distance: 100,
color: '#fff',
opacity: 1,
width: 1
},
move: {
enable: true,
speed: 2,
direction: 'none',
random: false,
straight: false,
out_mode: 'out',
bounce: false,
attract: {
enable: false,
rotateX: 3000,
rotateY: 3000
}
},
array: []
},
interactivity: {
detect_on: 'canvas',
events: {
onhover: {
enable: true,
mode: 'grab'
},
onclick: {
enable: true,
mode: 'push'
},
resize: true
},
modes: {
grab: {
distance: 100,
line_linked: {
opacity: 1
}
},
bubble: {
distance: 200,
size: 80,
duration: 0.4
},
repulse: {
distance: 200,
duration: 0.4
},
push: {
particles_nb: 4
},
remove: {
particles_nb: 2
}
},
mouse: {}
},
retina_detect: false,
});
//var count_particles, stats, update;
//stats = new Stats;
//stats.setMode(0);
//stats.domElement.style.position = 'absolute';
//stats.domElement.style.left = '0px';
//stats.domElement.style.top = '0px';
//document.body.appendChild(stats.domElement);
//count_particles = document.querySelector('.js-count-particles');
//update = function () {
// stats.begin();
// stats.end();
// if (window.pJSDom[0].pJS.particles && window.pJSDom[0].pJS.particles.array) {
// count_particles.innerText = window.pJSDom[0].pJS.particles.array.length;
// }
// requestAnimationFrame(update);
//};
//requestAnimationFrame(update);;
</script>
Update: I finally found the answer. To facilitate people who working on this in the future, make sure to use the download from the sidebar and not the one in the center.
Not this (the download in the center):
But this (the one at the bottom right side, "Download current config(json)"):
I have a Plotly on my webpage and you can download it as a png by clicking the picture icon in the modebar. However when I click it, it downloads it as a png with the name new-plot, how can I give it a custom name?
My current code (var data is just data, so left it out) :
var layout = {
showlegend: true,
legend: {
x: 0,
y: 1
},
xaxis: {
title: 'Date',
titlefont: {
family: 'Courier New, monospace',
size: 18,
color: '#7f7f7f'
}
},
yaxis: {
title: 'Sales',
titlefont: {
family: 'Courier New, monospace',
size: 18,
color: '#7f7f7f'
}
}
};
var options = {
scrollZoom: true,
showLink: false,
modeBarButtonsToRemove: ['zoom2d', 'pan', 'pan2d', 'sendDataToCloud', 'hoverClosestCartesian', 'autoScale2d'],
displaylogo: false,
displayModeBar: true,
};
Plotly.newPlot('tester', data, layout, options);
Use Plotly.downloadImage
https://plot.ly/javascript/plotlyjs-function-reference/#plotlydownloadimage
Add this to your modebar setup for the button callback:
Plotly.downloadImage({
filename: 'customNamedImage',
format: 'png', //also can use 'jpeg', 'webp', 'svg'
height: 500,
width: 500
});
Edit:
I ran a custom example and I think you will want to custimze your own download button in the modebar, like so:
Plotly.newPlot(gd, [{
y: [1, 2, 1],
line: { shape: 'spline' }
}], {
title: 'custom modebar button',
width: 400,
height: 700
}, {
showTips: false,
displayModeBar: true,
modeBarButtons: [[{
name: 'custom download button',
icon: Plotly.Icons.camera,
click: function (gd) {
Plotly.downloadImage(gd, {
filename: 'your_custom_name',
format: 'jpeg',
width: gd._fullLayout.width,
height: gd._fullLayout.height
})
}
}, 'toImage'
], []]
})
There's an easier way to do this in newer versions of Plotly (v1.38+). Use the toImageButtonOptions parameter in the config like this:
Plotly.newPlot(graphDiv, data, layout, {
toImageButtonOptions: {
filename: 'image_filename',
width: 800,
height: 600,
format: 'png'
}
});
You can leave out options you don't need to use the defaults.
Developing in Titanium Mobile.
I need to remove a view from a scrollView when a delete button is clicked. I have a custom event firing when my button is clicked, which the scrollView listens for. My question is, how do I reference the view that needs to be deleted? These views are added to the scrollView dynamically, and there is no unique information about the view. I tried passing the view itself when firing the custom event, but this does not work. How do I tell the scrollView which view to delete?
When you have a delete button inside the view - that's a piece of cake :) Just get its' parent and delete it - scrollView.remove(e.source.parent);
Here I created a demo page:
var scrollView = Titanium.UI.createScrollView({
contentWidth: 'auto',
contentHeight: 'auto',
top: 0,
showVerticalScrollIndicator: true,
showHorizontalScrollIndicator: true,
layout: 'vertical'
});
var colors = ['red', 'green', 'blue', 'orange', 'purple', 'yellow'];
for (var i = 0; i < 6; i++) {
var view = Ti.UI.createView({
backgroundColor: colors[i],
borderRadius: 10,
width: 300,
height: 200,
top: 10,
id: i
});
scrollView.add(view);
var deleteButton = Ti.UI.createButton({
borderRadius: 3,
style: Ti.UI.iPhone.SystemButtonStyle.PLAIN,
backgroundGradient: {
type: 'linear',
colors: [ '#c7c7c7', '#686868' ],
startPoint: { x: 0, y: 0 },
endPoint: { x: 0, y: 30 },
backFillStart: false
},
title: 'Delete view ' + i,
font: { fontSize: 12, fontWeight: 'bold' },
color: '#fff',
width: 120,
height: 30
});
view.add(deleteButton);
deleteButton.addEventListener('click', function(e) {
Ti.API.info(e.source.id); // use this ID
scrollView.remove(e.source.parent);
});
}
Ti.UI.currentWindow.add(scrollView);