<!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 lang="EN">
<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>
    <!-- <script src="ut/lib/canteen.js"></script> -->
    <link rel="stylesheet" href="lib/reset.css" />
</head>
<body>
<style>
    body {
        background: #eee;
        margin: 0;
        text-align: center;
    }
    #container {
        box-sizing: border-box;
        margin: 0 auto;
        width: 800px;
        max-width: 100%;
        text-align: center;
    }
    .chart {
        width: 100%;
        height: 300px;

        border-radius: 5px;
        margin: 20px 0;
        box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
        background: #fff;
    }
</style>

<div id="container">
    <div id="main2" class="chart"></div>
    <div id="main1" class="chart"></div>
    <div id="main3" class="chart"></div>
    <div id="main4" class="chart"></div>
    <div id="main-FI" class="chart"></div>
    <div id="main-DE" class="chart"></div>
    <div id="main-FR" class="chart"></div>
    <div id="main-JA" class="chart"></div>
    <div id="main-TH" class="chart"></div>
</div>

<script>
    var base = +new Date(2010, 9, 3);
    var oneDay = 24 * 3600 * 1000;

    var data = [[base, Math.random() * 300]];

    for (var i = 1; i < 2000; i++) {
        var now = new Date(base += oneDay);
        data.push([
            [now.getFullYear(), now.getMonth() + 1, now.getDate()].join('/'),
            Math.round((Math.random() - 0.5) * 20 + data[i - 1][1])
        ]);
    }

    window.option = {
        tooltip: {
            trigger: 'axis',
            position: function (pt) {
                return [pt[0], '10%'];
            }
        },
        toolbox: {
            show: true,
            feature: {
                restore: {},
                saveAsImage: {},
                dataZoom: {},
                dataView: {},
                brush: ['rect']
            },
            orient: 'vertical',
            right: 5
        },
        legend: {
            selector: true
        },
        xAxis: {
            type: 'time',
            boundaryGap: false
        },
        yAxis: {
            type: 'value',
            boundaryGap: [0, '100%']
        },
        dataZoom: [{
            type: 'inside',
            start: 0,
            end: 20
        }, {
            start: 0,
            end: 20,
            height: 25,
            bottom: 10
        }],
        series: [
            {
                type: 'line',
                smooth: true,
                symbol: 'none',
                areaStyle: {},
                data: data
            }
        ]
    };
</script>

<script>
    // auto with default
    require(['echarts'], function (echarts) {
        var chart = echarts.init(document.getElementById('main2'), null);
        chart.setOption(window.option);
    });
</script>

<script>
    // lang object
    require(['echarts', 'i18n/langEN-obj'], function (echarts, lang) {
        echarts.registerLocale('EN', lang);
        var chart = echarts.init(document.getElementById('main1'), null, {
            locale: lang
        });
        chart.setOption(window.option);
    });
</script>

<script>
    // Modified lang
    require(['echarts', 'i18n/langZH-obj'], function (echarts, lang) {
        echarts.registerLocale('ZH-mod', lang);
        lang.legend.selector.inverse = '反選';
        lang.legend.selector.all = '全選';
        var chart = echarts.init(document.getElementById('main4'), null, {
            locale: 'ZH-mod'
        });
        chart.setOption(window.option);
    });
</script>

<script>
    // register neither zh or en lang
    require(['echarts', 'i18n/langES-obj'], function (echarts, lang) {
        echarts.registerLocale('ES', lang);
        var chart = echarts.init(document.getElementById('main3'), null, {
            locale: 'ES'
        });
        chart.setOption(window.option);
    });
</script>


<script>
    require(['echarts', 'i18n/langFI'], function (echarts) {
        var chart = echarts.init(document.getElementById('main-FI'), null, {
            locale: 'FI'
        });
        chart.setOption(window.option);
    });
</script>

<script>
    require(['echarts', 'i18n/langDE'], function (echarts) {
        var chart = echarts.init(document.getElementById('main-DE'), null, {
            locale: 'DE'
        });
        chart.setOption(window.option);
    });
</script>

<script>
    require(['echarts', 'i18n/langFR'], function (echarts) {
        var chart = echarts.init(document.getElementById('main-FR'), null, {
            locale: 'FR'
        });
        chart.setOption(window.option);
    });
</script>

<script>
    require(['echarts', 'i18n/langJA'], function (echarts) {
        var chart = echarts.init(document.getElementById('main-JA'), null, {
            locale: 'JA'
        });
        chart.setOption(window.option);
    });
</script>

<script>
    require(['echarts', 'i18n/langTH'], function (echarts) {
        var chart = echarts.init(document.getElementById('main-TH'), null, {
            locale: 'TH'
        });
        chart.setOption(window.option);
    });
</script>

</body>
</html>

