e5496fcf90
This just makes the links to the source code and Chart.js open in a new tab. The `rel="noopener noreferrer"` has been added to prevent security issues in older browsers. This is just an ease of use change that doesn't affect any of the core speedtest functionality in any way. Signed-off-by: Matthew Nickson <mnickson@sidingsmedia.com>
263 lines
6.7 KiB
HTML
Executable file
263 lines
6.7 KiB
HTML
Executable file
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
|
|
<meta charset="UTF-8" />
|
|
<link rel="shortcut icon" href="favicon.ico">
|
|
<script type="text/javascript" src="speedtest.js"></script>
|
|
<script type="text/javascript">
|
|
function I(i){return document.getElementById(i);}
|
|
//INITIALIZE SPEEDTEST
|
|
var s=new Speedtest(); //create speedtest object
|
|
|
|
var meterBk=/Trident.*rv:(\d+\.\d+)/i.test(navigator.userAgent)?"#EAEAEA":"#80808040";
|
|
var dlColor="#6060AA",
|
|
ulColor="#616161";
|
|
var progColor=meterBk;
|
|
|
|
//CODE FOR GAUGES
|
|
function drawMeter(c,amount,bk,fg,progress,prog){
|
|
var ctx=c.getContext("2d");
|
|
var dp=window.devicePixelRatio||1;
|
|
var cw=c.clientWidth*dp, ch=c.clientHeight*dp;
|
|
var sizScale=ch*0.0055;
|
|
if(c.width==cw&&c.height==ch){
|
|
ctx.clearRect(0,0,cw,ch);
|
|
}else{
|
|
c.width=cw;
|
|
c.height=ch;
|
|
}
|
|
ctx.beginPath();
|
|
ctx.strokeStyle=bk;
|
|
ctx.lineWidth=12*sizScale;
|
|
ctx.arc(c.width/2,c.height-58*sizScale,c.height/1.8-ctx.lineWidth,-Math.PI*1.1,Math.PI*0.1);
|
|
ctx.stroke();
|
|
ctx.beginPath();
|
|
ctx.strokeStyle=fg;
|
|
ctx.lineWidth=12*sizScale;
|
|
ctx.arc(c.width/2,c.height-58*sizScale,c.height/1.8-ctx.lineWidth,-Math.PI*1.1,amount*Math.PI*1.2-Math.PI*1.1);
|
|
ctx.stroke();
|
|
if(typeof progress !== "undefined"){
|
|
ctx.fillStyle=prog;
|
|
ctx.fillRect(c.width*0.3,c.height-16*sizScale,c.width*0.4*progress,4*sizScale);
|
|
}
|
|
}
|
|
function mbpsToAmount(s){
|
|
return 1-(1/(Math.pow(1.3,Math.sqrt(s))));
|
|
}
|
|
function format(d){
|
|
d=Number(d);
|
|
if(d<10) return d.toFixed(2);
|
|
if(d<100) return d.toFixed(1);
|
|
return d.toFixed(0);
|
|
}
|
|
|
|
//UI CODE
|
|
var uiData=null;
|
|
function startStop(){
|
|
if(s.getState()==3){
|
|
//speedtest is running, abort
|
|
s.abort();
|
|
data=null;
|
|
I("startStopBtn").className="";
|
|
initUI();
|
|
}else{
|
|
//test is not running, begin
|
|
I("startStopBtn").className="running";
|
|
s.onupdate=function(data){
|
|
uiData=data;
|
|
};
|
|
s.onend=function(aborted){
|
|
I("startStopBtn").className="";
|
|
updateUI(true);
|
|
};
|
|
s.start();
|
|
}
|
|
}
|
|
//this function reads the data sent back by the test and updates the UI
|
|
function updateUI(forced){
|
|
if(!forced&&s.getState()!=3) return;
|
|
if(uiData==null) return;
|
|
var status=uiData.testState;
|
|
I("ip").textContent=uiData.clientIp;
|
|
I("dlText").textContent=(status==1&&uiData.dlStatus==0)?"...":format(uiData.dlStatus);
|
|
drawMeter(I("dlMeter"),mbpsToAmount(Number(uiData.dlStatus*(status==1?oscillate():1))),meterBk,dlColor,Number(uiData.dlProgress),progColor);
|
|
I("ulText").textContent=(status==3&&uiData.ulStatus==0)?"...":format(uiData.ulStatus);
|
|
drawMeter(I("ulMeter"),mbpsToAmount(Number(uiData.ulStatus*(status==3?oscillate():1))),meterBk,ulColor,Number(uiData.ulProgress),progColor);
|
|
I("pingText").textContent=format(uiData.pingStatus);
|
|
I("jitText").textContent=format(uiData.jitterStatus);
|
|
}
|
|
function oscillate(){
|
|
return 1+0.02*Math.sin(Date.now()/100);
|
|
}
|
|
//update the UI every frame
|
|
window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||(function(callback,element){setTimeout(callback,1000/60);});
|
|
function frame(){
|
|
requestAnimationFrame(frame);
|
|
updateUI();
|
|
}
|
|
frame(); //start frame loop
|
|
//function to (re)initialize UI
|
|
function initUI(){
|
|
drawMeter(I("dlMeter"),0,meterBk,dlColor,0);
|
|
drawMeter(I("ulMeter"),0,meterBk,ulColor,0);
|
|
I("dlText").textContent="";
|
|
I("ulText").textContent="";
|
|
I("pingText").textContent="";
|
|
I("jitText").textContent="";
|
|
I("ip").textContent="";
|
|
}
|
|
</script>
|
|
<style type="text/css">
|
|
html,body{
|
|
border:none; padding:0; margin:0;
|
|
background:#FFFFFF;
|
|
color:#202020;
|
|
}
|
|
body{
|
|
text-align:center;
|
|
font-family:"Roboto",sans-serif;
|
|
}
|
|
h1{
|
|
color:#404040;
|
|
}
|
|
#startStopBtn{
|
|
display:inline-block;
|
|
margin:0 auto;
|
|
color:#6060AA;
|
|
background-color:rgba(0,0,0,0);
|
|
border:0.15em solid #6060FF;
|
|
border-radius:0.3em;
|
|
transition:all 0.3s;
|
|
box-sizing:border-box;
|
|
width:8em; height:3em;
|
|
line-height:2.7em;
|
|
cursor:pointer;
|
|
box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
|
|
}
|
|
#startStopBtn:hover{
|
|
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
|
|
}
|
|
#startStopBtn.running{
|
|
background-color:#FF3030;
|
|
border-color:#FF6060;
|
|
color:#FFFFFF;
|
|
}
|
|
#startStopBtn:before{
|
|
content:"Start";
|
|
}
|
|
#startStopBtn.running:before{
|
|
content:"Abort";
|
|
}
|
|
#test{
|
|
margin-top:2em;
|
|
margin-bottom:12em;
|
|
}
|
|
div.testArea{
|
|
display:inline-block;
|
|
width:16em;
|
|
height:12.5em;
|
|
position:relative;
|
|
box-sizing:border-box;
|
|
}
|
|
div.testArea2{
|
|
display:inline-block;
|
|
width:14em;
|
|
height:7em;
|
|
position:relative;
|
|
box-sizing:border-box;
|
|
text-align:center;
|
|
}
|
|
div.testArea div.testName{
|
|
position:absolute;
|
|
top:0.1em; left:0;
|
|
width:100%;
|
|
font-size:1.4em;
|
|
z-index:9;
|
|
}
|
|
div.testArea2 div.testName{
|
|
display:block;
|
|
text-align:center;
|
|
font-size:1.4em;
|
|
}
|
|
div.testArea div.meterText{
|
|
position:absolute;
|
|
bottom:1.55em; left:0;
|
|
width:100%;
|
|
font-size:2.5em;
|
|
z-index:9;
|
|
}
|
|
div.testArea2 div.meterText{
|
|
display:inline-block;
|
|
font-size:2.5em;
|
|
}
|
|
div.meterText:empty:before{
|
|
content:"0.00";
|
|
}
|
|
div.testArea div.unit{
|
|
position:absolute;
|
|
bottom:2em; left:0;
|
|
width:100%;
|
|
z-index:9;
|
|
}
|
|
div.testArea2 div.unit{
|
|
display:inline-block;
|
|
}
|
|
div.testArea canvas{
|
|
position:absolute;
|
|
top:0; left:0; width:100%; height:100%;
|
|
z-index:1;
|
|
}
|
|
div.testGroup{
|
|
display:block;
|
|
margin: 0 auto;
|
|
}
|
|
@media all and (max-width:40em){
|
|
body{
|
|
font-size:0.8em;
|
|
}
|
|
}
|
|
</style>
|
|
<title>LibreSpeed Example</title>
|
|
</head>
|
|
<body>
|
|
<h1>LibreSpeed Example</h1>
|
|
<div id="testWrapper">
|
|
<div id="startStopBtn" onclick="startStop()"></div>
|
|
<div id="test">
|
|
<div class="testGroup">
|
|
<div class="testArea2">
|
|
<div class="testName">Ping</div>
|
|
<div id="pingText" class="meterText" style="color:#AA6060"></div>
|
|
<div class="unit">ms</div>
|
|
</div>
|
|
<div class="testArea2">
|
|
<div class="testName">Jitter</div>
|
|
<div id="jitText" class="meterText" style="color:#AA6060"></div>
|
|
<div class="unit">ms</div>
|
|
</div>
|
|
</div>
|
|
<div class="testGroup">
|
|
<div class="testArea">
|
|
<div class="testName">Download</div>
|
|
<canvas id="dlMeter" class="meter"></canvas>
|
|
<div id="dlText" class="meterText"></div>
|
|
<div class="unit">Mbps</div>
|
|
</div>
|
|
<div class="testArea">
|
|
<div class="testName">Upload</div>
|
|
<canvas id="ulMeter" class="meter"></canvas>
|
|
<div id="ulText" class="meterText"></div>
|
|
<div class="unit">Mbps</div>
|
|
</div>
|
|
</div>
|
|
<div id="ipArea">
|
|
<span id="ip"></span>
|
|
</div>
|
|
</div>
|
|
<a href="https://github.com/librespeed/speedtest" target="_blank" rel="noopener noreferrer">Source code</a>
|
|
</div>
|
|
<script type="text/javascript">setTimeout(function(){initUI()},100);</script>
|
|
</body>
|
|
</html>
|