$(() => {
const data = complaintsData.sort((a, b) => b.count - a.count);
const totalCount = data.reduce((prevValue, item) => prevValue + item.count, 0);
let cumulativeCount = 0;
const dataSource = data.map((item) => {
cumulativeCount += item.count;
return {
complaint: item.complaint,
count: item.count,
cumulativePercentage: Math.round((cumulativeCount * 100) / totalCount),
};
});
$('#chart').dxChart({
palette: 'Harmony Light',
dataSource,
title: 'Pizza Shop Complaints',
argumentAxis: {
label: {
overlappingBehavior: 'stagger',
},
},
tooltip: {
enabled: true,
shared: true,
customizeTooltip(info) {
const content = ["<div><div class='tooltip-header'></div>",
"<div class='tooltip-body'><div class='series-name'>",
"<span class='top-series-name'></span>",
": </div><div class='value-text'>",
"<span class='top-series-value'></span>",
"</div><div class='series-name'>",
"<span class='bottom-series-name'></span>",
": </div><div class='value-text'>",
"<span class='bottom-series-value'></span>",
'% </div></div></div>'].join('');
const htmlContent = $(content);
htmlContent.find('.tooltip-header').text(info.argumentText);
htmlContent.find('.top-series-name').text(info.points[0].seriesName);
htmlContent.find('.top-series-value').text(info.points[0].valueText);
htmlContent.find('.bottom-series-name').text(info.points[1].seriesName);
htmlContent.find('.bottom-series-value').text(info.points[1].valueText);
return {
html: $('<div>').append(htmlContent).html(),
};
},
},
valueAxis: [{
name: 'frequency',
position: 'left',
tickInterval: 300,
}, {
name: 'percentage',
position: 'right',
showZero: true,
label: {
customizeText(info) {
return `${info.valueText}%`;
},
},
constantLines: [{
value: 80,
color: '#fc3535',
dashStyle: 'dash',
width: 2,
label: { visible: false },
}],
tickInterval: 20,
valueMarginsEnabled: false,
}],
commonSeriesSettings: {
argumentField: 'complaint',
},
series: [{
type: 'bar',
valueField: 'count',
axis: 'frequency',
name: 'Complaint frequency',
color: '#fac29a',
}, {
type: 'spline',
valueField: 'cumulativePercentage',
axis: 'percentage',
name: 'Cumulative percentage',
color: '#6b71c3',
}],
legend: {
verticalAlignment: 'top',
horizontalAlignment: 'center',
},
});
});
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script>
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/23.1.5/css/dx.light.css" />
<script src="https://cdn3.devexpress.com/jslib/23.1.5/js/dx.all.js"></script>
<script src="data.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
<script src="index.js"></script>
</head>
<body class="dx-viewport">
<div class="demo-container">
<div id="chart-demo">
<div id="chart"></div>
</div>
</div>
</body>
</html>
#chart {
height: 440px;
}
.tooltip-header {
margin-bottom: 5px;
font-size: 16px;
font-weight: 500;
padding-bottom: 5px;
border-bottom: 1px solid #c5c5c5;
}
.tooltip-body {
width: 170px;
}
.tooltip-body .series-name {
font-weight: normal;
opacity: 0.6;
display: inline-block;
line-height: 1.5;
padding-right: 10px;
width: 126px;
}
.tooltip-body .value-text {
display: inline-block;
line-height: 1.5;
width: 30px;
}
const complaintsData = [
{ complaint: 'Cold pizza', count: 780 },
{ complaint: 'Not enough cheese', count: 120 },
{ complaint: 'Underbaked or Overbaked', count: 52 },
{ complaint: 'Delayed delivery', count: 1123 },
{ complaint: 'Damaged pizza', count: 321 },
{ complaint: 'Incorrect billing', count: 89 },
{ complaint: 'Wrong size delivered', count: 222 },
];