ZingChart Stock Trends
This demo shows off the interaction between ZingGrid and ZingChart – a charting library and another one of our products.
Click a row to see the full data in the chart.
Result
Full
HTML
CSS
JS
Edit
Download
Full Code
<!DOCTYPE html> <html class="zg-html"> <head> <meta charset="utf-8"> <title>ZingGrid Stock Ticker!!!</title> <script nonce="undefined" src="https://cdn.zinggrid.com/zinggrid.min.js"></script> <style> .zg-html, .zg-body { height: 100%; width: 100%; margin: 0; padding: 0; } .zg-body .component--container { display: flex; } zing-grid { opacity: 1; } zing-grid.loading { opacity: 0; transition: opacity .3s ease-out; } zing-grid.loading * { opacity: 0; } zing-grid, .zg-body #myChart { width: 49%; } .zg-body #myChart { height: 515px; } zg-row:hover { cursor: pointer; } zg-column { min-height: 150px; } @media screen and (max-width:1024px) { .component--container { flex-direction: column; } zing-grid, .zg-body #myChart { width: 100%; } } zing-grid[loading] { height: 538px; } </style> </head> <body class="zg-body"> <script nonce="undefined" src="https://cdn.zingchart.com/zingchart.min.js"></script> <script nonce="undefined"> ZC.LICENSE = ['09c5964a057c3124ffaa293847e9aef4', 'd41d8cd98f00b204e9800998ecf8427e', 'faa38520146223e92b6b0d2fc89c0dc6']; </script> <div class="component--container"> <!-- ZingGrid webcomponent --> <zing-grid caption="ZingGrid Stock Ticker!!!" height="350" layout="row" layout-controls="disabled" viewport-stop pager page-size="5" page-size-option="2,5,10" sort src="https://cdn.zinggrid.com/datasets/company-stock-data-snapshot.json" class="loading"> <zg-colgroup> <zg-column index="Symbol" width=110></zg-column> <zg-column index="Date" width=105></zg-column> <zg-column index="Open" width=110></zg-column> <zg-column index="High" width=110></zg-column> <zg-column index="Low" width=110></zg-column> <zg-column index="Close" width=110></zg-column> <zg-column index="CloseTrends" sort="disabled" renderer="_renderLineChart"> <div class="line-chart--spark"></div> </zg-column> <zg-column index="AverageVolume" sort="disabled" renderer="_renderBarChart"> <div class="bar-chart--spark"></div> </zg-column> <zg-column index="targetExpenditure" width=135></zg-column> <zg-column index="Expenditure.R&D, Expenditure.Marketing, Expenditure.Infrastructure" header="Expenditure" sort="disabled" renderer="_renderPieChart"> <div class="pie-chart--spark"></div> </zg-column> </zg-colgroup> </zing-grid> <!-- ZingChart container --> <div id="myChart"></div> </div> <script> ZC.LICENSE = ["569d52cefae586f634c54f86dc99e6a9", "b55b025e438fa8a98e32482b5f768ff5"]; ZingGrid.setLicense(['26ccbfec16b8be9ee98c7d57bee6e498']); const ZingChartConfig = function(type, series) { return { type, theme: 'spark', tooltip: { visible: type != 'pie' ? false : true, }, crosshairX: {}, series, }; }; function _renderLineChart(ctv, cellRef, $cell) { let zcRef = cellRef.querySelector('.line-chart--spark'); let id = `line-chart-${Math.floor(Math.random() * 99999)}`; zcRef.setAttribute('id', id); let mapValues = ctv.map(function(trend) { return trend.Close; }); // render line chart zingchart.render({ id, data: ZingChartConfig('line', [{ values: mapValues }]), height: 100, width: 150, }); } function _renderBarChart(ctv, cellRef, $cell) { let zcRef = cellRef.querySelector('.bar-chart--spark'); let id = `bar-chart-${Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - 100))}`; zcRef.setAttribute('id', id); let mapValues = ctv.map(function(trend) { return Math.floor(trend.AverageVolume); }); // render chart zingchart.render({ id, data: ZingChartConfig('bar', [{ values: mapValues }]), height: 100, width: 150, }); } function _renderPieChart(rd, marketing, infrastructure, cellRef, $cell) { let zcRef = cellRef.querySelector('.pie-chart--spark'); let id = `pie-chart-${Math.floor(Math.random() * 99999)}`; zcRef.setAttribute('id', id); // render chart zingchart.render({ id, data: ZingChartConfig('pie', [{ text: 'R&D', values: [rd] }, { text: 'Infrastructure', values: [infrastructure] }, { text: 'Marketing', values: [marketing] }]), height: 100, width: 150, }); } function ChartConfig(title, timeSeries) { return { type: 'line', title: { text: title || 'Company N/A' }, noData: { text: 'Please Click a Grid Row', fontSize: 20, }, crosshairX: { plotLabel: { padding: 10, borderRadius: 5, text: '%kt<br>Value:<b>%v</b>' } }, scaleX: { zooming: true, transform: { type: 'date', item: { visible: true } } }, preview: {}, series: [{ values: timeSeries || [] }] }; } // parse a date from day-month-year e.g) 15-Apr-16 // to be 15-3-16 returned in milliseconds function parseDate(input) { const parts = input.split('-'); const monthShortNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', ]; // get month index const monthInt = monthShortNames.findIndex(m => m == parts[1]); // return new date in milliseconds y/m/d return new Date(20 + parts[2], monthInt, parts[0]).getTime(); } function renderNewStockData(e) { let symbol = e.detail.ZGData.data.Symbol; let title = e.detail.ZGData.data.Symbol; let uri = `https://cdn.zinggrid.com/datasets/${symbol}-stock-data.json`; // fetch data fetch(uri) .then(res => res.json()) .then(stockData => { const mapValues = stockData.map((point) => [parseDate(point.Date), point.Close]); // re-render chart for simplicity zingchart.exec('myChart', 'setdata', { data: ChartConfig(title, mapValues) }); }); } window.addEventListener('load', () => { let zgRef = document.querySelector('zing-grid'); // render initial main chart zingchart.render({ id: 'myChart', height: '100%', width: '100%', data: ChartConfig(), // empty chartconfig }); // on record/row click, display chart zgRef.addEventListener('record:click', renderNewStockData); zgRef.executeOnLoad(() => { zgRef.updateSize(); }); }); // Custom loading class for CSS handling const zgLoaded = document.querySelector('zing-grid'); zgLoaded.addEventListener('grid:ready', () => { setTimeout(() => zgLoaded.classList.remove('loading'), 0); }); </script> </body> </html>
<!DOCTYPE html> <html class="zg-html"> <head> <meta charset="utf-8"> <title>ZingGrid Stock Ticker!!!</title> <script src="https://cdn.zinggrid.com/zinggrid.min.js"></script> </head> <body class="zg-body"> <script src="https://cdn.zingchart.com/zingchart.min.js"></script> <script>ZC.LICENSE = ['09c5964a057c3124ffaa293847e9aef4','d41d8cd98f00b204e9800998ecf8427e', 'faa38520146223e92b6b0d2fc89c0dc6'];</script> <div class="component--container"> <!-- ZingGrid webcomponent --> <zing-grid caption="ZingGrid Stock Ticker!!!" height="350" layout="row" layout-controls="disabled" viewport-stop pager page-size="5" page-size-option="2,5,10" sort src="https://cdn.zinggrid.com/datasets/company-stock-data-snapshot.json" class="loading" > <zg-colgroup> <zg-column index="Symbol" width=110></zg-column> <zg-column index="Date" width=105></zg-column> <zg-column index="Open" width=110></zg-column> <zg-column index="High" width=110></zg-column> <zg-column index="Low" width=110></zg-column> <zg-column index="Close" width=110></zg-column> <zg-column index="CloseTrends" sort="disabled" renderer="_renderLineChart"> <div class="line-chart--spark"></div> </zg-column> <zg-column index="AverageVolume" sort="disabled" renderer="_renderBarChart"> <div class="bar-chart--spark"></div> </zg-column> <zg-column index="targetExpenditure" width=135></zg-column> <zg-column index="Expenditure.R&D, Expenditure.Marketing, Expenditure.Infrastructure" header="Expenditure" sort="disabled" renderer="_renderPieChart"> <div class="pie-chart--spark"></div> </zg-column> </zg-colgroup> </zing-grid> <!-- ZingChart container --> <div id="myChart"></div> </div> </body> </html>
.zg-html, .zg-body { height: 100%; width: 100%; margin: 0; padding: 0; } .zg-body .component--container { display: flex; } zing-grid { opacity: 1; } zing-grid.loading { opacity:0; transition:opacity .3s ease-out; } zing-grid.loading * { opacity:0; } zing-grid, .zg-body #myChart { width:49%; } .zg-body #myChart { height: 515px; } zg-row:hover { cursor:pointer; } zg-column { min-height: 150px; } @media screen and (max-width:1024px) { .component--container { flex-direction:column; } zing-grid, .zg-body #myChart { width:100%; } }
const ZingChartConfig = function (type, series) { return { type, theme: 'spark', tooltip: { visible: type != 'pie' ? false : true, }, crosshairX: {}, series, }; }; function _renderLineChart(ctv, cellRef, $cell) { let zcRef = cellRef.querySelector('.line-chart--spark'); let id = `line-chart-${Math.floor(Math.random() * 99999)}`; zcRef.setAttribute('id', id); let mapValues = ctv.map(function (trend) { return trend.Close; }); // render line chart zingchart.render({ id, data: ZingChartConfig('line', [{ values: mapValues }]), height: 100, width: 150, }); } function _renderBarChart(ctv, cellRef, $cell) { let zcRef = cellRef.querySelector('.bar-chart--spark'); let id = `bar-chart-${Math.floor(Math.random() * (Number.MAX_SAFE_INTEGER - 100))}`; zcRef.setAttribute('id', id); let mapValues = ctv.map(function (trend) { return Math.floor(trend.AverageVolume); }); // render chart zingchart.render({ id, data: ZingChartConfig('bar', [{ values: mapValues }]), height: 100, width: 150, }); } function _renderPieChart(rd, marketing, infrastructure, cellRef, $cell) { let zcRef = cellRef.querySelector('.pie-chart--spark'); let id = `pie-chart-${Math.floor(Math.random() * 99999)}`; zcRef.setAttribute('id', id); // render chart zingchart.render({ id, data: ZingChartConfig('pie', [{ text: 'R&D', values: [rd] }, { text: 'Infrastructure', values: [infrastructure] }, { text: 'Marketing', values: [marketing] }]), height: 100, width: 150, }); } function ChartConfig(title, timeSeries) { return { type: 'line', title: { text: title || 'Company N/A' }, noData: { text: 'Please Click a Grid Row', fontSize: 20, }, crosshairX: { plotLabel: { padding: 10, borderRadius: 5, text: '%kt<br>Value:<b>%v</b>' } }, scaleX: { zooming: true, transform: { type: 'date', item: { visible: true } } }, preview: {}, series: [ { values: timeSeries || [] } ] }; } // parse a date from day-month-year e.g) 15-Apr-16 // to be 15-3-16 returned in milliseconds function parseDate(input) { const parts = input.split('-'); const monthShortNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec',]; // get month index const monthInt = monthShortNames.findIndex(m => m == parts[1]); // return new date in milliseconds y/m/d return new Date(20 + parts[2], monthInt, parts[0]).getTime(); } function renderNewStockData(e) { let symbol = e.detail.ZGData.data.Symbol; let title = e.detail.ZGData.data.Symbol; let uri = `https://cdn.zinggrid.com/datasets/${symbol}-stock-data.json`; // fetch data fetch(uri) .then(res => res.json()) .then(stockData => { const mapValues = stockData.map((point) => [parseDate(point.Date), point.Close]); // re-render chart for simplicity zingchart.exec('myChart', 'setdata', { data: ChartConfig(title, mapValues) }); }); } window.addEventListener('load', () => { let zgRef = document.querySelector('zing-grid'); // render initial main chart zingchart.render({ id: 'myChart', height: '100%', width: '100%', data: ChartConfig(), // empty chartconfig }); // on record/row click, display chart zgRef.addEventListener('record:click', renderNewStockData); zgRef.executeOnLoad(() => { zgRef.updateSize(); }); }); // Custom loading class for CSS handling const zgLoaded = document.querySelector('zing-grid'); zgLoaded.addEventListener('grid:ready', () => { setTimeout(() => zgLoaded.classList.remove('loading'), 0); });
Interested in this demo? Modify it to your needs in ZingSoft Studio, our testing sandbox. It's free to sign up, and you can come back and edit at any time!