
<!--
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/esl.js"></script>
        <script src="lib/config.js"></script>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <link rel="stylesheet" href="lib/reset.css" />
        <script src="lib/testHelper.js"></script>
        <script src="tooltipTestHelper.js"></script>
    </head>
    <body>
        <style>
            h1 {
                line-height: 60px;
                height: 60px;
                background: #ddd;
                text-align: center;
                font-weight: bold;
                font-size: 14px;
            }
            .chart {
                height: 350px;
            }
        </style>


        <h1>dynamic data update tooltip content and keep show</h1>
        <div><a target="_blank" href="dynamicData.html">dynamicData.html</a></div>
        <div><a target="_blank" href="dynamicData2.html">dynamicData2.html</a></div>
        <div><a target="_blank" href="dynamicData3.html">dynamicData3.html</a></div>
        <h1>triggerOn: click, setOption when trigger axis (keep show)</h1>
        <div class="chart" id="click-setOption1"></div>


        <h1>tooltip should auto show and auto disappear when setOption(..., {notMerge: true})</h1>
        <div class="chart" id="setOption2"></div>
        <div class="chart" id="setOption3" style="height: 550px"></div>


























        <script>

            require([
                'echarts'
                // 'echarts/chart/line',
                // 'echarts/component/legend',
                // 'echarts/component/grid',
                // 'echarts/component/tooltip',
                // 'zrender/vml/vml'
            ], function (echarts) {

                var option = {
                    tooltip: {
                        trigger: 'axis',
                        triggerOn: 'click',
                        enterable: true,
                        axisPointer: {
                            type: 'cross'
                        },
                        formatter: function () {
                            return '<button onclick="console.log(\'click\');window.ecClickSetOptionAxisChart.setOption({tooltip: {}});">click me</button>';
                        }
                    }
                };
                var baseTop = 90;
                var height = 150;
                var gap = 50;
                makeCategoryGrid(option, {
                    grid: {top: baseTop, height: height},
                    yAxis: {
                        name: 'click show tip',
                        tooltip: {
                            show: true
                        }
                    }
                });
                baseTop += height + gap;

                var chart = createChart('click-setOption1', echarts, option, baseTop);
                window.ecClickSetOptionAxisChart = chart;
            })
        </script>




        <script>
            require([
                'echarts'
            ], function (echarts) {

                function genOption() {
                    return {
                        tooltip: {
                            trigger: 'axis',
                            axisPointer: {
                                type: 'cross'
                            }
                        },
                        xAxis: {},
                        yAxis: {},
                        series: [{
                            type: 'scatter',
                            data: [
                                [Math.random(), Math.random() * 100],
                                [Math.random(), Math.random() * 100],
                                [Math.random(), Math.random() * 100]
                            ]
                        }]
                    };
                }

                var chart = echarts.init(document.getElementById('setOption2'));
                chart.setOption(genOption());

                setTimeout(function () {
                    chart.dispatchAction({
                        type: 'showTip',
                        seriesIndex: 0,
                        dataIndex: 0
                    });

                    setTimeout(function () {

                        // chart.clear();
                        chart.dispose();

                        chart = echarts.init(document.getElementById('setOption2'));

                        chart.setOption(genOption());
                    }, 2000)
                }, 100);

            });
        </script>







        <script>
            require(['echarts'], function (echarts) {
                var colors = ['red', 'blue'];
                var option = {
                    color: colors,
                    "tooltip": {
                        "show": true
                    },
                    "xAxis": {
                        "type": "category",
                        "data": ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
                    },
                    "yAxis": {
                    },
                    "series": [{
                        "data": [820, 932, 901, 934, 1290, 1330, 1320],
                        "type": 'bar'
                    }, {
                        "data": [620, 532, 501, 734, 1090, 1130, 1220],
                        "type": 'bar'
                    }]
                };

                var myChart = testHelper.create(echarts, 'setOption3', {
                    title: 'Click the blue bar, should no error throw',
                    option: option
                });

                myChart.on('click', function (params) {
                    myChart.clear();
                    myChart.setOption({
                        "tooltip": {
                            "show": true
                        },
                        "xAxis": {
                            "type": "category",
                            "data": ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
                        },
                        "yAxis": {
                        },
                        "series": [{
                            "data": [820, 932, 901, 934, 1290, 1330, 1320],
                            "type": 'bar'
                        }]
                    });
                });
            });

        </script>


    </body>
</html>