<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ZingSoft Demo</title>
<script nonce="undefined" src="https://cdn.zingchart.com/zingchart.min.js"></script>
<style>
.chart--container {
min-height: 530px;
width: 100%;
height: 100%;
}
/* CSS for custom tooltip outside of ZingChart */
#custom-tooltip {
background-color: #B0BEC5;
border-radius: 4px;
color: #000;
font-size: 14px;
padding: 3px 0px;
position: absolute;
text-align: center;
width: 100px;
z-index: 1000;
}
#custom-tooltip:hover {
cursor: pointer;
}
.zc-ref {
display: none;
}
</style>
</head>
<body>
<div id="myChart" class="chart--container">
<a class="zc-ref" href="https://www.zingchart.com/">Powered by ZingChart</a>
</div>
<script>
ZC.LICENSE = ["569d52cefae586f634c54f86dc99e6a9", "b55b025e438fa8a98e32482b5f768ff5"];
let chartConfig = {
type: 'scatter',
theme: 'dark',
globals: {
fontColor: '#fff',
},
forecastWeight: {},
utc: true,
title: {
text: 'PROGRAM OVERVIEW',
align: 'left',
marginTop: '13px',
marginLeft: '72px',
backgroundColor: 'none',
fontColor: '#B0BEC5',
fontSize: '18px'
},
plot: {
tooltip: {
text: '%kl <br> Node Value: %v',
borderRadius: '5px'
},
cursor: 'pointer',
hoverMarker: {
border: 'none',
size: '9px'
},
marker: {
size: '8px'
}
},
plotarea: {
marginRight: '70px',
marginBottom: '148px',
marginLeft: 'dynamic'
},
scaleX: {
guide: {
visible: false
},
transform: {
type: 'date',
all: '%d %M %Y'
},
zooming: true
},
scaleY: {
values: '-20:120:20',
guide: {
lineStyle: 'solid'
},
label: {
text: 'Forecast Revenue',
fontSize: '14px'
},
refLine: {
lineWidth: '0px'
},
zooming: true
},
labels: [{
id: 'reset',
text: 'Reset',
backgroundColor: '#FF6E40',
borderRadius: '5px',
cursor: 'pointer',
fontColor: '#FFF',
fontSize: '14px',
offsetX: '-80px',
width: '55px',
height: '30px',
x: '100%',
y: '20px'
}],
zoom: {
label: {
backgroundColor: '#D4D4D4'
}
},
scrollX: {
bar: {
borderColor: 'none',
borderRadius: '7px'
},
handle: {
backgroundColor: '#00E5FF'
}
},
scrollY: {
bar: {
borderRadius: '7px'
},
handle: {
backgroundColor: '#00E5FF'
}
},
preview: {
handle: {
backgroundColor: '#00E5FF',
borderColor: '#00E5FF',
borderRadius: '10px',
width: '20px',
height: '20px'
},
live: true,
},
//legend: {},
series: [{
text: 'NewsPaper Ads',
values: [
[1546333207000, 35],
[1546678807000, -5]
],
backgroundColor: '#FF4081',
dataWeight: [55, 75],
marker: {
backgroundColor: '#FF4081'
}
},
{
text: 'Digital Ads',
values: [
[1546851607000, 89],
[1546506007000, 25]
],
backgroundColor: '#448AFF',
dataWeight: [123, 88],
marker: {
backgroundColor: '#448AFF'
}
},
{
text: 'Magazine Ads',
values: [
[1546765207000, 50],
[1546592407000, 75]
],
backgroundColor: '#FFAB40',
dataWeight: [78, 95],
marker: {
backgroundColor: '#FFAB40'
}
}
]
};
// Create a custom HTML tooltip outside of ZingChart on node_click
zingchart.node_click = (e) => {
let xPosition = e.ev.clientX;
let yPosition = e.ev.clientY;
let graphInfo = zingchart.exec(e.id, 'getobjectinfo', {
object: 'graph'
});
let plotInfo = zingchart.exec(e.id, 'getobjectinfo', {
object: 'plot',
plotindex: e.plotindex
});
let graphWidth = graphInfo.width;
let graphHeight = graphInfo.height;
// tooltip DOM creation
let tooltip = document.getElementById('custom-tooltip');
if (!tooltip) tooltip = document.createElement('div');
// Calculate tooltip position
tooltip.id = 'custom-tooltip';
tooltip.style.left = (xPosition > (graphWidth / 2)) ? (xPosition - 115) + 'px' : (xPosition + 20) + 'px';
tooltip.style.top = (yPosition > (graphHeight / 2)) ? (yPosition - 30) + 'px' : (yPosition - 50) + 'px';
tooltip.style.visibility = 'visible';
// tooltip will grab the custom token at the correct index from the plot
tooltip.innerHTML = plotInfo.text + ' <br> ' + 'Weight: ' + plotInfo.xdata.weight[e.nodeindex];
// add event listener for clicking on the tooltip to remove it
tooltip.addEventListener('click', () => {
this.style.visibility = 'hidden';
});
document.body.appendChild(tooltip);
}
// On click remove the custom HTML tooltip
zingchart.click = () => {
let tooltip = document.getElementById('custom-tooltip');
if (tooltip)
tooltip.style.visibility = 'hidden';
}
// On zoom remove the custom HTML tooltip
zingchart.zoom = () => {
let tooltip = document.getElementById('custom-tooltip');
if (tooltip)
tooltip.style.visibility = 'hidden';
}
// zoomout on reset button click
zingchart.label_click = (e) => {
if (e.labelid == 'reset') {
zingchart.exec('myChart', 'viewall');
}
}
// Define module before render method
zingchart.defineModule('forecastWeight', 'plugin', (json) => {
// marker class
let Marker = () => {
return {
type: 'rectangle',
backgroundColor: 'none',
width: '5px',
height: '10px',
offsetY: '5px',
borderWidth: '0px'
};
};
// loop through and create weighted series
let additionalSeries = [];
for (let i = 0; i < json.series.length; i++) {
let rules = [];
let newSeries = JSON.parse(JSON.stringify(json.series[i]));
let weightedMarker = Marker();
weightedMarker.backgroundColor = newSeries.backgroundColor;
for (let j = 0; j < newSeries['dataWeight'].length; j++) {
let iHeight = newSeries['dataWeight'][j];
let ioffsetY = -(iHeight / 2);
rules.push({
rule: '%i == ' + j,
height: iHeight,
offsetY: ioffsetY
});
}
weightedMarker.rules = rules;
newSeries.marker = weightedMarker;
additionalSeries.push(newSeries);
}
// add new series
for (let i = 0; i < additionalSeries.length; i++) {
json.series.push(additionalSeries[i]);
}
return json;
});
zingchart.render({
id: 'myChart',
data: chartConfig,
modules: 'forecastWeight',
height: '100%',
width: '100%',
});
</script>
</body>
</html>
let chartConfig = {
type: 'scatter',
theme: 'dark',
globals: {
fontColor: '#fff',
},
forecastWeight: {},
utc: true,
title: {
text: 'PROGRAM OVERVIEW',
align: 'left',
marginTop: '13px',
marginLeft: '72px',
backgroundColor: 'none',
fontColor: '#B0BEC5',
fontSize: '18px'
},
plot: {
tooltip: {
text: '%kl <br> Node Value: %v',
borderRadius: '5px'
},
cursor: 'pointer',
hoverMarker: {
border: 'none',
size: '9px'
},
marker: {
size: '8px'
}
},
plotarea: {
marginRight: '70px',
marginBottom: '148px',
marginLeft: 'dynamic'
},
scaleX: {
guide: {
visible: false
},
transform: {
type: 'date',
all: '%d %M %Y'
},
zooming: true
},
scaleY: {
values: '-20:120:20',
guide: {
lineStyle: 'solid'
},
label: {
text: 'Forecast Revenue',
fontSize: '14px'
},
refLine: {
lineWidth: '0px'
},
zooming: true
},
labels: [
{
id: 'reset',
text: 'Reset',
backgroundColor: '#FF6E40',
borderRadius: '5px',
cursor: 'pointer',
fontColor: '#FFF',
fontSize: '14px',
offsetX: '-80px',
width: '55px',
height: '30px',
x: '100%',
y: '20px'
}
],
zoom: {
label: {
backgroundColor: '#D4D4D4'
}
},
scrollX: {
bar: {
borderColor: 'none',
borderRadius: '7px'
},
handle: {
backgroundColor: '#00E5FF'
}
},
scrollY: {
bar: {
borderRadius: '7px'
},
handle: {
backgroundColor: '#00E5FF'
}
},
preview: {
handle: {
backgroundColor: '#00E5FF',
borderColor: '#00E5FF',
borderRadius: '10px',
width: '20px',
height: '20px'
},
live: true,
},
//legend: {},
series: [
{
text: 'NewsPaper Ads',
values: [[1546333207000, 35], [1546678807000, -5]],
backgroundColor: '#FF4081',
dataWeight: [55, 75],
marker: {
backgroundColor: '#FF4081'
}
},
{
text: 'Digital Ads',
values: [[1546851607000, 89], [1546506007000, 25]],
backgroundColor: '#448AFF',
dataWeight: [123, 88],
marker: {
backgroundColor: '#448AFF'
}
},
{
text: 'Magazine Ads',
values: [[1546765207000, 50], [1546592407000, 75]],
backgroundColor: '#FFAB40',
dataWeight: [78, 95],
marker: {
backgroundColor: '#FFAB40'
}
}
]
};
// Create a custom HTML tooltip outside of ZingChart on node_click
zingchart.node_click = (e) => {
let xPosition = e.ev.clientX;
let yPosition = e.ev.clientY;
let graphInfo = zingchart.exec(e.id, 'getobjectinfo', {
object: 'graph'
});
let plotInfo = zingchart.exec(e.id, 'getobjectinfo', {
object: 'plot',
plotindex: e.plotindex
});
let graphWidth = graphInfo.width;
let graphHeight = graphInfo.height;
// tooltip DOM creation
let tooltip = document.getElementById('custom-tooltip');
if (!tooltip) tooltip = document.createElement('div');
// Calculate tooltip position
tooltip.id = 'custom-tooltip';
tooltip.style.left = (xPosition > (graphWidth / 2)) ? (xPosition - 115) + 'px' : (xPosition + 20) + 'px';
tooltip.style.top = (yPosition > (graphHeight / 2)) ? (yPosition - 30) + 'px' : (yPosition - 50) + 'px';
tooltip.style.visibility = 'visible';
// tooltip will grab the custom token at the correct index from the plot
tooltip.innerHTML = plotInfo.text + ' <br> ' + 'Weight: ' + plotInfo.xdata.weight[e.nodeindex];
// add event listener for clicking on the tooltip to remove it
tooltip.addEventListener('click', () => {
this.style.visibility = 'hidden';
});
document.body.appendChild(tooltip);
}
// On click remove the custom HTML tooltip
zingchart.click = () => {
let tooltip = document.getElementById('custom-tooltip');
if (tooltip)
tooltip.style.visibility = 'hidden';
}
// On zoom remove the custom HTML tooltip
zingchart.zoom = () => {
let tooltip = document.getElementById('custom-tooltip');
if (tooltip)
tooltip.style.visibility = 'hidden';
}
// zoomout on reset button click
zingchart.label_click = (e) => {
if (e.labelid == 'reset') {
zingchart.exec('myChart', 'viewall');
}
}
// Define module before render method
zingchart.defineModule('forecastWeight', 'plugin', (json) => {
// marker class
let Marker = () => {
return {
type: 'rectangle',
backgroundColor: 'none',
width: '5px',
height: '10px',
offsetY: '5px',
borderWidth: '0px'
};
};
// loop through and create weighted series
let additionalSeries = [];
for (let i = 0; i < json.series.length; i++) {
let rules = [];
let newSeries = JSON.parse(JSON.stringify(json.series[i]));
let weightedMarker = Marker();
weightedMarker.backgroundColor = newSeries.backgroundColor;
for (let j = 0; j < newSeries['dataWeight'].length; j++) {
let iHeight = newSeries['dataWeight'][j];
let ioffsetY = -(iHeight / 2);
rules.push({
rule: '%i == ' + j,
height: iHeight,
offsetY: ioffsetY
});
}
weightedMarker.rules = rules;
newSeries.marker = weightedMarker;
additionalSeries.push(newSeries);
}
// add new series
for (let i = 0; i < additionalSeries.length; i++) {
json.series.push(additionalSeries[i]);
}
return json;
});
zingchart.render({
id: 'myChart',
data: chartConfig,
modules: 'forecastWeight',
height: '100%',
width: '100%',
});