Sync frontend components with PHP version
This commit is contained in:
parent
2ca5dbf071
commit
a9adc15ce9
@ -1,461 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
|
||||
<meta charset="UTF-8" />
|
||||
<script type="text/javascript" src="speedtest.js"></script>
|
||||
<script type="text/javascript">
|
||||
function I(i){return document.getElementById(i);}
|
||||
|
||||
//LIST OF TEST SERVERS. See documentation for details if needed
|
||||
var SPEEDTEST_SERVERS=[
|
||||
{ //this is my demo server, remove it
|
||||
name:"Speedtest Demo Server (Helsinki)", //user friendly name for the server
|
||||
server:"//fi.openspeed.org/", //URL to the server. // at the beginning will be replaced with http:// or https:// automatically
|
||||
dlURL:"garbage", //path to download test on this server (garbage.php or replacement)
|
||||
ulURL:"empty", //path to upload test on this server (empty.php or replacement)
|
||||
pingURL:"empty", //path to ping/jitter test on this server (empty.php or replacement)
|
||||
getIpURL:"getIP" //path to getIP on this server (getIP.php or replacement)
|
||||
},
|
||||
{ //this is my demo server, remove it
|
||||
name:"Old Speedtest Demo Server",
|
||||
server:"//mpotdemo.fdossena.com/",
|
||||
dlURL:"garbage",
|
||||
ulURL:"empty",
|
||||
pingURL:"empty",
|
||||
getIpURL:"getIP"
|
||||
}
|
||||
//add other servers here, comma separated
|
||||
];
|
||||
|
||||
//INITIALIZE SPEEDTEST
|
||||
var s=new Speedtest(); //create speedtest object
|
||||
s.setParameter("telemetry_level","basic"); //enable telemetry
|
||||
s.addTestPoints(SPEEDTEST_SERVERS); //add list of servers
|
||||
|
||||
//SERVER AUTO SELECTION
|
||||
function initServers(){
|
||||
s.selectServer(function(server){
|
||||
if(server!=null){ //at least 1 server is available
|
||||
I("loading").className="hidden"; //hide loading message
|
||||
//populate server list for manual selection
|
||||
for(var i=0;i<SPEEDTEST_SERVERS.length;i++){
|
||||
if(SPEEDTEST_SERVERS[i].pingT==-1) continue;
|
||||
var option=document.createElement("option");
|
||||
option.value=i;
|
||||
option.textContent=SPEEDTEST_SERVERS[i].name;
|
||||
if(SPEEDTEST_SERVERS[i]===server) option.selected=true;
|
||||
I("server").appendChild(option);
|
||||
}
|
||||
//show test UI
|
||||
I("testWrapper").className="visible";
|
||||
initUI();
|
||||
}else{ //no servers are available, the test cannot proceed
|
||||
I("message").innerHTML="No servers available";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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="";
|
||||
I("server").disabled=false;
|
||||
initUI();
|
||||
}else{
|
||||
//test is not running, begin
|
||||
I("startStopBtn").className="running";
|
||||
I("shareArea").style.display="none";
|
||||
I("server").disabled=true;
|
||||
s.onupdate=function(data){
|
||||
uiData=data;
|
||||
};
|
||||
s.onend=function(aborted){
|
||||
I("startStopBtn").className="";
|
||||
I("server").disabled=false;
|
||||
updateUI(true);
|
||||
if(!aborted){
|
||||
//if testId is present, show sharing panel, otherwise do nothing
|
||||
try{
|
||||
var testId=uiData.testId;
|
||||
if(testId!=null){
|
||||
var shareURL=window.location.href.substring(0,window.location.href.lastIndexOf("/"))+"/results/?id="+testId;
|
||||
I("resultsImg").src=shareURL;
|
||||
I("resultsURL").value=shareURL;
|
||||
I("testId").innerHTML=testId;
|
||||
I("shareArea").style.display="";
|
||||
}
|
||||
}catch(e){}
|
||||
}
|
||||
};
|
||||
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;
|
||||
}
|
||||
#loading{
|
||||
background-color:#FFFFFF;
|
||||
color:#404040;
|
||||
text-align:center;
|
||||
}
|
||||
span.loadCircle{
|
||||
display:inline-block;
|
||||
width:2em;
|
||||
height:2em;
|
||||
vertical-align:middle;
|
||||
background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAP1BMVEUAAAB2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZyFzwnAAAAFHRSTlMAEvRFvX406baecwbf0casimhSHyiwmqgAAADpSURBVHja7dbJbQMxAENRahnN5lkc//5rDRAkDeRgHszXgACJoKiIiIiIiIiIiIiIiIiIiIj4HHspsrpAVhdVVguzrA4OWc10WcEqpwKbnBo0OU1Q5NSpsoJFTgOecrrdEag85DRgktNqfoEdTjnd7hrEHMEJvmRUYJbTYk5Agy6nau6Abp5Cm7mDBtRdPi9gyKdU7w4p1fsLvyqs8hl4z9/w3n/Hmr9WoQ65lAU4d7lMYOz//QboRR5jBZibLMZdAR6O/Vfa1PlxNr3XdS3HzK/HVPRu/KnLs8iAOh993VpRRERERMT/fAN60wwWaVyWwAAAAABJRU5ErkJggg==');
|
||||
background-size:2em 2em;
|
||||
margin-right:0.5em;
|
||||
animation: spin 0.6s linear infinite;
|
||||
}
|
||||
@keyframes spin{
|
||||
0%{transform:rotate(0deg);}
|
||||
100%{transform:rotate(359deg);}
|
||||
}
|
||||
#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";
|
||||
}
|
||||
#serverArea{
|
||||
margin-top:1em;
|
||||
}
|
||||
#server{
|
||||
font-size:1em;
|
||||
padding:0.2em;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
#shareArea{
|
||||
width:95%;
|
||||
max-width:40em;
|
||||
margin:0 auto;
|
||||
margin-top:2em;
|
||||
}
|
||||
#shareArea > *{
|
||||
display:block;
|
||||
width:100%;
|
||||
height:auto;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
#privacyPolicy{
|
||||
position:fixed;
|
||||
top:2em;
|
||||
bottom:2em;
|
||||
left:2em;
|
||||
right:2em;
|
||||
overflow-y:auto;
|
||||
width:auto;
|
||||
height:auto;
|
||||
box-shadow:0 0 3em 1em #000000;
|
||||
z-index:999999;
|
||||
text-align:left;
|
||||
background-color:#FFFFFF;
|
||||
padding:1em;
|
||||
}
|
||||
a.privacy{
|
||||
text-align:center;
|
||||
font-size:0.8em;
|
||||
color:#808080;
|
||||
display:block;
|
||||
}
|
||||
@media all and (max-width:40em){
|
||||
body{
|
||||
font-size:0.8em;
|
||||
}
|
||||
}
|
||||
div.visible{
|
||||
animation: fadeIn 0.4s;
|
||||
display:block;
|
||||
}
|
||||
div.hidden{
|
||||
animation: fadeOut 0.4s;
|
||||
display:none;
|
||||
}
|
||||
@keyframes fadeIn{
|
||||
0%{
|
||||
opacity:0;
|
||||
}
|
||||
100%{
|
||||
opacity:1;
|
||||
}
|
||||
}
|
||||
@keyframes fadeOut{
|
||||
0%{
|
||||
display:block;
|
||||
opacity:1;
|
||||
}
|
||||
100%{
|
||||
display:block;
|
||||
opacity:0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<title>LibreSpeed Example</title>
|
||||
</head>
|
||||
<body onload="initServers()">
|
||||
<h1>LibreSpeed Example</h1>
|
||||
<div id="loading" class="visible">
|
||||
<p id="message"><span class="loadCircle"></span>Selecting a server...</p>
|
||||
</div>
|
||||
<div id="testWrapper" class="hidden">
|
||||
<div id="startStopBtn" onclick="startStop()"></div>
|
||||
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''">Privacy</a>
|
||||
<div id="serverArea">
|
||||
Server: <select id="server" onchange="s.setSelectedServer(SPEEDTEST_SERVERS[this.value])"></select>
|
||||
</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">Mbit/s</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">Mbit/s</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipArea">
|
||||
<span id="ip"></span>
|
||||
</div>
|
||||
<div id="shareArea" style="display:none">
|
||||
<h3>Share results</h3>
|
||||
<p>Test ID: <span id="testId"></span></p>
|
||||
<input type="text" value="" id="resultsURL" readonly="readonly" onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')"/>
|
||||
<img src="" id="resultsImg" />
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
</div>
|
||||
<div id="privacyPolicy" style="display:none">
|
||||
<h2>Privacy Policy</h2>
|
||||
<p>This HTML5 Speedtest server is configured with telemetry enabled.</p>
|
||||
<h4>What data we collect</h4>
|
||||
<p>
|
||||
At the end of the test, the following data is collected and stored:
|
||||
<ul>
|
||||
<li>Test ID</li>
|
||||
<li>Time of testing</li>
|
||||
<li>Test results (download and upload speed, ping and jitter)</li>
|
||||
<li>IP address</li>
|
||||
<li>ISP information</li>
|
||||
<li>Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li>User agent and browser locale</li>
|
||||
<li>Test log (contains no personal information)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h4>How we use the data</h4>
|
||||
<p>
|
||||
Data collected through this service is used to:
|
||||
<ul>
|
||||
<li>Allow sharing of test results (sharable image for forums, etc.)</li>
|
||||
<li>To improve the service offered to you (for instance, to detect problems on our side)</li>
|
||||
</ul>
|
||||
No personal information is disclosed to third parties.
|
||||
</p>
|
||||
<h4>Your consent</h4>
|
||||
<p>
|
||||
By starting the test, you consent to the terms of this privacy policy.
|
||||
</p>
|
||||
<h4>Data removal</h4>
|
||||
<p>
|
||||
If you want to have your information deleted, you need to provide either the ID of the test or your IP address. This is the only way to identify your data, without this information we won't be able to comply with your request.<br/><br/>
|
||||
Contact this email address for all deletion requests: <a href="mailto:PUT@YOUR_EMAIL.HERE">TO BE FILLED BY DEVELOPER</a>.
|
||||
</p>
|
||||
<br/><br/>
|
||||
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display='none'">Close</a><br/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,225 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
|
||||
<title>LibreSpeed Example</title>
|
||||
<script type="text/javascript" src="speedtest.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
//LIST OF TEST SERVERS. See documentation for details if needed
|
||||
var SPEEDTEST_SERVERS=[
|
||||
{ //this is my demo server, remove it
|
||||
name:"Speedtest Demo Server (Helsinki)", //user friendly name for the server
|
||||
server:"//fi.openspeed.org/", //URL to the server. // at the beginning will be replaced with http:// or https:// automatically
|
||||
dlURL:"garbage", //path to download test on this server (garbage.php or replacement)
|
||||
ulURL:"empty", //path to upload test on this server (empty.php or replacement)
|
||||
pingURL:"empty", //path to ping/jitter test on this server (empty.php or replacement)
|
||||
getIpURL:"getIP" //path to getIP on this server (getIP.php or replacement)
|
||||
},
|
||||
{ //this is my demo server, remove it
|
||||
name:"Old Speedtest Demo Server",
|
||||
server:"//mpotdemo.fdossena.com/",
|
||||
dlURL:"garbage",
|
||||
ulURL:"empty",
|
||||
pingURL:"empty",
|
||||
getIpURL:"getIP"
|
||||
}
|
||||
//add other servers here, comma separated
|
||||
];
|
||||
|
||||
|
||||
//INITIALIZE SPEEDTEST
|
||||
var s=new Speedtest(); //create speedtest object
|
||||
s.addTestPoints(SPEEDTEST_SERVERS); //add list of servers
|
||||
s.onupdate=function(data){ //callback to update data in UI
|
||||
I("ip").textContent=data.clientIp;
|
||||
I("dlText").textContent=(data.testState==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||
I("ulText").textContent=(data.testState==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||
I("pingText").textContent=data.pingStatus;
|
||||
I("jitText").textContent=data.jitterStatus;
|
||||
}
|
||||
s.onend=function(aborted){ //callback for test ended/aborted
|
||||
I("startStopBtn").className=""; //show start button again
|
||||
if(aborted){ //if the test was aborted, clear the UI and prepare for new test
|
||||
initUI();
|
||||
}
|
||||
}
|
||||
function selectServer(){ //called when the page is fully loaded
|
||||
I("startStopBtn").style.display="none"; //hide start/stop button during server selection
|
||||
s.selectServer(function(server){ //run server selection. When the server has been selected, display it in the UI
|
||||
I("startStopBtn").style.display=""; //show start/stop button again
|
||||
I("serverId").textContent=server.name; //show name of test server
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function startStop(){ //start/stop button pressed
|
||||
if(s.getState()==3){
|
||||
//speedtest is running, abort
|
||||
s.abort();
|
||||
}else{
|
||||
//test is not running, begin
|
||||
s.start();
|
||||
I("startStopBtn").className="running";
|
||||
}
|
||||
}
|
||||
|
||||
//function to (re)initialize UI
|
||||
function initUI(){
|
||||
I("dlText").textContent="";
|
||||
I("ulText").textContent="";
|
||||
I("pingText").textContent="";
|
||||
I("jitText").textContent="";
|
||||
I("ip").textContent="";
|
||||
}
|
||||
|
||||
function I(id){return document.getElementById(id);}
|
||||
</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:14em;
|
||||
height:9em;
|
||||
position:relative;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
div.testName{
|
||||
position:absolute;
|
||||
top:0.1em; left:0;
|
||||
width:100%;
|
||||
font-size:1.4em;
|
||||
z-index:9;
|
||||
}
|
||||
div.meterText{
|
||||
position:absolute;
|
||||
bottom:1.5em; left:0;
|
||||
width:100%;
|
||||
font-size:2.5em;
|
||||
z-index:9;
|
||||
}
|
||||
#dlText{
|
||||
color:#6060AA;
|
||||
}
|
||||
#ulText{
|
||||
color:#309030;
|
||||
}
|
||||
#pingText,#jitText{
|
||||
color:#AA6060;
|
||||
}
|
||||
div.meterText:empty:before{
|
||||
color:#505050 !important;
|
||||
content:"0.00";
|
||||
}
|
||||
div.unit{
|
||||
position:absolute;
|
||||
bottom:2em; left:0;
|
||||
width:100%;
|
||||
z-index:9;
|
||||
}
|
||||
div.testGroup{
|
||||
display:inline-block;
|
||||
}
|
||||
@media all and (max-width:65em){
|
||||
body{
|
||||
font-size:1.5vw;
|
||||
}
|
||||
}
|
||||
@media all and (max-width:40em){
|
||||
body{
|
||||
font-size:0.8em;
|
||||
}
|
||||
div.testGroup{
|
||||
display:block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LibreSpeed Example</h1>
|
||||
<div id="startStopBtn" onclick="startStop()"></div>
|
||||
<div id="serverId">Selecting server...</div>
|
||||
<div id="test">
|
||||
<div class="testGroup">
|
||||
<div class="testArea">
|
||||
<div class="testName">Download</div>
|
||||
<div id="dlText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Upload</div>
|
||||
<div id="ulText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="testGroup">
|
||||
<div class="testArea">
|
||||
<div class="testName">Ping</div>
|
||||
<div id="pingText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Jitter</div>
|
||||
<div id="jitText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipArea">
|
||||
IP Address: <span id="ip"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
<script type="text/javascript">
|
||||
initUI();
|
||||
selectServer();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,38 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<meta charset="UTF-8" />
|
||||
<head>
|
||||
<title>LibreSpeed Example</title>
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
</head>
|
||||
<script type="text/javascript" src="speedtest.js"></script>
|
||||
<body>
|
||||
<h1>LibreSpeed Example</h1>
|
||||
|
||||
<h4>IP Address</h4>
|
||||
<p id="ip"></p>
|
||||
|
||||
<h4>Download</h4>
|
||||
<p id="download"></p>
|
||||
|
||||
<h4>Upload</h4>
|
||||
<p id="upload"></p>
|
||||
|
||||
<h4>Latency</h4>
|
||||
<p id="ping"></p>
|
||||
|
||||
<script type="text/javascript">
|
||||
var s=new Speedtest();
|
||||
s.onupdate = function (data) { // when status is received, put the values in the appropriate fields
|
||||
document.getElementById('download').textContent = data.dlStatus + ' Mbit/s'
|
||||
document.getElementById('upload').textContent = data.ulStatus + ' Mbit/s'
|
||||
document.getElementById('ping').textContent = data.pingStatus + ' ms, ' + data.jitterStatus + ' ms jitter'
|
||||
document.getElementById('ip').textContent = data.clientIp
|
||||
}
|
||||
s.start(); // start the speedtest with default settings
|
||||
</script>
|
||||
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,256 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>LibreSpeed Example</title>
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<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> <!--THIS LIBRARY SUCKS!-->
|
||||
<script src="speedtest.js"></script>
|
||||
<script type="text/javascript">
|
||||
var s = 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 = ''
|
||||
s=new Speedtest();
|
||||
s.onupdate = function (data) {
|
||||
var status = data.testState
|
||||
if (status === 1 && Number(data.dlStatus) > 0) {
|
||||
for(var i=~~(20*Number(data.dlProgress));i<20;i++) chart1.data.datasets[0].data[i]=(Number(data.dlStatus))
|
||||
chart1.data.labels[chart1.data.datasets[0].data.length - 1] = ''
|
||||
chart1.update()
|
||||
}
|
||||
if (status === 3 && Number(data.ulStatus) > 0) {
|
||||
for(var i=~~(20*Number(data.ulProgress));i<20;i++) chart1.data.datasets[1].data[i]=(Number(data.ulStatus))
|
||||
chart1.data.labels[chart1.data.datasets[1].data.length - 1] = ''
|
||||
chart1.update()
|
||||
}
|
||||
if (status === 2 && Number(data.pingStatus) > 0) {
|
||||
chart2.data.datasets[0].data.push(Number(data.pingStatus))
|
||||
chart2.data.datasets[1].data.push(Number(data.jitterStatus))
|
||||
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.clientIp
|
||||
}
|
||||
s.onend=function(aborted){
|
||||
document.getElementById('abortBtn').style.display = 'none'
|
||||
document.getElementById('startBtn').style.display = ''
|
||||
s = null
|
||||
if (aborted) {
|
||||
document.getElementById('testArea').style.display = 'none'
|
||||
}
|
||||
}
|
||||
s.start();
|
||||
}
|
||||
function abortTest() {
|
||||
if (s) s.abort();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>LibreSpeed - Chart.js example</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><br/><br/><a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
</body>
|
||||
</html>
|
@ -1,174 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
|
||||
<title>LibreSpeed Example</title>
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<script type="text/javascript" src="speedtest.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
//INITIALIZE SPEEDTEST
|
||||
var s=new Speedtest(); //create speedtest object
|
||||
//CUSTOM SETTINGS HERE
|
||||
s.setParameter("test_order","D_U"); //we only want download and upload test
|
||||
s.setParameter("time_auto",false); //fixed duration for tests
|
||||
s.setParameter("time_dl_max",10); //10 seconds for the download test
|
||||
s.setParameter("time_ul_max",15); //15 seconds for the upload test
|
||||
//END OF CUSTOM SETTINGS
|
||||
s.onupdate=function(data){ //callback to update data in UI
|
||||
I("dlText").textContent=(data.testState==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||
I("ulText").textContent=(data.testState==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||
}
|
||||
s.onend=function(aborted){ //callback for test ended/aborted
|
||||
I("startStopBtn").className=""; //show start button again
|
||||
if(aborted){ //if the test was aborted, clear the UI and prepare for new test
|
||||
initUI();
|
||||
}
|
||||
}
|
||||
|
||||
function startStop(){ //start/stop button pressed
|
||||
if(s.getState()==3){
|
||||
//speedtest is running, abort
|
||||
s.abort();
|
||||
}else{
|
||||
//test is not running, begin
|
||||
s.start();
|
||||
I("startStopBtn").className="running";
|
||||
}
|
||||
}
|
||||
|
||||
//function to (re)initialize UI
|
||||
function initUI(){
|
||||
I("dlText").textContent="";
|
||||
I("ulText").textContent="";
|
||||
}
|
||||
|
||||
function I(id){return document.getElementById(id);}
|
||||
</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:14em;
|
||||
height:9em;
|
||||
position:relative;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
div.testName{
|
||||
position:absolute;
|
||||
top:0.1em; left:0;
|
||||
width:100%;
|
||||
font-size:1.4em;
|
||||
z-index:9;
|
||||
}
|
||||
div.meterText{
|
||||
position:absolute;
|
||||
bottom:1.5em; left:0;
|
||||
width:100%;
|
||||
font-size:2.5em;
|
||||
z-index:9;
|
||||
}
|
||||
#dlText{
|
||||
color:#6060AA;
|
||||
}
|
||||
#ulText{
|
||||
color:#309030;
|
||||
}
|
||||
div.meterText:empty:before{
|
||||
color:#505050 !important;
|
||||
content:"0.00";
|
||||
}
|
||||
div.unit{
|
||||
position:absolute;
|
||||
bottom:2em; left:0;
|
||||
width:100%;
|
||||
z-index:9;
|
||||
}
|
||||
div.testGroup{
|
||||
display:inline-block;
|
||||
}
|
||||
@media all and (max-width:65em){
|
||||
body{
|
||||
font-size:2vw;
|
||||
}
|
||||
}
|
||||
@media all and (max-width:40em){
|
||||
body{
|
||||
font-size:0.8em;
|
||||
}
|
||||
div.testGroup{
|
||||
display:block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LibreSpeed Example</h1>
|
||||
<div id="startStopBtn" onclick="startStop()"></div>
|
||||
<div id="test">
|
||||
<div class="testGroup">
|
||||
<div class="testArea">
|
||||
<div class="testName">Download</div>
|
||||
<div id="dlText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Upload</div>
|
||||
<div id="ulText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
<script type="text/javascript">
|
||||
initUI();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,365 +0,0 @@
|
||||
<!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
|
||||
s.setParameter("telemetry_level","basic"); //enable telemetry
|
||||
s.setParameter("url_telemetry", "results/telemetry");
|
||||
var server = {
|
||||
name: "demo",
|
||||
server:window.location.protocol + "//" + window.location.host,
|
||||
dlURL:"garbage",
|
||||
ulURL:"empty",
|
||||
pingURL:"empty",
|
||||
getIpURL:"getIP",
|
||||
};
|
||||
s.setSelectedServer(server);
|
||||
|
||||
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";
|
||||
I("shareArea").style.display="none";
|
||||
s.onupdate=function(data){
|
||||
uiData=data;
|
||||
};
|
||||
s.onend=function(aborted){
|
||||
I("startStopBtn").className="";
|
||||
updateUI(true);
|
||||
if(!aborted){
|
||||
//if testId is present, show sharing panel, otherwise do nothing
|
||||
try{
|
||||
var testId=uiData.testId;
|
||||
if(testId!=null){
|
||||
var shareURL=window.location.href.substring(0,window.location.href.lastIndexOf("/"))+"/results/?id="+testId;
|
||||
I("resultsImg").src=shareURL;
|
||||
I("resultsURL").value=shareURL;
|
||||
I("testId").innerHTML=testId;
|
||||
I("shareArea").style.display="";
|
||||
}
|
||||
}catch(e){}
|
||||
}
|
||||
};
|
||||
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;
|
||||
}
|
||||
#shareArea{
|
||||
width:95%;
|
||||
max-width:40em;
|
||||
margin:0 auto;
|
||||
margin-top:2em;
|
||||
}
|
||||
#shareArea > *{
|
||||
display:block;
|
||||
width:100%;
|
||||
height:auto;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
#privacyPolicy{
|
||||
position:fixed;
|
||||
top:2em;
|
||||
bottom:2em;
|
||||
left:2em;
|
||||
right:2em;
|
||||
overflow-y:auto;
|
||||
width:auto;
|
||||
height:auto;
|
||||
box-shadow:0 0 3em 1em #000000;
|
||||
z-index:999999;
|
||||
text-align:left;
|
||||
background-color:#FFFFFF;
|
||||
padding:1em;
|
||||
}
|
||||
a.privacy{
|
||||
text-align:center;
|
||||
font-size:0.8em;
|
||||
color:#808080;
|
||||
display:block;
|
||||
}
|
||||
@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><br/>
|
||||
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''">Privacy</a>
|
||||
<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">Mbit/s</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">Mbit/s</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipArea">
|
||||
<span id="ip"></span>
|
||||
</div>
|
||||
<div id="shareArea" style="display:none">
|
||||
<h3>Share results</h3>
|
||||
<p>Test ID: <span id="testId"></span></p>
|
||||
<input type="text" value="" id="resultsURL" readonly="readonly" onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')"/>
|
||||
<img src="" id="resultsImg" />
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
</div>
|
||||
<div id="privacyPolicy" style="display:none">
|
||||
<h2>Privacy Policy</h2>
|
||||
<p>This HTML5 Speedtest server is configured with telemetry enabled.</p>
|
||||
<h4>What data we collect</h4>
|
||||
<p>
|
||||
At the end of the test, the following data is collected and stored:
|
||||
<ul>
|
||||
<li>Test ID</li>
|
||||
<li>Time of testing</li>
|
||||
<li>Test results (download and upload speed, ping and jitter)</li>
|
||||
<li>IP address</li>
|
||||
<li>ISP information</li>
|
||||
<li>Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li>User agent and browser locale</li>
|
||||
<li>Test log (contains no personal information)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h4>How we use the data</h4>
|
||||
<p>
|
||||
Data collected through this service is used to:
|
||||
<ul>
|
||||
<li>Allow sharing of test results (sharable image for forums, etc.)</li>
|
||||
<li>To improve the service offered to you (for instance, to detect problems on our side)</li>
|
||||
</ul>
|
||||
No personal information is disclosed to third parties.
|
||||
</p>
|
||||
<h4>Your consent</h4>
|
||||
<p>
|
||||
By starting the test, you consent to the terms of this privacy policy.
|
||||
</p>
|
||||
<h4>Data removal</h4>
|
||||
<p>
|
||||
If you want to have your information deleted, you need to provide either the ID of the test or your IP address. This is the only way to identify your data, without this information we won't be able to comply with your request.<br/><br/>
|
||||
Contact this email address for all deletion requests: <a href="mailto:PUT@YOUR_EMAIL.HERE">TO BE FILLED BY DEVELOPER</a>.
|
||||
</p>
|
||||
<br/><br/>
|
||||
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display='none'">Close</a><br/>
|
||||
</div>
|
||||
<script type="text/javascript">setTimeout(function(){initUI()},100);</script>
|
||||
</body>
|
||||
</html>
|
@ -1,262 +0,0 @@
|
||||
<!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">Mbit/s</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">Mbit/s</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipArea">
|
||||
<span id="ip"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
</div>
|
||||
<script type="text/javascript">setTimeout(function(){initUI()},100);</script>
|
||||
</body>
|
||||
</html>
|
@ -1,192 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
|
||||
<title>LibreSpeed Example</title>
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<script type="text/javascript" src="speedtest.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
//INITIALIZE SPEEDTEST
|
||||
var s=new Speedtest(); //create speedtest object
|
||||
s.onupdate=function(data){ //callback to update data in UI
|
||||
I("ip").textContent=data.clientIp;
|
||||
I("dlText").textContent=(data.testState==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||
I("ulText").textContent=(data.testState==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||
I("pingText").textContent=data.pingStatus;
|
||||
I("jitText").textContent=data.jitterStatus;
|
||||
}
|
||||
s.onend=function(aborted){ //callback for test ended/aborted
|
||||
I("startStopBtn").className=""; //show start button again
|
||||
if(aborted){ //if the test was aborted, clear the UI and prepare for new test
|
||||
initUI();
|
||||
}
|
||||
}
|
||||
|
||||
function startStop(){ //start/stop button pressed
|
||||
if(s.getState()==3){
|
||||
//speedtest is running, abort
|
||||
s.abort();
|
||||
}else{
|
||||
//test is not running, begin
|
||||
s.start();
|
||||
I("startStopBtn").className="running";
|
||||
}
|
||||
}
|
||||
|
||||
//function to (re)initialize UI
|
||||
function initUI(){
|
||||
I("dlText").textContent="";
|
||||
I("ulText").textContent="";
|
||||
I("pingText").textContent="";
|
||||
I("jitText").textContent="";
|
||||
I("ip").textContent="";
|
||||
}
|
||||
|
||||
function I(id){return document.getElementById(id);}
|
||||
</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:14em;
|
||||
height:9em;
|
||||
position:relative;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
div.testName{
|
||||
position:absolute;
|
||||
top:0.1em; left:0;
|
||||
width:100%;
|
||||
font-size:1.4em;
|
||||
z-index:9;
|
||||
}
|
||||
div.meterText{
|
||||
position:absolute;
|
||||
bottom:1.5em; left:0;
|
||||
width:100%;
|
||||
font-size:2.5em;
|
||||
z-index:9;
|
||||
}
|
||||
#dlText{
|
||||
color:#6060AA;
|
||||
}
|
||||
#ulText{
|
||||
color:#309030;
|
||||
}
|
||||
#pingText,#jitText{
|
||||
color:#AA6060;
|
||||
}
|
||||
div.meterText:empty:before{
|
||||
color:#505050 !important;
|
||||
content:"0.00";
|
||||
}
|
||||
div.unit{
|
||||
position:absolute;
|
||||
bottom:2em; left:0;
|
||||
width:100%;
|
||||
z-index:9;
|
||||
}
|
||||
div.testGroup{
|
||||
display:inline-block;
|
||||
}
|
||||
@media all and (max-width:65em){
|
||||
body{
|
||||
font-size:1.5vw;
|
||||
}
|
||||
}
|
||||
@media all and (max-width:40em){
|
||||
body{
|
||||
font-size:0.8em;
|
||||
}
|
||||
div.testGroup{
|
||||
display:block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LibreSpeed Example</h1>
|
||||
<div id="startStopBtn" onclick="startStop()"></div>
|
||||
<div id="test">
|
||||
<div class="testGroup">
|
||||
<div class="testArea">
|
||||
<div class="testName">Download</div>
|
||||
<div id="dlText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Upload</div>
|
||||
<div id="ulText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="testGroup">
|
||||
<div class="testArea">
|
||||
<div class="testName">Ping</div>
|
||||
<div id="pingText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Jitter</div>
|
||||
<div id="jitText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipArea">
|
||||
IP Address: <span id="ip"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
<script type="text/javascript">
|
||||
initUI();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,212 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
|
||||
<title>LibreSpeed Example</title>
|
||||
<link rel="shortcut icon" href="favicon.ico">
|
||||
<script type="text/javascript" src="speedtest.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
//INITIALIZE SPEEDTEST
|
||||
var s=new Speedtest(); //create speedtest object
|
||||
s.onupdate=function(data){ //callback to update data in UI
|
||||
I("ip").textContent=data.clientIp;
|
||||
I("dlText").textContent=(data.testState==1&&data.dlStatus==0)?"...":data.dlStatus;
|
||||
I("ulText").textContent=(data.testState==3&&data.ulStatus==0)?"...":data.ulStatus;
|
||||
I("pingText").textContent=data.pingStatus;
|
||||
I("jitText").textContent=data.jitterStatus;
|
||||
var prog=(Number(data.dlProgress)*2+Number(data.ulProgress)*2+Number(data.pingProgress))/5;
|
||||
I("progress").style.width=(100*prog)+"%";
|
||||
}
|
||||
s.onend=function(aborted){ //callback for test ended/aborted
|
||||
I("startStopBtn").className=""; //show start button again
|
||||
if(aborted){ //if the test was aborted, clear the UI and prepare for new test
|
||||
initUI();
|
||||
}
|
||||
}
|
||||
|
||||
function startStop(){ //start/stop button pressed
|
||||
if(s.getState()==3){
|
||||
//speedtest is running, abort
|
||||
s.abort();
|
||||
}else{
|
||||
//test is not running, begin
|
||||
s.start();
|
||||
I("startStopBtn").className="running";
|
||||
}
|
||||
}
|
||||
|
||||
//function to (re)initialize UI
|
||||
function initUI(){
|
||||
I("dlText").textContent="";
|
||||
I("ulText").textContent="";
|
||||
I("pingText").textContent="";
|
||||
I("jitText").textContent="";
|
||||
I("ip").textContent="";
|
||||
}
|
||||
|
||||
function I(id){return document.getElementById(id);}
|
||||
</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:14em;
|
||||
height:9em;
|
||||
position:relative;
|
||||
box-sizing:border-box;
|
||||
}
|
||||
div.testName{
|
||||
position:absolute;
|
||||
top:0.1em; left:0;
|
||||
width:100%;
|
||||
font-size:1.4em;
|
||||
z-index:9;
|
||||
}
|
||||
div.meterText{
|
||||
position:absolute;
|
||||
bottom:1.5em; left:0;
|
||||
width:100%;
|
||||
font-size:2.5em;
|
||||
z-index:9;
|
||||
}
|
||||
#dlText{
|
||||
color:#6060AA;
|
||||
}
|
||||
#ulText{
|
||||
color:#309030;
|
||||
}
|
||||
#pingText,#jitText{
|
||||
color:#AA6060;
|
||||
}
|
||||
div.meterText:empty:before{
|
||||
color:#505050 !important;
|
||||
content:"0.00";
|
||||
}
|
||||
div.unit{
|
||||
position:absolute;
|
||||
bottom:2em; left:0;
|
||||
width:100%;
|
||||
z-index:9;
|
||||
}
|
||||
div.testGroup{
|
||||
display:inline-block;
|
||||
}
|
||||
@media all and (max-width:65em){
|
||||
body{
|
||||
font-size:1.5vw;
|
||||
}
|
||||
}
|
||||
@media all and (max-width:40em){
|
||||
body{
|
||||
font-size:0.8em;
|
||||
}
|
||||
div.testGroup{
|
||||
display:block;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
#progressBar{
|
||||
width:90%;
|
||||
height:0.3em;
|
||||
background-color:#EEEEEE;
|
||||
position:relative;
|
||||
display:block;
|
||||
margin:0 auto;
|
||||
margin-bottom:2em;
|
||||
}
|
||||
#progress{
|
||||
position:absolute;
|
||||
top:0; left:0;
|
||||
height:100%;
|
||||
width:0%;
|
||||
transition: width 2s;
|
||||
background-color:#90BBFF;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LibreSpeed Example</h1>
|
||||
<div id="startStopBtn" onclick="startStop()"></div>
|
||||
<div id="test">
|
||||
<div id="progressBar"><div id="progress"></div></div>
|
||||
<div class="testGroup">
|
||||
<div class="testArea">
|
||||
<div class="testName">Download</div>
|
||||
<div id="dlText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Upload</div>
|
||||
<div id="ulText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="testGroup">
|
||||
<div class="testArea">
|
||||
<div class="testName">Ping</div>
|
||||
<div id="pingText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Jitter</div>
|
||||
<div id="jitText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipArea">
|
||||
IP Address: <span id="ip"></span>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
<script type="text/javascript">
|
||||
initUI();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -4,27 +4,59 @@
|
||||
<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">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Oswald:300,400|Source+Sans+Pro:400,600">
|
||||
<script type="text/javascript" src="speedtest.js"></script>
|
||||
<script type="text/javascript">
|
||||
function I(i){return document.getElementById(i);}
|
||||
function I(i) {
|
||||
return document.getElementById(i);
|
||||
}
|
||||
|
||||
var meterBk = "#ebecf0"; // ui--input-border
|
||||
var dlColor = "#02b159", // grass-green
|
||||
ulColor = "#02b159", // grass-green
|
||||
pingColor = "#02b159", // grass-green
|
||||
jitColor = "#02b159"; // grass-green
|
||||
var progColor = "#0ac9f7"; // sky-blue
|
||||
|
||||
function setPageTitle() {
|
||||
var pageTitleDiv = document.getElementById('pageTitle');
|
||||
var titlePrefixNode = document.createTextNode("You're currently using this server:");
|
||||
var lineBreakElement = document.createElement('br');
|
||||
var locationNode = document.createTextNode('Unknown');
|
||||
switch (window.location.hostname) {
|
||||
case 'us1.zzz.cat':
|
||||
locationNode.textContent = 'Unites States 1 (Fremont, Linode)';
|
||||
break;
|
||||
case 'us2.zzz.cat':
|
||||
locationNode.textContent = 'Unites States 2 (LAX (CN2), Bandwagon)';
|
||||
break;
|
||||
case 'us3.zzz.cat':
|
||||
locationNode.textContent = 'Unites States 3 (LAX (CN2 GIA-E), Bandwagon)';
|
||||
break;
|
||||
case 'jp1.zzz.cat':
|
||||
locationNode.textContent = 'Japan 1 (Tokyo 2, Linode)';
|
||||
break;
|
||||
case 'jp2.zzz.cat':
|
||||
locationNode.textContent = 'Japan 2 (Tokyo 2, Linode)';
|
||||
break;
|
||||
case 'sg1.zzz.cat':
|
||||
locationNode.textContent = 'Singapore (Singapore, Linode)';
|
||||
break;
|
||||
case 'ca1.zzz.cat':
|
||||
locationNode.textContent = 'Canada (Toronto, Linode)';
|
||||
break;
|
||||
default:
|
||||
locationNode.textContent = window.location.hostname;
|
||||
break;
|
||||
}
|
||||
|
||||
pageTitleDiv.appendChild(titlePrefixNode);
|
||||
pageTitleDiv.appendChild(lineBreakElement);
|
||||
pageTitleDiv.appendChild(locationNode);
|
||||
}
|
||||
|
||||
//INITIALIZE SPEEDTEST
|
||||
var s = new Speedtest(); //create speedtest object
|
||||
s.setParameter("telemetry_level","basic"); //enable telemetry
|
||||
s.setParameter("url_telemetry", "results/telemetry");
|
||||
var server = {
|
||||
name: "demo",
|
||||
server:window.location.protocol + "//" + window.location.host,
|
||||
dlURL:"garbage",
|
||||
ulURL:"empty",
|
||||
pingURL:"empty",
|
||||
getIpURL:"getIP",
|
||||
};
|
||||
s.setSelectedServer(server);
|
||||
|
||||
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) {
|
||||
@ -40,22 +72,28 @@ function drawMeter(c,amount,bk,fg,progress,prog){
|
||||
}
|
||||
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.lineWidth = 4 * sizScale;
|
||||
ctx.arc(c.width / 2, c.height / 2, c.height / 2 - ctx.lineWidth, -Math.PI * 1.2, Math.PI * 0.2);
|
||||
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.lineWidth = 4 * sizScale;
|
||||
ctx.arc(c.width / 2, c.height / 2, c.height / 2 - ctx.lineWidth, -Math.PI * 1.2, amount * Math.PI * 1.2 - Math.PI * 1.2);
|
||||
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);
|
||||
ctx.fillRect(c.width * 0.3, c.height - 28 * sizScale, c.width * 0.4 * progress, 4 * sizScale);
|
||||
}
|
||||
}
|
||||
|
||||
function mbpsToAmount(s) {
|
||||
return 1 - (1 / (Math.pow(1.3, Math.sqrt(s))));
|
||||
}
|
||||
|
||||
function msToAmount(s) {
|
||||
return 1 - (1 / (Math.pow(1.08, Math.sqrt(s))));
|
||||
}
|
||||
|
||||
function format(d) {
|
||||
d = Number(d);
|
||||
if (d < 10) return d.toFixed(2);
|
||||
@ -65,6 +103,7 @@ function format(d){
|
||||
|
||||
//UI CODE
|
||||
var uiData = null;
|
||||
|
||||
function startStop() {
|
||||
if (s.getState() == 3) {
|
||||
//speedtest is running, abort
|
||||
@ -87,45 +126,57 @@ function startStop(){
|
||||
try {
|
||||
var testId = uiData.testId;
|
||||
if (testId != null) {
|
||||
var shareURL=window.location.href.substring(0,window.location.href.lastIndexOf("/"))+"/results/?id="+testId;
|
||||
var shareURL = window.location.href.substring(0, window.location.href.lastIndexOf("/")) + "/results?id=" + testId;
|
||||
I("resultsImg").src = shareURL;
|
||||
I("resultsURL").value = shareURL;
|
||||
I("testId").innerHTML = testId;
|
||||
I("shareArea").style.display = "";
|
||||
}
|
||||
}catch(e){}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
};
|
||||
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("ip").textContent = "IP Address: " + 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);
|
||||
drawMeter(I("pingMeter"), msToAmount(Number(uiData.pingStatus * (status == 2 ? oscillate() : 1))), meterBk, pingColor, Number(uiData.pingProgress), progColor);
|
||||
I("jitText").textContent = format(uiData.jitterStatus);
|
||||
drawMeter(I("jitMeter"), msToAmount(Number(uiData.jitterStatus * (status == 2 ? oscillate() : 1))), meterBk, jitColor, Number(uiData.pingProgress), progColor);
|
||||
}
|
||||
|
||||
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);});
|
||||
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);
|
||||
drawMeter(I("pingMeter"), 0, meterBk, pingColor, 0);
|
||||
drawMeter(I("jitMeter"), 0, meterBk, jitColor, 0);
|
||||
I("dlText").textContent = "";
|
||||
I("ulText").textContent = "";
|
||||
I("pingText").textContent = "";
|
||||
@ -133,128 +184,174 @@ function initUI(){
|
||||
I("ip").textContent = "";
|
||||
}
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
:root {
|
||||
--dark-gray: #32363b;
|
||||
--grass-green: #02b159;
|
||||
}
|
||||
|
||||
html, body {
|
||||
border:none; padding:0; margin:0;
|
||||
background:#FFFFFF;
|
||||
color:#202020;
|
||||
background-color: white;
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
color: var(--dark-gray);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
line-height: 1.15;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 18px;
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.33333;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
margin: 1rem 1rem 2rem;
|
||||
text-align: center;
|
||||
font-family:"Roboto",sans-serif;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
h1{
|
||||
color:#404040;
|
||||
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
#startStopBtn {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
color:#6060AA;
|
||||
background-color:rgba(0,0,0,0);
|
||||
border:0.15em solid #6060FF;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
color: white;
|
||||
background-color: var(--grass-green);
|
||||
border: 0.15em solid var(--grass-green);
|
||||
border-radius: 0.3em;
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
width:8em; height:3em;
|
||||
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);
|
||||
/*box-shadow:0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);*/
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#startStopBtn:hover {
|
||||
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
|
||||
/*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;
|
||||
background-color: var(--dark-gray);
|
||||
border-color: var(--dark-gray);
|
||||
color: white;
|
||||
}
|
||||
|
||||
#startStopBtn:before {
|
||||
content:"Start";
|
||||
content: "Start Speed Test";
|
||||
}
|
||||
|
||||
#startStopBtn.running:before {
|
||||
content: "Abort";
|
||||
}
|
||||
|
||||
#test {
|
||||
margin-top:2em;
|
||||
margin-bottom:12em;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
div.testArea {
|
||||
display: inline-block;
|
||||
width:16em;
|
||||
height:12.5em;
|
||||
width: calc(100% - 2rem - 2rem); /* subtract margins */
|
||||
max-width: 16em;
|
||||
margin: 2rem;
|
||||
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{
|
||||
|
||||
div.testArea::before {
|
||||
content: '';
|
||||
display: block;
|
||||
text-align:center;
|
||||
font-size:1.4em;
|
||||
padding-top: 100%;
|
||||
}
|
||||
div.testArea div.meterText{
|
||||
|
||||
div.testName {
|
||||
bottom: 0;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
left: 0;
|
||||
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 {
|
||||
bottom: 1.8em;
|
||||
font-family: "Oswald", sans-serif;
|
||||
font-size: 4em;
|
||||
font-weight: 300;
|
||||
left: 0;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
div.meterText:empty:before {
|
||||
content: "0.00";
|
||||
}
|
||||
div.testArea div.unit{
|
||||
|
||||
div.unit {
|
||||
bottom: 3.5em;
|
||||
font-family: "Oswald", sans-serif;
|
||||
font-size: 1.5em;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.5px;
|
||||
left: 0;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
bottom:2em; left:0;
|
||||
text-transform: uppercase;
|
||||
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%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
div.testGroup{
|
||||
display:block;
|
||||
margin: 0 auto;
|
||||
|
||||
#ipArea {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
#shareArea {
|
||||
width: 95%;
|
||||
max-width:40em;
|
||||
max-width: 25em;
|
||||
margin: 0 auto;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
#shareArea > * {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
#privacyPolicy {
|
||||
position: fixed;
|
||||
top:2em;
|
||||
bottom:2em;
|
||||
left:2em;
|
||||
right:2em;
|
||||
top: 10em;
|
||||
bottom: 10em;
|
||||
left: 15em;
|
||||
right: 15em;
|
||||
overflow-y: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
@ -264,38 +361,80 @@ function initUI(){
|
||||
background-color: #FFFFFF;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#privacyCloseBtn {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
color: white;
|
||||
background-color: var(--grass-green);
|
||||
border: 0.15em solid var(--grass-green);
|
||||
border-radius: 0.3em;
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
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);*/
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#resultsURL {
|
||||
color: #333;
|
||||
font-size: 1.2rem;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 0.2rem;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border: green;
|
||||
display: block;
|
||||
border-style: dashed;
|
||||
border-width: 2px;
|
||||
margin: 0.8em 0 0.8em 0;
|
||||
}
|
||||
|
||||
#testId {
|
||||
margin-top: 1.4em;
|
||||
}
|
||||
|
||||
a.privacy {
|
||||
margin-top: 2em;
|
||||
text-align: center;
|
||||
font-size: 0.8em;
|
||||
color: #808080;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media all and (max-width: 65em) {
|
||||
/* 1040 px */
|
||||
div.testGroup {
|
||||
margin-left: -1rem;
|
||||
margin-right: -1rem;
|
||||
}
|
||||
|
||||
div.testArea {
|
||||
font-size: 1.5384615vw; /* 16 px */
|
||||
margin: 1rem;
|
||||
width: calc(100% - 1rem - 1rem); /* subtract margins */
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 40em) {
|
||||
body{
|
||||
font-size:0.8em;
|
||||
/* 640 px */
|
||||
div.testArea {
|
||||
font-size: 0.8em; /* 12.8 px */
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<title>LibreSpeed Example</title>
|
||||
<title>zzz.cat Speedtest</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>LibreSpeed Example</h1>
|
||||
<div id="testWrapper">
|
||||
<div id="startStopBtn" onclick="startStop()"></div><br/>
|
||||
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''">Privacy</a>
|
||||
<h1 id="pageTitle"></h1>
|
||||
<div id="startStopBtn" onclick="startStop()"></div>
|
||||
<br/>
|
||||
<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>
|
||||
@ -309,18 +448,32 @@ function initUI(){
|
||||
<div id="ulText" class="meterText"></div>
|
||||
<div class="unit">Mbit/s</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Ping</div>
|
||||
<canvas id="pingMeter" class="meter"></canvas>
|
||||
<div id="pingText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
|
||||
<div class="testArea">
|
||||
<div class="testName">Jitter</div>
|
||||
<canvas id="jitMeter" class="meter"></canvas>
|
||||
<div id="jitText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipArea">
|
||||
<span id="ip"></span>
|
||||
</div>
|
||||
<div><a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''">Privacy</a></div>
|
||||
<div id="shareArea" style="display:none">
|
||||
<h3>Share results</h3>
|
||||
<p>Test ID: <span id="testId"></span></p>
|
||||
<input type="text" value="" id="resultsURL" readonly="readonly" onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')"/>
|
||||
<h3>Share your results</h3>
|
||||
<input type="text" value="" id="resultsURL" readonly="readonly"
|
||||
onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')"/>
|
||||
<img src="" id="resultsImg"/>
|
||||
<p>Test ID: <span id="testId"></span></p>
|
||||
</div>
|
||||
</div>
|
||||
<a href="https://github.com/librespeed/speedtest">Source code</a>
|
||||
</div>
|
||||
<div id="privacyPolicy" style="display:none">
|
||||
<h2>Privacy Policy</h2>
|
||||
@ -354,12 +507,17 @@ function initUI(){
|
||||
</p>
|
||||
<h4>Data removal</h4>
|
||||
<p>
|
||||
If you want to have your information deleted, you need to provide either the ID of the test or your IP address. This is the only way to identify your data, without this information we won't be able to comply with your request.<br/><br/>
|
||||
Contact this email address for all deletion requests: <a href="mailto:PUT@YOUR_EMAIL.HERE">TO BE FILLED BY DEVELOPER</a>.
|
||||
If you want to have your information deleted, you need to provide either the ID of the test or your IP address.
|
||||
This is the only way to identify your data, without this information we won't be able to comply with your
|
||||
request.<br/><br/>
|
||||
Contact this email address for all deletion requests: maddie at zzz dot cat.
|
||||
</p>
|
||||
<br/><br/>
|
||||
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display='none'">Close</a><br/>
|
||||
<a id="privacyCloseBtn" class="privacy" href="#" onclick="I('privacyPolicy').style.display='none'">Close</a><br/>
|
||||
</div>
|
||||
<script type="text/javascript">setTimeout(function(){initUI()},100);</script>
|
||||
<script type="text/javascript">setPageTitle();</script>
|
||||
<script type="text/javascript">setTimeout(function () {
|
||||
initUI()
|
||||
}, 100);</script>
|
||||
</body>
|
||||
</html>
|
||||
|
508
assets/linode.html
Normal file
508
assets/linode.html
Normal file
@ -0,0 +1,508 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no"/>
|
||||
|
||||
<title>zzz.cat Speedtest</title>
|
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Oswald:300,400|Source+Sans+Pro:400,600"
|
||||
type="text/css" media="all"/>
|
||||
|
||||
<style type="text/css">
|
||||
:root {
|
||||
--dark-gray: #32363b;
|
||||
--grass-green: #02b159;
|
||||
}
|
||||
|
||||
html, body {
|
||||
background-color: white;
|
||||
border: none;
|
||||
box-sizing: border-box;
|
||||
color: var(--dark-gray);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
line-height: 1.15;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 18px;
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.33333;
|
||||
font-family: "Source Sans Pro", sans-serif;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0;
|
||||
margin: 1rem 1rem 2rem;
|
||||
text-align: center;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
#startStopBtn {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
color: white;
|
||||
background-color: var(--grass-green);
|
||||
border: 0.15em solid var(--grass-green);
|
||||
border-radius: 0.3em;
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
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);*/
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#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: var(--dark-gray);
|
||||
border-color: var(--dark-gray);
|
||||
color: white;
|
||||
}
|
||||
|
||||
#startStopBtn:before {
|
||||
content: "Start Speed Test";
|
||||
}
|
||||
|
||||
#startStopBtn.running:before {
|
||||
content: "Abort";
|
||||
}
|
||||
|
||||
#test {
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
div.testArea {
|
||||
display: inline-block;
|
||||
width: calc(100% - 2rem - 2rem); /* subtract margins */
|
||||
max-width: 16em;
|
||||
margin: 2rem;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
div.testArea::before {
|
||||
content: '';
|
||||
display: block;
|
||||
padding-top: 100%;
|
||||
}
|
||||
|
||||
div.testName {
|
||||
bottom: 0;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
div.meterText {
|
||||
bottom: 1.8em;
|
||||
font-family: "Oswald", sans-serif;
|
||||
font-size: 4em;
|
||||
font-weight: 300;
|
||||
left: 0;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
div.meterText:empty:before {
|
||||
content: "0.00";
|
||||
}
|
||||
|
||||
div.unit {
|
||||
bottom: 3.5em;
|
||||
font-family: "Oswald", sans-serif;
|
||||
font-size: 1.5em;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.5px;
|
||||
left: 0;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
text-transform: uppercase;
|
||||
width: 100%;
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
div.testArea canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#ipArea {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
#shareArea {
|
||||
width: 95%;
|
||||
max-width: 40em;
|
||||
margin: 0 auto;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
#shareArea > * {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 0.25em 0;
|
||||
}
|
||||
|
||||
#privacyPolicy {
|
||||
position: fixed;
|
||||
top: 10em;
|
||||
bottom: 10em;
|
||||
left: 15em;
|
||||
right: 15em;
|
||||
overflow-y: auto;
|
||||
width: auto;
|
||||
height: auto;
|
||||
box-shadow: 0 0 3em 1em #000000;
|
||||
z-index: 999999;
|
||||
text-align: left;
|
||||
background-color: #FFFFFF;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
#privacyCloseBtn {
|
||||
display: inline-block;
|
||||
margin: 0 auto;
|
||||
padding-left: 2rem;
|
||||
padding-right: 2rem;
|
||||
color: white;
|
||||
background-color: var(--grass-green);
|
||||
border: 0.15em solid var(--grass-green);
|
||||
border-radius: 0.3em;
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
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);*/
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
a.privacy {
|
||||
margin-top: 2em;
|
||||
text-align: center;
|
||||
font-size: 0.8em;
|
||||
color: #808080;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media all and (max-width: 65em) {
|
||||
/* 1040 px */
|
||||
div.testGroup {
|
||||
margin-left: -1rem;
|
||||
margin-right: -1rem;
|
||||
}
|
||||
|
||||
div.testArea {
|
||||
font-size: 1.5384615vw; /* 16 px */
|
||||
margin: 1rem;
|
||||
width: calc(100% - 1rem - 1rem); /* subtract margins */
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: 40em) {
|
||||
/* 640 px */
|
||||
div.testArea {
|
||||
font-size: 0.8em; /* 12.8 px */
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
function I(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
var meterBk = "#ebecf0"; // ui--input-border
|
||||
var dlColor = "#02b159", // grass-green
|
||||
ulColor = "#02b159", // grass-green
|
||||
pingColor = "#02b159", // grass-green
|
||||
jitColor = "#02b159"; // grass-green
|
||||
var progColor = "#0ac9f7"; // sky-blue
|
||||
|
||||
function setPageTitle() {
|
||||
var pageTitleDiv = document.getElementById('pageTitle');
|
||||
var titlePrefixNode = document.createTextNode('Speed Test:');
|
||||
var lineBreakElement = document.createElement('br');
|
||||
var locationNode = document.createTextNode('Unknown');
|
||||
switch (window.location.hostname) {
|
||||
case 'us1.zzz.cat':
|
||||
locationNode.textContent = 'Unites States 1 (Fremont, Linode)';
|
||||
break;
|
||||
case 'us2.zzz.cat':
|
||||
locationNode.textContent = 'Unites States 2 (LAX (CN2), Bandwagon)';
|
||||
break;
|
||||
case 'us3.zzz.cat':
|
||||
locationNode.textContent = 'Unites States 3 (LAX (CN2 GIA-E), Bandwagon)';
|
||||
break;
|
||||
case 'jp1.zzz.cat':
|
||||
locationNode.textContent = 'Japan 1 (Tokyo 2, Linode)';
|
||||
break;
|
||||
case 'jp2.zzz.cat':
|
||||
locationNode.textContent = 'Japan 2 (Tokyo 2, Linode)';
|
||||
break;
|
||||
case 'sg1.zzz.cat':
|
||||
locationNode.textContent = 'Singapore (Singapore, Linode)';
|
||||
break;
|
||||
case 'ca1.zzz.cat':
|
||||
locationNode.textContent = 'Canada (Toronto, Linode)';
|
||||
break;
|
||||
default:
|
||||
locationNode.textContent = window.location.hostname;
|
||||
break;
|
||||
}
|
||||
|
||||
pageTitleDiv.appendChild(titlePrefixNode);
|
||||
pageTitleDiv.appendChild(lineBreakElement);
|
||||
pageTitleDiv.appendChild(locationNode);
|
||||
}
|
||||
|
||||
//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.lineCap = "round";
|
||||
ctx.lineWidth = 4 * sizScale;
|
||||
ctx.arc(
|
||||
c.width / 2,
|
||||
c.height / 2,// c.height/2-58*sizScale,
|
||||
c.height / 2 - ctx.lineWidth,//c.height/1.8-ctx.lineWidth,
|
||||
-Math.PI * 1.2,
|
||||
Math.PI * 0.2
|
||||
);
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = fg;
|
||||
ctx.lineCap = (amount > 0 ? "round" : "butt");
|
||||
ctx.lineWidth = 4 * sizScale;
|
||||
ctx.arc(
|
||||
c.width / 2,
|
||||
c.height / 2,// c.height/2-58*sizScale,
|
||||
c.height / 2 - ctx.lineWidth,//c.height/1.8-ctx.lineWidth,
|
||||
-Math.PI * 1.2,
|
||||
amount * Math.PI * 1.2 - Math.PI * 1.2
|
||||
);
|
||||
ctx.stroke();
|
||||
if (typeof progress !== "undefined") {
|
||||
ctx.fillStyle = prog;
|
||||
ctx.fillRect(
|
||||
c.width * 0.3,
|
||||
c.height - 28 * sizScale,
|
||||
c.width * 0.4 * progress,
|
||||
4 * sizScale
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mbpsToAmount(s) {
|
||||
return 1 - (1 / (Math.pow(1.3, Math.sqrt(s))));
|
||||
}
|
||||
|
||||
function msToAmount(s) {
|
||||
return 1 - (1 / (Math.pow(1.08, Math.sqrt(s))));
|
||||
}
|
||||
|
||||
//SPEEDTEST AND UI CODE
|
||||
var w = null; //speedtest worker
|
||||
var data = null; //data from worker
|
||||
function startStop() {
|
||||
if (w != null) {
|
||||
//speedtest is running, abort
|
||||
w.postMessage('abort');
|
||||
w = null;
|
||||
data = null;
|
||||
I("startStopBtn").className = "";
|
||||
initUI();
|
||||
} else {
|
||||
//test is not running, begin
|
||||
w = new Worker('speedtest_worker.js');
|
||||
w.postMessage('start'); //Add optional parameters as a JSON object to this command
|
||||
I("startStopBtn").className = "running";
|
||||
w.onmessage = function (e) {
|
||||
data = JSON.parse(e.data);
|
||||
var status = data.testState;
|
||||
if (status >= 4) {
|
||||
//test completed
|
||||
I("startStopBtn").className = "";
|
||||
w = null;
|
||||
updateUI(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//this function reads the data sent back by the worker and updates the UI
|
||||
function updateUI(forced) {
|
||||
if (!forced && (!data || !w)) return;
|
||||
console.log(data);
|
||||
var status = data.testState;
|
||||
I("ip").textContent = data.clientIp;
|
||||
I("dlText").textContent = (status == 1 && data.dlStatus == 0) ? "..." : data.dlStatus;
|
||||
drawMeter(I("dlMeter"), mbpsToAmount(Number(data.dlStatus * (status == 1 ? oscillate() : 1))), meterBk, dlColor, Number(data.dlProgress), progColor);
|
||||
I("ulText").textContent = (status == 3 && data.ulStatus == 0) ? "..." : data.ulStatus;
|
||||
drawMeter(I("ulMeter"), mbpsToAmount(Number(data.ulStatus * (status == 3 ? oscillate() : 1))), meterBk, ulColor, Number(data.ulProgress), progColor);
|
||||
I("pingText").textContent = data.pingStatus;
|
||||
drawMeter(I("pingMeter"), msToAmount(Number(data.pingStatus * (status == 2 ? oscillate() : 1))), meterBk, pingColor, Number(data.pingProgress), progColor);
|
||||
I("jitText").textContent = data.jitterStatus;
|
||||
drawMeter(I("jitMeter"), msToAmount(Number(data.jitterStatus * (status == 2 ? oscillate() : 1))), meterBk, jitColor, Number(data.pingProgress), progColor);
|
||||
}
|
||||
|
||||
function oscillate() {
|
||||
return 1 + 0.02 * Math.sin(Date.now() / 100);
|
||||
}
|
||||
|
||||
//poll the status from the worker (this will call updateUI)
|
||||
setInterval(function () {
|
||||
if (w) w.postMessage('status');
|
||||
}, 200);
|
||||
//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);
|
||||
drawMeter(I("pingMeter"), 0, meterBk, pingColor, 0);
|
||||
drawMeter(I("jitMeter"), 0, meterBk, jitColor, 0);
|
||||
I("dlText").textContent = "";
|
||||
I("ulText").textContent = "";
|
||||
I("pingText").textContent = "";
|
||||
I("jitText").textContent = "";
|
||||
I("ip").textContent = "";
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<h1 id="pageTitle"></h1>
|
||||
<div id="test">
|
||||
<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">Mbit/s</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">Mbit/s</div>
|
||||
</div>
|
||||
<div class="testArea">
|
||||
<div class="testName">Ping</div>
|
||||
<canvas id="pingMeter" class="meter"></canvas>
|
||||
<div id="pingText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
|
||||
<div class="testArea">
|
||||
<div class="testName">Jitter</div>
|
||||
<canvas id="jitMeter" class="meter"></canvas>
|
||||
<div id="jitText" class="meterText"></div>
|
||||
<div class="unit">ms</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="ipArea">
|
||||
IP Address: <span id="ip"></span>
|
||||
</div>
|
||||
<div id="shareArea" style="display:none">
|
||||
<h3>Share results</h3>
|
||||
<p>Test ID: <span id="testId"></span></p>
|
||||
<input type="text" value="" id="resultsURL" readonly="readonly"
|
||||
onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')"/>
|
||||
<img src="" id="resultsImg"/>
|
||||
</div>
|
||||
</div>
|
||||
<div id="startStopBtn" onclick="startStop()"></div>
|
||||
<div id="privacyPolicy" style="display:none;">
|
||||
<h2>Privacy Policy</h2>
|
||||
<p>This HTML5 Speedtest server is configured with telemetry enabled.</p>
|
||||
<h4>What data we collect</h4>
|
||||
<p>
|
||||
At the end of the test, the following data is collected and stored:
|
||||
<ul>
|
||||
<li>Test ID</li>
|
||||
<li>Time of testing</li>
|
||||
<li>Test results (download and upload speed, ping and jitter)</li>
|
||||
<li>IP address</li>
|
||||
<li>ISP information</li>
|
||||
<li>Approximate location (inferred from IP address, not GPS)</li>
|
||||
<li>User agent and browser locale</li>
|
||||
<li>Test log (contains no personal information)</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h4>How we use the data</h4>
|
||||
<p>
|
||||
Data collected through this service is used to:
|
||||
<ul>
|
||||
<li>Allow sharing of test results (sharable image for forums, etc.)</li>
|
||||
<li>To improve the service offered to you (for instance, to detect problems on our side)</li>
|
||||
</ul>
|
||||
No personal information is disclosed to third parties.
|
||||
</p>
|
||||
<h4>Your consent</h4>
|
||||
<p>
|
||||
By starting the test, you consent to the terms of this privacy policy.
|
||||
</p>
|
||||
<h4>Data removal</h4>
|
||||
<p>
|
||||
If you want to have your information deleted, you need to provide either the ID of the test or your IP
|
||||
address. This is the only way to identify your data, without this information we won't be able to comply
|
||||
with your request.<br/><br/>
|
||||
Contact this email address for all deletion requests: maddie at zzz dot cat</a>.
|
||||
</p>
|
||||
<br/><br/>
|
||||
<a id="privacyCloseBtn" class="privacy" href="#"
|
||||
onclick="I('privacyPolicy').style.display='none'">Close</a><br/>
|
||||
</div>
|
||||
<div><a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''">Privacy</a></div>
|
||||
</div>
|
||||
<script type="text/javascript">setPageTitle();</script>
|
||||
<script type="text/javascript">setTimeout(initUI, 100);</script>
|
||||
</body>
|
||||
</html>
|
30
assets/speedtest.js
Normal file → Executable file
30
assets/speedtest.js
Normal file → Executable file
@ -28,8 +28,8 @@
|
||||
While in state 1, you can only add test points, you cannot change the test settings. When you're done, use selectServer(callback) to select the test point with the lowest ping. This is asynchronous, when it's done, it will call your callback function and move to state 2. Calling setSelectedServer(server) will manually select a server and move to state 2.
|
||||
- 2: test point selected, ready to start the test. Use start() to begin, this will move to state 3
|
||||
- 3: test running. Here, your onupdate event calback will be called periodically, with data coming from the worker about speed and progress. A data object will be passed to your onupdate function, with the following items:
|
||||
- dlStatus: download speed in Mbit/s
|
||||
- ulStatus: upload speed in Mbit/s
|
||||
- dlStatus: download speed in mbps
|
||||
- ulStatus: upload speed in mbps
|
||||
- pingStatus: ping in ms
|
||||
- jitterStatus: jitter in ms
|
||||
- dlProgress: progress of the download test as a float 0-1
|
||||
@ -49,7 +49,7 @@ function Speedtest() {
|
||||
this._settings = {}; //settings for the speedtest worker
|
||||
this._state = 0; //0=adding settings, 1=adding servers, 2=server selection done, 3=test running, 4=done
|
||||
console.log(
|
||||
"LibreSpeed by Federico Dossena v5.2 - https://github.com/librespeed/speedtest"
|
||||
"LibreSpeed by Federico Dossena v5.2.4 - https://github.com/librespeed/speedtest"
|
||||
);
|
||||
}
|
||||
|
||||
@ -69,10 +69,10 @@ Speedtest.prototype = {
|
||||
* Invalid values or nonexistant parameters will be ignored by the speedtest worker.
|
||||
*/
|
||||
setParameter: function(parameter, value) {
|
||||
if (this._state != 0)
|
||||
throw "You cannot change the test settings after adding server or starting the test";
|
||||
if (this._state == 3)
|
||||
throw "You cannot change the test settings while running the test";
|
||||
this._settings[parameter] = value;
|
||||
if(parameter === "temeletry_extra"){
|
||||
if(parameter === "telemetry_extra"){
|
||||
this._originalExtra=this._settings.telemetry_extra;
|
||||
}
|
||||
},
|
||||
@ -191,9 +191,9 @@ Speedtest.prototype = {
|
||||
throw "You can't select a server while the test is running";
|
||||
}
|
||||
if (this._selectServerCalled) throw "selectServer already called"; else this._selectServerCalled=true;
|
||||
/*this function goes through a list of servers. For each server, the ping is measured, then the server with the function result is called with the best server, or null if all the servers were down.
|
||||
/*this function goes through a list of servers. For each server, the ping is measured, then the server with the function selected is called with the best server, or null if all the servers were down.
|
||||
*/
|
||||
var select = function(serverList, result) {
|
||||
var select = function(serverList, selected) {
|
||||
//pings the specified URL, then calls the function result. Result will receive a parameter which is either the time it took to ping the URL, or -1 if something went wrong.
|
||||
var PING_TIMEOUT = 2000;
|
||||
var USE_PING_TIMEOUT = true; //will be disabled on unsupported browsers
|
||||
@ -201,7 +201,7 @@ Speedtest.prototype = {
|
||||
//IE11 doesn't support XHR timeout
|
||||
USE_PING_TIMEOUT = false;
|
||||
}
|
||||
var ping = function(url, result) {
|
||||
var ping = function(url, rtt) {
|
||||
url += (url.match(/\?/) ? "&" : "?") + "cors=true";
|
||||
var xhr = new XMLHttpRequest();
|
||||
var t = new Date().getTime();
|
||||
@ -217,11 +217,11 @@ Speedtest.prototype = {
|
||||
if (d <= 0) d = p.duration;
|
||||
if (d > 0 && d < instspd) instspd = d;
|
||||
} catch (e) {}
|
||||
result(instspd);
|
||||
} else result(-1);
|
||||
rtt(instspd);
|
||||
} else rtt(-1);
|
||||
}.bind(this);
|
||||
xhr.onerror = function() {
|
||||
result(-1);
|
||||
rtt(-1);
|
||||
}.bind(this);
|
||||
xhr.open("GET", url);
|
||||
if (USE_PING_TIMEOUT) {
|
||||
@ -271,7 +271,7 @@ Speedtest.prototype = {
|
||||
)
|
||||
bestServer = serverList[i];
|
||||
}
|
||||
result(bestServer);
|
||||
selected(bestServer);
|
||||
}.bind(this);
|
||||
var nextServer = function() {
|
||||
if (i == serverList.length) {
|
||||
@ -330,13 +330,13 @@ Speedtest.prototype = {
|
||||
console.error("Speedtest onupdate event threw exception: " + e);
|
||||
}
|
||||
if (data.testState >= 4) {
|
||||
clearInterval(this.updater);
|
||||
this._state = 4;
|
||||
try {
|
||||
if (this.onend) this.onend(data.testState == 5);
|
||||
} catch (e) {
|
||||
console.error("Speedtest onend event threw exception: " + e);
|
||||
}
|
||||
clearInterval(this.updater);
|
||||
this._state = 4;
|
||||
}
|
||||
}.bind(this);
|
||||
this.updater = setInterval(
|
||||
|
29
assets/speedtest_worker.js
Normal file → Executable file
29
assets/speedtest_worker.js
Normal file → Executable file
@ -7,11 +7,11 @@
|
||||
|
||||
// data reported to main thread
|
||||
var testState = -1; // -1=not started, 0=starting, 1=download test, 2=ping+jitter test, 3=upload test, 4=finished, 5=abort
|
||||
var dlStatus = ""; // download speed in Mbit/s with 2 decimal digits
|
||||
var ulStatus = ""; // upload speed in Mbit/s with 2 decimal digits
|
||||
var dlStatus = ""; // download speed in megabit/s with 2 decimal digits
|
||||
var ulStatus = ""; // upload speed in megabit/s with 2 decimal digits
|
||||
var pingStatus = ""; // ping in milliseconds with 2 decimal digits
|
||||
var jitterStatus = ""; // jitter in milliseconds with 2 decimal digits
|
||||
var clientIp = ""; // client's IP address as reported by getIP
|
||||
var clientIp = ""; // client's IP address as reported by getIP.php
|
||||
var dlProgress = 0; //progress of download test 0-1
|
||||
var ulProgress = 0; //progress of upload test 0-1
|
||||
var pingProgress = 0; //progress of ping+jitter test 0-1
|
||||
@ -45,10 +45,10 @@ var settings = {
|
||||
time_ulGraceTime: 3, //time to wait in seconds before actually measuring ul speed (wait for buffers to fill)
|
||||
time_dlGraceTime: 1.5, //time to wait in seconds before actually measuring dl speed (wait for TCP window to increase)
|
||||
count_ping: 10, // number of pings to perform in ping test
|
||||
url_dl: "backend/garbage", // path to a large file or garbage.php, used for download test. must be relative to this js file
|
||||
url_ul: "backend/empty", // path to an empty file, used for upload test. must be relative to this js file
|
||||
url_ping: "backend/empty", // path to an empty file, used for ping test. must be relative to this js file
|
||||
url_getIp: "backend/getIP", // path to getIP.php relative to this js file, or a similar thing that outputs the client's ip
|
||||
url_dl: "backend/garbage.php", // path to a large file or garbage.php, used for download test. must be relative to this js file
|
||||
url_ul: "backend/empty.php", // path to an empty file, used for upload test. must be relative to this js file
|
||||
url_ping: "backend/empty.php", // path to an empty file, used for ping test. must be relative to this js file
|
||||
url_getIp: "backend/getIP.php", // path to getIP.php relative to this js file, or a similar thing that outputs the client's ip
|
||||
getIp_ispInfo: true, //if set to true, the server will include ISP info with the IP address
|
||||
getIp_ispInfo_distance: "km", //km or mi=estimate distance from server in km/mi; set to false to disable distance estimation. getIp_ispInfo must be enabled in order for this to work
|
||||
xhr_dlMultistream: 6, // number of download streams to use (can be different if enable_quirks is active)
|
||||
@ -61,10 +61,11 @@ var settings = {
|
||||
enable_quirks: true, // enable quirks for specific browsers. currently it overrides settings to optimize for specific browsers, unless they are already being overridden with the start command
|
||||
ping_allowPerformanceApi: true, // if enabled, the ping test will attempt to calculate the ping more precisely using the Performance API. Currently works perfectly in Chrome, badly in Edge, and not at all in Firefox. If Performance API is not supported or the result is obviously wrong, a fallback is provided.
|
||||
overheadCompensationFactor: 1.06, //can be changed to compensatie for transport overhead. (see doc.md for some other values)
|
||||
useMebibits: false, //if set to true, speed will be reported in Mibit/s instead of Mbit/s
|
||||
useMebibits: false, //if set to true, speed will be reported in mebibits/s instead of megabits/s
|
||||
telemetry_level: 0, // 0=disabled, 1=basic (results only), 2=full (results and timing) 3=debug (results+log)
|
||||
url_telemetry: "results/telemetry", // path to the script that adds telemetry data to the database
|
||||
telemetry_extra: "" //extra data that can be passed to the telemetry through the settings
|
||||
url_telemetry: "results/telemetry.php", // path to the script that adds telemetry data to the database
|
||||
telemetry_extra: "", //extra data that can be passed to the telemetry through the settings
|
||||
forceIE11Workaround: false //when set to true, it will foce the IE11 upload test on all browsers. Debug only
|
||||
};
|
||||
|
||||
var xhr = null; // array of currently active xhr requests
|
||||
@ -403,8 +404,8 @@ function dlTest(done) {
|
||||
var speed = totLoaded / (t / 1000.0);
|
||||
if (settings.time_auto) {
|
||||
//decide how much to shorten the test. Every 200ms, the test is shortened by the bonusT calculated here
|
||||
var bonus = (6.4 * speed) / 100000;
|
||||
bonusT += bonus > 800 ? 800 : bonus;
|
||||
var bonus = (5.0 * speed) / 100000;
|
||||
bonusT += bonus > 400 ? 400 : bonus;
|
||||
}
|
||||
//update status
|
||||
dlStatus = ((speed * 8 * settings.overheadCompensationFactor) / (settings.useMebibits ? 1048576 : 1000000)).toFixed(2); // speed is multiplied by 8 to go from bytes to bits, overhead compensation is applied, then everything is divided by 1048576 or 1000000 to go to megabits/mebibits
|
||||
@ -551,8 +552,8 @@ function ulTest(done) {
|
||||
var speed = totLoaded / (t / 1000.0);
|
||||
if (settings.time_auto) {
|
||||
//decide how much to shorten the test. Every 200ms, the test is shortened by the bonusT calculated here
|
||||
var bonus = (6.4 * speed) / 100000;
|
||||
bonusT += bonus > 800 ? 800 : bonus;
|
||||
var bonus = (5.0 * speed) / 100000;
|
||||
bonusT += bonus > 400 ? 400 : bonus;
|
||||
}
|
||||
//update status
|
||||
ulStatus = ((speed * 8 * settings.overheadCompensationFactor) / (settings.useMebibits ? 1048576 : 1000000)).toFixed(2); // speed is multiplied by 8 to go from bytes to bits, overhead compensation is applied, then everything is divided by 1048576 or 1000000 to go to megabits/mebibits
|
||||
|
Loading…
Reference in New Issue
Block a user