Demos Back to Demos

ZingChart Stock Trends

8 of 25

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 HTML CSS JS
Edit Download

Result

HTML

<!DOCTYPE html>
<html>
	<head>
    <meta charset="utf-8">
    <title>ZingGrid Stock Ticker!!!</title>
    <script src="https://cdn.zinggrid.com/zinggrid.min.js" defer></script>
  	<script src="https://cdn.zingchart.com/zingchart.min.js"></script>
    <script>ZC.LICENSE = ['09c5964a057c3124ffaa293847e9aef4','d41d8cd98f00b204e9800998ecf8427e', 'faa38520146223e92b6b0d2fc89c0dc6'];</script>
  </head>
	<body>
    <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">
      	<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>

CSS

html, body {
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 0;
}

.component--container {
  display: flex;
}

zing-grid,
#myChart {
  width:49%;
}

#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,
	#myChart {
  	width:100%;
	}
}

JS

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: '%ktValue:%v'
      }
    },
    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();
  });
});

Interested in this demo? Modify it to your needs in the ZingSoft Studio, our testing sandbox. It's free to sign up, and you can come back and edit at any time!

Edit in Studio