<!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>
.zc-body {
background-color: #FFF;
font: 100%/1.5 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif, 'Comic Sans';
}
.chart--container {
background-color: #FFF;
min-height: 530px;
width: 100%;
height: 100%;
}
#day {
color: #2196F3;
}
#day {
margin-top: 20px;
margin-right: 20px;
font-size: 25px;
float: right;
}
#date-picker-container {
margin-left: 25px;
}
[data-period] {
margin: 5px;
padding: 10px 10px;
background-color: #2196F3;
color: #FFF;
display: inline-block;
}
[data-period]:hover {
cursor: pointer;
opacity: .7;
}
#date-picker-container div {
display: inline-block;
}
#date-from,
#date-to {
margin-right: 6px;
margin-left: 6px;
color: #2196F3;
}
.active {
background: #fd992b;
}
.zc-ref {
display: none;
}
</style>
</head>
<body>
<div id="myChart" class="chart--container">
<div id="date-picker-container">
<span data-period="1" class="active">30 Days</span>
<span data-period="2">60 Days</span>
<span data-period="3">90 Days</span>
<div>
<b>From:</b>
<span id="date-from">1/31/19</span>
</div>
<div>
<b>To:</b>
<span id="date-to">6/17/19</span>
</div>
<div id="day"></div>
</div>
<div id="main-container">
<a class="zc-ref" href="https://www.zingchart.com/">Powered by ZingChart</a>
</div>
</div>
<script>
ZC.LICENSE = ["569d52cefae586f634c54f86dc99e6a9", "b55b025e438fa8a98e32482b5f768ff5"];
let chartConfig = {
type: 'mixed',
title: {
text: 'Projected Cash Flow',
align: 'center',
},
plot: {
tooltip: {
visible: false,
},
aspect: 'spline',
marker: {
visible: false,
},
},
plotarea: {},
scaleX: {
values: [
'1/31/19',
'2/10/19',
'2/11/19',
'2/12/19',
'2/13/19',
'2/19/19',
'2/18/19',
'2/19/19',
'2/20/19',
'2/21/19',
'2/24/19',
'2/25/19',
'2/26/19',
'2/27/19',
'2/28/19',
'2/3/19',
'2/4/19',
'2/5/19',
'2/6/19',
'2/7/19',
'3/10/19',
'3/11/19',
'3/12/19',
'3/13/19',
'3/14/19',
'3/17/19',
'3/18/19',
'3/19/19',
'3/20/19',
'3/21/19',
'3/24/19',
'3/25/19',
'3/26/19',
'3/27/19',
'3/28/19',
'3/3/19',
'3/31/19',
'3/4/19',
'3/5/19',
'3/6/19',
'3/7/19',
'4/1/19',
'4/10/19',
'4/11/19',
'4/14/19',
'4/15/19',
'4/16/19',
'4/17/19',
'4/2/19',
'4/21/19',
'4/22/19',
'4/23/19',
'4/24/19',
'4/25/19',
'4/28/19',
'4/29/19',
'4/3/19',
'4/30/19',
'4/4/19',
'4/7/19',
'4/8/19',
'4/9/19',
'5/1/19',
'5/12/19',
'5/13/19',
'5/14/19',
'5/15/19',
'5/16/19',
'5/19/19',
'5/20/19',
'5/21/19',
'5/22/19',
'5/23/19',
'5/27/19',
'5/28/19',
'5/29/19',
'5/30/19',
'5/5/19',
'5/6/19',
'5/7/19',
'5/8/19',
'5/9/19',
'6/10/19',
'6/11/19',
'6/12/19',
'6/13/19',
'6/16/19',
'6/17/19',
],
itemsOverlap: true,
lineWidth: '0px',
tick: {
alpha: 1,
lineColor: '#2196F3',
lineWidth: '2px',
},
zooming: true,
zoomTo: [0, 30],
},
scaleY: {
values: '0:20000:1000',
guide: {
visible: false,
},
},
scaleY2: {},
crosshairX: {
lineColor: '#2196F3',
lineStyle: 'dashed',
lineWidth: '2px',
marker: {
type: 'triangle',
size: '5px',
visible: true,
},
plotLabel: {
visible: false,
},
},
preview: {
live: true,
},
series: [{
type: 'bar',
values: [
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
8000, 0, 5000,
],
backgroundColor: '#FFEB3B',
scales: 'scale-x, scale-y-2',
},
{
type: 'line',
values: [
6000, 7000, 3000, 4000, 10000, 13000, 5000, 0, 9000, 16000, 9000, 6000,
7000, 3000, 4000, 10000, 13000, 5000, 0, 9000, 16000, 9000, 6000, 7000,
3000, 4000, 10000, 13000, 5000, 0, 9000, 16000, 9000, 6000, 7000, 3000,
4000, 10000, 13000, 5000, 0, 9000, 16000, 9000, 6000, 7000, 3000, 4000,
10000, 13000, 5000, 0, 9000, 16000, 9000, 6000, 7000, 3000, 4000, 10000,
13000, 5000, 0, 9000, 16000, 9000, 6000, 7000, 3000, 4000, 10000, 13000,
5000, 0, 9000, 16000, 9000, 6000, 7000, 3000, 4000, 10000, 13000, 5000,
0, 9000, 16000, 9000, 6000, 7000, 15000,
],
lineColor: '#2196F3',
scales: 'scale-x, scale-y-2',
},
],
};
zingchart.render({
id: 'myChart',
data: chartConfig,
width: '100%',
});
/**
* As we are moving the guide, we want to update the items outside
* of the chart. We could do this inside the chart, but since JS
* is single threaded we don't want to block UI with a chart
* update. A chart update is more expensive than a node update.
* You may see no performance gains on a dataset this size, but
* with some increase its possible to see a discrepancy for the
* user. This is why I chose to contstruct the items outside
* of the graph.
*/
zingchart.guide_mousemove = (e) => {
if (e['scale-label']) {
document.getElementById('day').innerHTML =
'Day: ' + e['scale-label']['scale-x'];
}
};
/*********** Functions ***********/
/**
* ZingChart defined event listener. Will capture ZoomEvent and related
* Zooming Information.
*/
zingchart.zoom = (e) => {
displayZoomValues(e.kmin, e.kmax);
};
/**
* Apply dates to display current zoomed dates
*/
let displayZoomValues = (sFrom, sTo) => {
let dateFrom = document.getElementById('date-from');
let dateTo = document.getElementById('date-to');
// If viewall is clicked show the default dates
if (!sFrom) {
sFrom = '1/31/19';
}
if (!sTo) {
sTo = '6/17/19';
}
dateFrom.innerHTML = sFrom;
dateTo.innerHTML = sTo;
};
/**
* Apply zoom to graph.
*/
let zoomToIndex = (max) => {
// ZingChart api automated zoom. Have to be careful
// not to zoom past the end of the graph
zingchart.exec('myChart', 'zoomto', {
xmax: max,
xmin: 0,
});
};
/**
* Capture the spans clicks with data-period attribute.
*/
document
.getElementById('date-picker-container')
.addEventListener('click', (e) => {
let target = e.target;
// Only capture spans with data-period attribute
if (target.dataset['period']) {
// Toggle classes
removeActiveClass();
e.target.classList.toggle('active');
switch (target.dataset['period']) {
case '1':
zoomToIndex(30);
break;
case '2':
zoomToIndex(60);
break;
default:
zingchart.exec('myChart', 'viewall');
break;
}
}
});
let removeActiveClass = () => {
let activeElement = document.querySelector('[data-period].active');
activeElement.classList.toggle('active');
};
</script>
</body>
</html>
let chartConfig = {
type: 'mixed',
title: {
text: 'Projected Cash Flow',
align: 'center',
},
plot: {
tooltip: {
visible: false,
},
aspect: 'spline',
marker: {
visible: false,
},
},
plotarea: {},
scaleX: {
values: [
'1/31/19',
'2/10/19',
'2/11/19',
'2/12/19',
'2/13/19',
'2/19/19',
'2/18/19',
'2/19/19',
'2/20/19',
'2/21/19',
'2/24/19',
'2/25/19',
'2/26/19',
'2/27/19',
'2/28/19',
'2/3/19',
'2/4/19',
'2/5/19',
'2/6/19',
'2/7/19',
'3/10/19',
'3/11/19',
'3/12/19',
'3/13/19',
'3/14/19',
'3/17/19',
'3/18/19',
'3/19/19',
'3/20/19',
'3/21/19',
'3/24/19',
'3/25/19',
'3/26/19',
'3/27/19',
'3/28/19',
'3/3/19',
'3/31/19',
'3/4/19',
'3/5/19',
'3/6/19',
'3/7/19',
'4/1/19',
'4/10/19',
'4/11/19',
'4/14/19',
'4/15/19',
'4/16/19',
'4/17/19',
'4/2/19',
'4/21/19',
'4/22/19',
'4/23/19',
'4/24/19',
'4/25/19',
'4/28/19',
'4/29/19',
'4/3/19',
'4/30/19',
'4/4/19',
'4/7/19',
'4/8/19',
'4/9/19',
'5/1/19',
'5/12/19',
'5/13/19',
'5/14/19',
'5/15/19',
'5/16/19',
'5/19/19',
'5/20/19',
'5/21/19',
'5/22/19',
'5/23/19',
'5/27/19',
'5/28/19',
'5/29/19',
'5/30/19',
'5/5/19',
'5/6/19',
'5/7/19',
'5/8/19',
'5/9/19',
'6/10/19',
'6/11/19',
'6/12/19',
'6/13/19',
'6/16/19',
'6/17/19',
],
itemsOverlap: true,
lineWidth: '0px',
tick: {
alpha: 1,
lineColor: '#2196F3',
lineWidth: '2px',
},
zooming: true,
zoomTo: [0, 30],
},
scaleY: {
values: '0:20000:1000',
guide: {
visible: false,
},
},
scaleY2: {},
crosshairX: {
lineColor: '#2196F3',
lineStyle: 'dashed',
lineWidth: '2px',
marker: {
type: 'triangle',
size: '5px',
visible: true,
},
plotLabel: {
visible: false,
},
},
preview: {
live: true,
},
series: [{
type: 'bar',
values: [
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
4000, 10000, 5000, 2000, 6000, 10000, 15000, 8000, 3000, 7000, 13000,
8000, 0, 5000,
],
backgroundColor: '#FFEB3B',
scales: 'scale-x, scale-y-2',
},
{
type: 'line',
values: [
6000, 7000, 3000, 4000, 10000, 13000, 5000, 0, 9000, 16000, 9000, 6000,
7000, 3000, 4000, 10000, 13000, 5000, 0, 9000, 16000, 9000, 6000, 7000,
3000, 4000, 10000, 13000, 5000, 0, 9000, 16000, 9000, 6000, 7000, 3000,
4000, 10000, 13000, 5000, 0, 9000, 16000, 9000, 6000, 7000, 3000, 4000,
10000, 13000, 5000, 0, 9000, 16000, 9000, 6000, 7000, 3000, 4000, 10000,
13000, 5000, 0, 9000, 16000, 9000, 6000, 7000, 3000, 4000, 10000, 13000,
5000, 0, 9000, 16000, 9000, 6000, 7000, 3000, 4000, 10000, 13000, 5000,
0, 9000, 16000, 9000, 6000, 7000, 15000,
],
lineColor: '#2196F3',
scales: 'scale-x, scale-y-2',
},
],
};
zingchart.render({
id: 'myChart',
data: chartConfig,
width: '100%',
});
/**
* As we are moving the guide, we want to update the items outside
* of the chart. We could do this inside the chart, but since JS
* is single threaded we don't want to block UI with a chart
* update. A chart update is more expensive than a node update.
* You may see no performance gains on a dataset this size, but
* with some increase its possible to see a discrepancy for the
* user. This is why I chose to contstruct the items outside
* of the graph.
*/
zingchart.guide_mousemove = (e) => {
if (e['scale-label']) {
document.getElementById('day').innerHTML =
'Day: ' + e['scale-label']['scale-x'];
}
};
/*********** Functions ***********/
/**
* ZingChart defined event listener. Will capture ZoomEvent and related
* Zooming Information.
*/
zingchart.zoom = (e) => {
displayZoomValues(e.kmin, e.kmax);
};
/**
* Apply dates to display current zoomed dates
*/
let displayZoomValues = (sFrom, sTo) => {
let dateFrom = document.getElementById('date-from');
let dateTo = document.getElementById('date-to');
// If viewall is clicked show the default dates
if (!sFrom) {
sFrom = '1/31/19';
}
if (!sTo) {
sTo = '6/17/19';
}
dateFrom.innerHTML = sFrom;
dateTo.innerHTML = sTo;
};
/**
* Apply zoom to graph.
*/
let zoomToIndex = (max) => {
// ZingChart api automated zoom. Have to be careful
// not to zoom past the end of the graph
zingchart.exec('myChart', 'zoomto', {
xmax: max,
xmin: 0,
});
};
/**
* Capture the spans clicks with data-period attribute.
*/
document
.getElementById('date-picker-container')
.addEventListener('click', (e) => {
let target = e.target;
// Only capture spans with data-period attribute
if (target.dataset['period']) {
// Toggle classes
removeActiveClass();
e.target.classList.toggle('active');
switch (target.dataset['period']) {
case '1':
zoomToIndex(30);
break;
case '2':
zoomToIndex(60);
break;
default:
zingchart.exec('myChart', 'viewall');
break;
}
}
});
let removeActiveClass = () => {
let activeElement = document.querySelector('[data-period].active');
activeElement.classList.toggle('active');
};