
<!--
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>
        <script src="lib/testHelper.js"></script>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    </head>
    <body>
        <style>
            html, body, #main {
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }
            .controller {
                position: fixed;
                top: 0;
                left: 0;
                right: 0;
                background: #fff;
                border-bottom: 1px solid #ccc;
                line-height: 30px;
                z-index: 100;
            }
            .controller label {
                margin-right: 10px;
            }
            .item-title {
                font-weight: bold;
            }
            .controller .item {
                margin-right: 20px;
                padding-right: 10px;
                border-right: 1px solid #ccc;
            }
            .tooltip-title {
                color: yellow;
                font-size: 16px;
                margin-bottom: 5px;
            }
            #btn-area {
                position: fixed;
                left: 10px;
                top: 10px;
                z-index: 999999;
                background-color: #fff;
            }
        </style>

        <div id="btn-area">
        </div>

        <div id="main"></div>

        <script src="data/disk.tree.js"></script>

        <script>

            var chart;
            var formatUtil;

            require([
                'echarts'
                // 'echarts/util/format',
                // 'echarts/component/tooltip',
                // 'echarts/component/legend',
                // 'echarts/chart/treemap'
            ], function (echarts) {
                formatUtil = echarts.format;
                initEcharts(echarts);
            });

            function initEcharts(echarts) {
                chart = echarts.init(document.getElementById('main'), null, {

                });

                chart.setOption({

                    tooltip: {
                        formatter: function (info) {
                            var value = info.value;
                            var treePathInfo = info.treePathInfo;
                            var treePath = [];

                            for (var i = 1; i < treePathInfo.length; i++) {
                                treePath.push(treePathInfo[i].name);
                            }

                            return [
                                '<div class="tooltip-title">' + formatUtil.encodeHTML(treePath.join('/')) + '</div>',
                                'Disk Usage: ' + formatUtil.addCommas(value) + ' KB',
                            ].join('');
                        }
                    },

                    series: [
                        {
                            name:'Disk Usage',
                            type:'treemap',
                            visibleMin: 300,
                            upperLabel: {
                                normal: {
                                    show: true,
                                    height: 30,
                                    color: 'green'
                                }
                            },
                            itemStyle: {
                                normal: {
                                    // borderColor: '#fff'
                                },
                                emphasis: {
                                    strokeColor: 'yellow',
                                    strokeWidth: 2
                                }
                            },
                            levels: [
                                {
                                    color: ['#d14a61'], // default color
                                    itemStyle: {
                                        normal: {
                                            borderWidth: 5,
                                            gapWidth: 3
                                        },
                                        emphasis: {
                                            borderColor: 'red'
                                        }
                                    },
                                },
                                {
                                    color: [
                                        '#d14a61', '#fd9c35',
                                        '#675bba', '#fec42c', '#dd4444',
                                        '#d4df5a', '#cd4870'
                                    ],
                                    highDownTarget: 'subtree',
                                    colorMappingBy: 'value',
                                    itemStyle: {
                                        normal: {
                                            borderColor: '#aaa',
                                            borderWidth: 5,
                                            gapWidth: 3
                                        },
                                        emphasis: {
                                            borderColor: 'red'
                                        }
                                    }
                                },
                                {
                                    colorSaturation: [0.35, 0.5],
                                    itemStyle: {
                                        normal: {
                                            borderWidth: 5,
                                            gapWidth: 3,
                                            borderColorSaturation: 0.6
                                        }
                                    }
                                }
                            ],
                            data: window.disk_usage_tree
                        }
                    ]
                });

                chart.on('click', function (params) {
                    console.log(params);
                });

                initBtns('Only single bg highlighted for non-leaf', [
                    'Disk Usage',
                    'PrivateFrameworks'
                ]);
                initBtns('Both of the bg and content is highlighted for leaf', [
                    'Alex.SpeechVoice'
                ]);

                function initBtns(desc, names) {
                    var btnArea = document.getElementById('btn-area');

                    var descEl = document.createElement('span');
                    descEl.innerHTML = testHelper.encodeHTML(desc) + '&nbsp;:&nbsp;&nbsp;';
                    btnArea.appendChild(descEl);

                    var highDown = ['highlight', 'downplay'];

                    for (var i = 0; i < names.length; i++) {
                        for (var j = 0; j < highDown.length; j++) {
                            var highDownName = highDown[j];
                            var name = names[i];
                            var btnEl = document.createElement('button');
                            btnEl.innerHTML = testHelper.encodeHTML(highDownName + ': ' + name);
                            btnEl.onclick = echarts.util.curry(clickHandler, highDownName, name);
                            btnArea.appendChild(btnEl);
                        }
                    }

                    function clickHandler(highDownName, name) {
                        chart.dispatchAction({
                            type: highDownName,
                            seriesIndex: 0,
                            name: name
                        });
                    }

                    btnArea.appendChild(document.createElement('br'));
                }
            }

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