Label to flows in JointJS - javascript

I'm working with jointJs and Rappid. I know how to draw a bpmn diagram, as the photo I have attached. I'm drawing the elements, but I'm having some problems with rows (flows). Is there any way to add a flow label or name? As I added on my image in red color.
I have seen this in their documentation, but I can't see anything about labels
var flow = new joint.shapes.bpmn.Flow({
source: { id: task.id },
target: { id: annotation.id },
flowType: 'association'
});
Thanks,

You may want to look into dia.Link.prototype.labels, since BPMN Flows are just Links extensions (joint.shapes.bpmn.Flow = joint.dia.Link.extend({).
An example to your flow:
flow.label(0, // the label's index (you can have multiple labels per link/flow)
{
position: .5, // place it halfway on the link (0-1)
attrs: {
text: { fill: 'red', text: 'Label' }
}
}
);

Related

Highcharts - Suppress points being dragged on drag event

I'm new to Highcharts - it seems you can only trigger drag events if the appropriate dragDrop events are defined and enabled on a series. E.g. https://api.highcharts.com/highcharts/plotOptions.series.dragDrop
How can I suppress the points actually being moved around in my chart? I have tried setting allowPointSelect: false and disabling both draggableX and draggableY but of course doing that don't fire any drag events. I have also tried event.preventDefault but no luck
What I'm basically looking for is to have a user drag over a range in a line/area chart from startX/Y to endX/Y and display the results to the user (which I can successfully get using mouseOver - a nice feature!)
For such a feature, you don't need to use draggable-points module. A simple custom solution with a crosshair and dynamically added/removed plot-lines will be enough. For example:
chart: {
animation: false,
events: {
load: function() {
const chart = this;
this.series[0].points.forEach(point => {
point.graphic.on('mousedown', function() {
chart.draggedPoint = point;
chart.xAxis[0].update({
plotLines: [{
width: 2,
color: 'grey',
dashStyle: 'ShortDash',
value: point.x
}]
});
});
});
document.body.addEventListener('mouseup', function() {
chart.draggedPoint = null;
chart.xAxis[0].update({
plotLines: []
});
});
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/rsuj93at/
API Reference: https://api.highcharts.com/highcharts/tooltip.formatter

SAP UI5 Gantt Chart color based on condition

How can I set the fill color of a Gantt chart shape based on the value of a property in the bound json model?
Here's the code I am using to configure the sap.gantt.config.Shape :-
var oRectangle = new sap.gantt.config.Shape({
key: "Rectangle",
shapeDataName: "schedule",
shapeClassName: "sap.gantt.shape.Rectangle",
shapeProperties: {
time: "{startTime}",
endTime: "{endTime}",
height: 32,
fill: "green",
title: "{name}",
level: 0
}
});
The use case I am trying to address is :-
If there are 4 or more schedules, then fill the shape with GREEN else fill YELLOW.
I have already tried expression binding like :
fill: "{= ${data>/schedule}.length > 4 ? 'green' : 'yellow' }"
But that didn't give any result and filled the shape with the default BLACK color.
Is there some other way of getting it possible?
Also, is there a way we can configure Gantt shapes in XML views itself ratherer than doing all these configurations the in controller?
delete the attribute from your shape definition.
Before you define the oRectangle, put the following code segment:
sap.ui.define(["sap/gantt/shape/Rectangle"], function (Rectangle) {
var shapeRectangle = Rectangle.extend("sap.test.shapeRectangle");
shapeRectangle.prototype.getFill = function (oRawData) {
return oRawData.color;
};
return shapeRectangle;
}, true);
After that, you have to provide the property color to the order in your data model on the same level as startTime, endTime, etc...

How to create custom legend in ChartJS

I need to create custom legend for my donut chart using ChartJS library.
I have created donut with default legend provided by ChartJS but I need some modification.
I would like to have value above the car name. Also I don't like sticky legend I want to have it separate from donut so I can change the style for fonts, boxes (next to the text "Audi" for example)
I know there is some Legend generator but I'm not sure how to use it with VueJS - because I'm using VueJS as a framework
This is how my legend looks like now - http://imgur.com/a/NPUoi
My code:
From Vue component where I import a donut component:
<div class="col-md-6">
<div class="chart-box">
<p class="chart-title">Cars</p>
<donut-message id="chart-parent"></donut-message>
</div>
</div>
Javascript:
import { Doughnut } from 'vue-chartjs'
export default Doughnut.extend({
ready () {
Chart.defaults.global.tooltips.enabled = false;
Chart.defaults.global.legend.display = false;
this.render({
labels: ['Audi','BMW','Ford','Opel'],
datasets: [
{
label: 'Cars',
backgroundColor: ['#35d89b','#4676ea','#fba545','#e6ebfd'],
data: [40, 30, 20, 10]
}
]
},
{
responsive: true,
cutoutPercentage: 75,
legend: {
display: true,
position: "right",
fullWidth: true,
labels: {
boxWidth: 10,
fontSize: 14
}
},
animation: {
animateScale: true
}
})
}
});
I'm having the same problem trying to understand the documentation and this link might clarify the process of customize the legends:
https://codepen.io/michiel-nuovo/pen/RRaRRv
The trick is to track a callback to build your own HTML structure and return this new structure to ChartJS.
Inside the options object:
legendCallback: function(chart) {
var text = [];
text.push('<ul class="' + chart.id + '-legend">');
for (var i = 0; i < chart.data.datasets[0].data.length; i++) {
text.push('<li><span style="background-color:' +
chart.data.datasets[0].backgroundColor[i] + '">');
if (chart.data.labels[i]) {
text.push(chart.data.labels[i]);
}
text.push('</span></li>');
}
text.push('</ul>');
return text.join("");
}
Second, you need a container to insert the new html and using the method myChart.generateLegend() to get the customized html:
$("#your-legend-container").html(myChart.generateLegend());
After that, if you need, track down the events:
$("#your-legend-container").on('click', "li", function() {
myChart.data.datasets[0].data[$(this).index()] += 50;
myChart.update();
console.log('legend: ' + data.datasets[0].data[$(this).index()]);
});
$('#myChart').on('click', function(evt) {
var activePoints = myChart.getElementsAtEvent(evt);
var firstPoint = activePoints[0];
if (firstPoint !== undefined) {
console.log('canvas: ' +
data.datasets[firstPoint._datasetIndex].data[firstPoint._index]);
}
else {
myChart.data.labels.push("New");
myChart.data.datasets[0].data.push(100);
myChart.data.datasets[0].backgroundColor.push("red");
myChart.options.animation.animateRotate = false;
myChart.options.animation.animateScale = false;
myChart.update();
$("#your-legend-container").html(myChart.generateLegend());
}
}
Another solution that I found, if you don't need to change the HTMl structure inside the legend, you can just insert the same HTML in your legend container and customize it by CSS, check this another link:
http://jsfiddle.net/vrwjfg9z/
Hope it works for you.
You can extract the legend markup.
data () {
return {
legendMarkup: ''
}
},
ready () {
this.legendMarkup = this._chart.generateLegend()
}
And in your template you can output it.
<div class="legend" ref="legend" v-html="legendMarkup"></div>
this._chart is the internal chartjs instance in vue-chartjs. So you can call all chartjs methods which are not exposed by vue-chartjs api over it.
However you can also use the legend generator. The usage is the same in vue. You can pass in the options, use callbacks etc.
please check this documentation
.
Legend Configuration
The chart legend displays data about the datasets that area appearing on the chart.
Configuration options
Position of the legend. Options are:
'top'
'left'
'bottom'
'right'
Legend Item Interface
Items passed to the legend onClick function are the ones returned from labels.generateLabels. These items must implement the following interface.
{
// Label that will be displayed
text: String,
// Fill style of the legend box
fillStyle: Color,
// If true, this item represents a hidden dataset. Label will be rendered with a strike-through effect
hidden: Boolean,
// For box border. See https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap
lineCap: String,
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setLineDash
lineDash: Array[Number],
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineDashOffset
lineDashOffset: Number,
// For box border. See https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/lineJoin
lineJoin: String,
// Width of box border
lineWidth: Number,
// Stroke style of the legend box
strokeStyle: Color
// Point style of the legend box (only used if usePointStyle is true)
pointStyle: String
}
Example
The following example will create a chart with the legend enabled and turn all of the text red in color.
var chart = new Chart(ctx, {
type: 'bar',
data: data,
options: {
legend: {
display: true,
labels: {
fontColor: 'rgb(255, 99, 132)'
}
}
}
});
Custom On Click Actions
It can be common to want to trigger different behaviour when clicking an item in the legend. This can be easily achieved using a callback in the config object.
The default legend click handler is:
function(e, legendItem) {
var index = legendItem.datasetIndex;
var ci = this.chart;
var meta = ci.getDatasetMeta(index);
// See controller.isDatasetVisible comment
meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
// We hid a dataset ... rerender the chart
ci.update();
}
Lets say we wanted instead to link the display of the first two datasets. We could change the click handler accordingly.
var defaultLegendClickHandler = Chart.defaults.global.legend.onClick;
var newLegendClickHandler = function (e, legendItem) {
var index = legendItem.datasetIndex;
if (index > 1) {
// Do the original logic
defaultLegendClickHandler(e, legendItem);
} else {
let ci = this.chart;
[ci.getDatasetMeta(0),
ci.getDatasetMeta(1)].forEach(function(meta) {
meta.hidden = meta.hidden === null? !ci.data.datasets[index].hidden : null;
});
ci.update();
}
};
var chart = new Chart(ctx, {
type: 'line',
data: data,
options: {
legend: {
}
}
});
Now when you click the legend in this chart, the visibility of the first two datasets will be linked together.
HTML Legends
Sometimes you need a very complex legend. In these cases, it makes sense to generate an HTML legend. Charts provide a generateLegend() method on their prototype that returns an HTML string for the legend.
To configure how this legend is generated, you can change the legendCallback config property.
var chart = new Chart(ctx, {
type: 'line',
data: data,
options: {
legendCallback: function(chart) {
// Return the HTML string here.
}
}
});

Highcharts Donut Chart customization

I'm working with highcharts and aiming to make a chart similar to this:
Now I've been playing around with the whole ordeal for a while now and I've come been able to reach the following point: http://jsfiddle.net/ccjSy/24/
$(function () {
$(document).ready(function () {
var chart = null;
var categories = ['Body Fat', 'Lean Mass'],
name = 'Body Fat vs. Lean Mass',
data = [{
y: 69,
color: '#F0CE0C',
drilldown: {
name: 'Body Fat',
color: '#F0CE0C'
}
}, {
y: 207,
color: '#23A303',
drilldown: {
name: 'Lean Mass' ,
color: '#23A303'
}
}];
// Build the data array
var browserData = [];
for (var i = 0; i < data.length; i++) {
// add browser data
browserData.push({
name: categories[i],
y: data[i].y,
color: data[i].color
});
}
// Create the chart
chart = new Highcharts.Chart({
chart: {
renderTo: 'donutchart',
type: 'pie',
spacingTop: 0
},
title: {
text: 'Your Body Fat vs Lean Mass',
style: {"color": '#7d7d7d'}
},
series: [{
name: 'Weight',
data: browserData,
dataLabels: {
style: {
fontFamily: 'ArialMT',
fontSize: '15px',
fontWeight: 'bold',
color: '#7d7d7d'
}
},
innerSize: '70%'
}],
tooltip: {
valueSuffix: ' lbs'
},
plotOptions: {
series: {
cursor: 'pointer'
}
}
});
});
});
I am thinking of leaving the space empty in the donut chart and inserting a custom circle with the Weight labeling.
However, I'm not certain how to tackle the following problems:
1) Leave more defined white spaces in between my two columns
2) How to properly align my two data labels? (As you can see in the model, they are in a straight line with neutral lines attached)
3) How to display the data underneath the two labels with both, the pounds and the percentage, as shown in the image.
Answering each of your three questions:
"More white space between columns?" -- add a plotOptions.pie.borderWidth element. The default value is 1. I used 5 to give it more white space.
"Properly align the two data labels?" -- You can compute a custom startAngle based on the two data values which will give you the correct angle to start with. Since you only have two data values in the series, that's easy.
Calculate startAngle for pie chart
var startAngle = 0 - (90 + (180 * (data[0].y / (data[0].y + data[1].y))));
Notice that if you change the y value for the first data object, the "Body Fat" portion of the pie chart will still maintain it's correct position, even as the portion of the chart grows larger or smaller.
"Display data underneath the two labels with custom formatting?" -- use plotOptions.pie.format to apply custom formatting to the pie value labels.
format: '<div style="position: relative; top: -20px; text-align: center">{point.name}<br><b><span style="font-size: 29px">{point.percentage:.0f}%</span></b> ({point.y} lbs)</div>'
Here's a working JSFiddle to see the results. You'll still need to add a dark gray circle behind the pie chart and add the "Total Weight" text but that shouldn't be too difficult.
Since I'm sure you'll be wondering about this, I should mention that there's a lot of white space under the pie chart title because it's leaving enough room for other labels that may appear above or below the pie. Since you're only using two values that will always be on the left/right sides of the pie chart, that doesn't change the fact that HighCharts is preparing to have other labels that may need to be displayed in the surrounding area.

Highcharts: How to link legend to categories rather than to bar series?

Using Highcharts to display a bar chart, is there a built-in way to link legend items to categories rather than to series? As such I would see a chart with a bunch of bars, and when I click a legend item it would show or hide just the bar(s) associated with a single category.
Thanks
There is not a built in way.
You can fake it in a number of ways, however.
One way is to use a separate series for each category, set grouping to false, dummy the x values to hover around the actual category value.
plotOptions: {
series: {
grouping: false,
pointRange: 0.2
}
},
series: [{
name: 'Group A',
data: [[-0.25,5],[0,7],[0.25,6]]
}]
Example:
http://jsfiddle.net/jlbriggs/x1cdz54r/
In the end, I found no out-of-the-box way to do this. But I found a solution that works, as follows:
correlate each bar with a single series (see fiddle referenced above)
in legendItemClick:
manually show or hide the series associated with the clicked-on legend item
given visibility of each category, recompute the indices of each visible category and update each visible bar series data[0].x with the new index of the category with which it is associated (use point.update())
call xAxis.setCategories with a list of the categories you want to be currently visible
call xAxis.setExtremes with the new extremes for the category indices
Here is a very simple example of the above:
legendItemClick = function (e) {
var seriesClicked = e.currentTarget;
var chart = seriesClicked.chart;
var axis = chart.xAxis[0]
if (seriesClicked.visible) {
seriesClicked.hide();
chart.series[2].data[0].update( { x: 1 });
axis.setCategories(['Group A', 'Group C'], false)
axis.setExtremes(0, 1, true)
} else {
seriesClicked.show();
chart.series[2].data[0].update( { x: 2 });
axis.setCategories(['Group A', 'Group B', 'Group C'], false)
axis.setExtremes(0, 2, true)
}
return false;
}
And a fiddle: http://jsfiddle.net/dkent600/e6357a22/17/

Categories

Resources