<!DOCTYPE html>
<html>
<head>
    <title>Speedtest</title>
    <style type="text/css">
        html,
        body {
            margin: 0;
            padding: 0;
            border: none;
            text-align: center;
        }

        #startBtn {
            display: inline-block;
            border: 0.15em solid #000000;
            padding: 0.3em 0.5em;
            margin: 0.6em;
            color: #000000;
            text-decoration: none;
        }

        #ip {
            margin: 0.8em 0;
            font-size: 1.2em;
        }

        #chart1Area,
        #chart2Area {
            width: 100%;
            max-width: 30em;
            height: 10em;
            display: block;
            margin: 0 auto;
        }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js"></script>
    <script type="text/javascript">
        var w = null
        function runTest() {
            var chart1ctx = document.getElementById('chart1Area').getContext('2d')
            var chart2ctx = document.getElementById('chart2Area').getContext('2d')
            var dlDataset = {
                label: 'Download',
                fill: false,
                lineTension: 0.1,
                backgroundColor: 'rgba(75,192,192,0.4)',
                borderColor: 'rgba(75,192,192,1)',
                borderCapStyle: 'butt',
                borderDash: [],
                borderDashOffset: 0.0,
                borderJoinStyle: 'miter',
                pointBorderColor: 'rgba(75,192,192,1)',
                pointBackgroundColor: '#fff',
                pointBorderWidth: 1,
                pointHoverRadius: 5,
                pointHoverBackgroundColor: 'rgba(75,192,192,1)',
                pointHoverBorderColor: 'rgba(220,220,220,1)',
                pointHoverBorderWidth: 2,
                pointRadius: 1,
                pointHitRadius: 10,
                data: [0],
                spanGaps: false
            }
            var ulDataset = {
                label: 'Upload',
                fill: false,
                lineTension: 0.1,
                backgroundColor: 'rgba(192,192,75,0.4)',
                borderColor: 'rgba(192,192,75,1)',
                borderCapStyle: 'butt',
                borderDash: [],
                borderDashOffset: 0.0,
                borderJoinStyle: 'miter',
                pointBorderColor: 'rgba(192,192,75,1)',
                pointBackgroundColor: '#fff',
                pointBorderWidth: 1,
                pointHoverRadius: 5,
                pointHoverBackgroundColor: 'rgba(192,192,75,1)',
                pointHoverBorderColor: 'rgba(220,220,220,1)',
                pointHoverBorderWidth: 2,
                pointRadius: 1,
                pointHitRadius: 10,
                data: [0],
                spanGaps: false
            }
            var pingDataset = {
                label: 'Ping',
                fill: false,
                lineTension: 0.1,
                backgroundColor: 'rgba(75,220,75,0.4)',
                borderColor: 'rgba(75,220,75,1)',
                borderCapStyle: 'butt',
                borderDash: [],
                borderDashOffset: 0.0,
                borderJoinStyle: 'miter',
                pointBorderColor: 'rgba(75,220,75,1)',
                pointBackgroundColor: '#fff',
                pointBorderWidth: 1,
                pointHoverRadius: 5,
                pointHoverBackgroundColor: 'rgba(75,220,75,1)',
                pointHoverBorderColor: 'rgba(220,220,220,1)',
                pointHoverBorderWidth: 2,
                pointRadius: 1,
                pointHitRadius: 10,
                data: [],
                spanGaps: false
            }
            var jitterDataset = {
                label: 'Jitter',
                fill: false,
                lineTension: 0.1,
                backgroundColor: 'rgba(220,75,75,0.4)',
                borderColor: 'rgba(220,75,75,1)',
                borderCapStyle: 'butt',
                borderDash: [],
                borderDashOffset: 0.0,
                borderJoinStyle: 'miter',
                pointBorderColor: 'rgba(220,75,75,1)',
                pointBackgroundColor: '#fff',
                pointBorderWidth: 1,
                pointHoverRadius: 5,
                pointHoverBackgroundColor: 'rgba(220,75,75,1)',
                pointHoverBorderColor: 'rgba(220,220,220,1)',
                pointHoverBorderWidth: 2,
                pointRadius: 1,
                pointHitRadius: 10,
                data: [],
                spanGaps: false
            }

            var chart1Options = {
                type: 'line',
                data: {
                    datasets: [dlDataset, ulDataset]
                },
                options: {
                    responsive: true,
                    legend: {
                        position: 'bottom'
                    },
                    scales: {
                        xAxes: [{
                            display: true,
                            scaleLabel: {
                                display: false
                            },
                            ticks: {
                                beginAtZero: true
                            }
                        }],
                        yAxes: [{
                            display: true,
                            scaleLabel: 'Speed',
                            ticks: {
                                beginAtZero: true
                            }
                        }]
                    }
                }
            }
            var chart2Options = {
                type: 'line',
                data: {
                    datasets: [pingDataset, jitterDataset]
                },
                options: {
                    responsive: true,
                    legend: {
                        position: 'bottom'
                    },
                    scales: {
                        xAxes: [{
                            display: true,
                            scaleLabel: {
                                display: false
                            },
                            ticks: {
                                beginAtZero: true
                            }
                        }],
                        yAxes: [{
                            display: true,
                            scaleLabel: 'Latency',
                            ticks: {
                                beginAtZero: true
                            }
                        }]
                    }
                }
            }

            var chart1 = new Chart(chart1ctx, chart1Options)
            var chart2 = new Chart(chart2ctx, chart2Options)

            document.getElementById('startBtn').style.display = 'none'
            document.getElementById('testArea').style.display = ''
            document.getElementById('abortBtn').style.display = ''
            w = new Worker('speedtest_worker.min.js')
            var interval = setInterval(function () { w.postMessage('status') }, 100)
            w.onmessage = function (event) {
                var data = event.data.split(';')
                var status = Number(data[0])
                if (status >= 4) {
                    clearInterval(interval)
                    document.getElementById('abortBtn').style.display = 'none'
                    document.getElementById('startBtn').style.display = ''
                    w = null
                }
                if (status === 5) {
                    document.getElementById('testArea').style.display = 'none'
                }
                if (status === 1 && Number(data[1]) > 0) {
                    chart1.data.datasets[0].data.push(Number(data[1]))
                    chart1.data.labels[chart1.data.datasets[0].data.length - 1] = ''
                    chart1.update()
                }
                if (status === 3 && Number(data[2]) > 0) {
                    chart1.data.datasets[1].data.push(Number(data[2]))
                    chart1.data.labels[chart1.data.datasets[1].data.length - 1] = ''
                    chart1.update()
                }
                if (status === 2 && Number(data[3]) > 0) {
                    chart2.data.datasets[0].data.push(Number(data[3]))
                    chart2.data.datasets[1].data.push(Number(data[5]))
                    chart2.data.labels[chart2.data.datasets[0].data.length - 1] = ''
                    chart2.data.labels[chart2.data.datasets[1].data.length - 1] = ''
                    chart2.update()
                }
                ip.textContent = data[4]
            }
            w.postMessage('start')
        }
        function abortTest() {
            if (w) w.postMessage('abort')
        }
    </script>
</head>

<body>
    <h1>Speedtest</h1>
    <div id="testArea" style="display:none">
        <p id="ip">Please wait...</p>

        <h2>Speed</h2>
        <canvas id="chart1Area"></canvas>

        <h2>Latency</h2>
        <canvas id="chart2Area"></canvas>
        <br/>
        <a href="javascript:abortTest()" id="abortBtn">Abort</a>
    </div>
    <a href="javascript:runTest()" id="startBtn">Run speedtest</a>
    <br/><br/> Charts by <a href="http://www.chartjs.org/">Chart.js</a>
</body>
</html>