
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<html>
    <head>
        <meta charset="utf-8">
        <script src="lib/simpleRequire.js"></script>
        <script src="lib/config.js"></script>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    </head>
    <body>
        <style>
            html, body, #main {
                width: 100%;
                height: 100%;
                margin: 0;
            }
        </style>
        <div id="timing"></div>
        <script>

            require([
                'echarts'
            ], function (echarts) {
                var myChart;
                var lineCount = 20;
                var pointCount = 10000;
                var chartCount = 20;

                var option = {
                    tooltip : {
                        trigger: 'axis',
                        axisPointer: {
                            animation: false
                        }
                    },
                    legend: {
                        data:[]
                    },
                    dataZoom: [{
                        show: true,
                        realtime: true,
                        // showDataShadow: false,
                        start: 10,
                        end: 60
                    }],
                    xAxis : [
                        {
                            type : 'time'
                        }
                    ],
                    yAxis : [
                        {
                            type : 'value'
                        }
                    ],
                    series: [],
                    animation: false
                };

                var lineStyle = {
                    normal: {
                        width: 2,
                        opacity: 1
                    }
                };

                var date = new Float64Array(pointCount)
                var oneDay = 24 * 3600 * 1000;
                var base = +new Date(1987, 9, 3);
                for (var j = 0; j < pointCount; j++) {
                    date[j] = base += oneDay;
                }
                for (var i = 0; i < lineCount; i++) {
                    var y = Math.random() * 1000;
                    var values = new Float64Array(pointCount * 2);
                    var off = 0;
                    for (var j = 0; j < pointCount; j++) {
                        y += Math.round(10 + Math.random() * (-10 - 10));
                        values[off++] = date[j];
                        values[off++] = y;
                    }

                  option.legend.data.push( 'line' + i );
                  option.series.push({
                    name: 'line' + i,
                    type: 'line',
                    hoverAnimation: false,
                    showSymbol: false,
                    dimensions: ['date', 'value'],
                    encode: {
                        x: 'date',
                        y: 'value'
                    },
                    data: values,
                    lineStyle: lineStyle
                  });
                }

                function refresh(isBtnRefresh){
                    var start = new Date();
                    console.profile('render');
                    for( var n = 0; n < chartCount; n++ ) {
                        var el = document.createElement('div');
                      el.innerHTML = '<h1>'+n+'</h1><div id="chart'+n+'" style="width: 860px; height: 320px"></div>';
                      document.body.appendChild(el);

                      myChart = echarts.init(document.getElementById('chart'+n));
                      myChart.setOption(option, true);
                    }
                    console.profileEnd('render');
                    setTimeout(function () {
                        var end = new Date();
                        document.getElementById('timing').innerHTML = 'Graphs loaded in ' + ( end - start ) + ' ms.';
                    });
                };

                refresh();
            });
        </script>
    </body>
</html>