
<!--
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">
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <script src="lib/simpleRequire.js"></script>
        <script src="lib/config.js"></script>
        <script src="lib/jquery.min.js"></script>
        <script src="lib/facePrint.js"></script>
        <script src="lib/testHelper.js"></script>
        <link rel="stylesheet" href="lib/reset.css" />
    </head>
    <body>
        <style>
            .chart {
                height: 400px;
            }
        </style>

        <div id="chart-1" class="chart"></div>
        <div id="main1"></div>


        <script>

            require([
                'echarts'
            ], function (echarts) {

                var chart = echarts.init(document.getElementById('chart-1'));

                var xCnt = 500;
                var data = [];
                var xAxis = [];
                for (var i = 0; i < xCnt; ++i) {
                    data.push(
                        Math.round(Math.random() * 100 * i) / 100
                            * (Math.random() < 0.6 ? 1 : -1)
                    );
                    xAxis.push((i + 1) + '');
                }

                chart.setOption({
                    dataZoom: [{
                        type: 'inside',
                        startValue: '20',
                        endValue: '50'
                    }, {
                        type: 'slider',
                        startValue: '20',
                        endValue: '50'
                    }],
                    toolbox: {
                        show: true,
                        feature: {
                            dataZoom: {
                                show: true
                            },
                            restore: {
                                show: true
                            }
                        }
                    },
                    tooltip: {
                        show: true
                    },
                    xAxis: {
                        data: xAxis
                    },
                    yAxis: {
                        min: function (value) {
                            return value.min - 20;
                        },
                        max: function (value) {
                            return value.max + 20;
                        }
                    },
                    series: [{
                        type: 'bar',
                        data: data,
                        markPoint: {
                            symbol: 'pin',
                            label: {
                                normal: {
                                    show: true
                                }
                            },
                            itemStyle: {
                                normal: {
                                    color: 'green'
                                }
                            },
                            data: [{
                                name: 'max',
                                type: 'max'
                            }, {
                                name: 'min',
                                type: 'min'
                            }]
                        }
                    }]
                });
            });
        </script>




        <script>

            require([
                'echarts'
            ], function (echarts) {
                function xAxisData() { return ['a', 'b', 'c']; };
                function seriesData() { return [12, 32, 44]; };
                var gridWidth = 100;
                var gridBottom = 80;
                var gridGap = 50;
                var gridCurrLeft = gridGap;
                var nameTextStyle = {align: 'left'};

                function getGridLeft() {
                    var left = gridCurrLeft;
                    gridCurrLeft += gridWidth + gridGap;
                    return left;
                }

                var option = {
                    dataZoom: [
                        {type: 'inside', yAxisIndex: 1},
                        {type: 'inside', yAxisIndex: 3}
                    ],
                    grid: [
                        {width: gridWidth, bottom: gridBottom, left: getGridLeft()},
                        {width: gridWidth, bottom: gridBottom, left: getGridLeft()},
                        {width: gridWidth, bottom: gridBottom, left: getGridLeft()},
                        {width: gridWidth, bottom: gridBottom, left: getGridLeft()}
                    ],
                    xAxis: [
                        {gridIndex: 0, data: xAxisData()},
                        {gridIndex: 1, data: xAxisData()},
                        {gridIndex: 2, data: xAxisData()},
                        {gridIndex: 3, data: xAxisData()}
                    ],
                    yAxis: [{
                        gridIndex: 0,
                        name: 'y min/max:\nfunction return null\nno dataZoom',
                        nameTextStyle: nameTextStyle,
                        min: function (param) {
                            return null;
                        },
                        max: function (param) {
                            return null;
                        }
                    }, {
                        gridIndex: 1,
                        name: 'y min/max:\nfunction return null\ny inside dataZoom',
                        nameTextStyle: nameTextStyle,
                        min: function (param) {
                            return null;
                        },
                        max: function (param) {
                            return null;
                        }
                    }, {
                        gridIndex: 2,
                        name: 'y min/max:\nnull\nno dataZoom',
                        nameTextStyle: nameTextStyle,
                        min: null,
                        max: null
                    }, {
                        gridIndex: 3,
                        name: 'y min/max:\nnull\ny inside dataZoom',
                        nameTextStyle: nameTextStyle,
                        min: null,
                        max: null
                    }],
                    series: [
                        {type: 'scatter', data: seriesData(), xAxisIndex: 0, yAxisIndex: 0},
                        {type: 'scatter', data: seriesData(), xAxisIndex: 1, yAxisIndex: 1},
                        {type: 'scatter', data: seriesData(), xAxisIndex: 2, yAxisIndex: 2},
                        {type: 'scatter', data: seriesData(), xAxisIndex: 3, yAxisIndex: 3},
                    ]
                };

                var chart = testHelper.create(echarts, 'main1', {
                    title: [
                        'Y range should be all the same',
                        'dataZoom should be normal'
                    ],
                    option: option
                });

            });

        </script>



    </body>
</html>