<!DOCTYPE html>
<!--
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>
            .test-title {
                background: #146402;
                color: #fff;
            }
        </style>


        <div id="main0"></div>


        <script>

            require([
                'echarts'/*, 'map/js/china' */
            ], function (echarts) {

                var data = [[10, 300], [10, 600]];

                var option = {
                    xAxis: {},
                    yAxis: {},
                    tooltip: {
                        position: function (point, params, dom, rect, size) {
                            return [rect.x, rect.y];
                        },
                        extraCssText: 'width: 60px; height: 60px;'
                    },
                    series: [{
                        id: 'scatter',
                        type: 'scatter',
                        symbol: 'rect',
                        symbolSize: 50,
                        emphasis: {
                            itemStyle: {
                                color: 'green'
                            }
                        },
                        data: data
                    }]
                };

                var chart = testHelper.create(echarts, 'main0', {
                    title: [
                        'Tooltip should be event disalbed:',
                        '(1) When hovering on the symbol',
                        'tooltip is shown on the symbol;',
                        'the symbol should keep green, but not return to red.',
                        '(2) Enable moving the symbol without tooltip effection',
                        '(3) click "set tooltip enterable, button in tooltip should be clickable'
                    ],
                    option: option,
                    button: {
                        text: 'set tooltip enterable',
                        onclick: function () {
                            chart.setOption({
                                tooltip: {
                                    formatter: function () {
                                        return [
                                            '<button onclick="console.log(\'click\');">click me</button>'
                                        ].join('');
                                    },
                                    enterable: true
                                }
                            });
                        }
                    }
                });

                if (chart) {
                    var zr = chart.getZr();
                    var pointerOffset;
                    var draggingDataIndex;

                    chart.on('mousedown', function (params) {
                        if (params.seriesIndex === 0) {
                            var pointerData = chart.convertFromPixel(
                                'grid', [params.event.offsetX, params.event.offsetY]
                            );
                            draggingDataIndex = params.dataIndex;
                            pointerOffset = [
                                params.data[0] - pointerData[0],
                                params.data[1] - pointerData[1]
                            ];
                        }
                    });

                    zr.on('mousemove', function (params) {
                        if (draggingDataIndex != null) {
                            var pointerData = chart.convertFromPixel(
                                'grid', [params.event.offsetX, params.event.offsetY]
                            );
                            data[draggingDataIndex] = [
                                pointerData[0] + pointerOffset[0],
                                pointerData[1] + pointerOffset[1]
                            ];
                            chart.setOption({
                                series: {
                                    id: 'scatter',
                                    data: data
                                },
                                animationDurationUpdate: 0
                            });
                        }
                    });

                    zr.on('mouseup', function (params) {
                        draggingDataIndex = null;
                        chart.setOption({
                            animationDurationUpdate: 700
                        });
                    });
                }
            });

        </script>
    </body>
</html>