69 |
70 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/js/thecore.js:
--------------------------------------------------------------------------------
1 | var w=null;
2 | var ggdl,ggul,ggping;
3 | function runTest(){
4 | w=new Worker("speedtest_worker.min.js");
5 | var interval=setInterval(function(){w.postMessage("status");}.bind(this),100);
6 | document.getElementById("abortBtn").style.display="";
7 | document.getElementById("startBtn").style.display="none";
8 | w.onmessage=function(event){
9 | var data=event.data.split(";");
10 | var status=Number(data[0]);
11 | if(status>=4){
12 | clearInterval(interval);
13 | document.getElementById("abortBtn").style.display="none";
14 | document.getElementById("startBtn").style.display="";
15 | w=null;
16 | }
17 | updateGauge(ggdl, data[1]);
18 | updateGauge(ggul, data[2]);
19 | updateGauge(ggping, data[3]);
20 | document.getElementById("ip").innerHTML="Your IP : " +data[4];
21 | document.getElementById("isp").innerHTML="Your ISP : " +data[6];
22 | updateGauge(ggjitter, data[5]);
23 | }.bind(this);
24 | w.postMessage('start {"time_ul":"10", "time_dl":"10", "count_ping":"50", "url_dl":"garbage.php","url_ul":"empty.dat","url_ping":"empty.dat","url_getIp":"getIP.php","url_getIsp":"getISP.php"}');
25 | }
26 | function abortTest(){
27 | if(w)w.postMessage("abort");
28 | }
29 |
30 | document.addEventListener("DOMContentLoaded", function(event) {
31 | ggdl = new JustGage({
32 | id: 'ggdl',
33 | title: "Download",
34 | label: "Mbit/s",
35 | titleFontFamily : "Open Sans",
36 | valueFontFamily : "Open Sans",
37 | refreshAnimationTime: 300,
38 | value: 0,
39 | min: 0,
40 | max: 10,
41 | decimals : 2,
42 | formatNumber: true,
43 | humanFriendly : false,
44 | levelColors: [
45 | "#999999",
46 | "#339933"
47 | ]
48 | });
49 |
50 | ggul = new JustGage({
51 | id: 'ggul',
52 | title: "Upload",
53 | label: "Mbit/s",
54 | titleFontFamily : "Open Sans",
55 | valueFontFamily : "Open Sans",
56 | refreshAnimationTime: 300,
57 | value: 0,
58 | min: 0,
59 | max: 10,
60 | decimals : 2,
61 | formatNumber: true,
62 | humanFriendly : false,
63 | levelColors: [
64 | "#999999",
65 | "#333399"
66 | ]
67 |
68 | });
69 |
70 | ggping = new JustGage({
71 | id: 'ggping',
72 | title: "Ping",
73 | label: "ms",
74 | titleFontFamily : "Open Sans",
75 | valueFontFamily : "Open Sans",
76 | refreshAnimationTime: 300,
77 | value: 0,
78 | min: 0,
79 | max: 100,
80 | decimals : 2,
81 | formatNumber: true,
82 | humanFriendly : false,
83 | levelColors: [
84 | "#999999",
85 | "#993333"
86 | ]
87 | });
88 | ggjitter = new JustGage({
89 | id: 'ggjitter',
90 | title: "Jitter",
91 | label: "ms",
92 | titleFontFamily : "Open Sans",
93 | valueFontFamily : "Open Sans",
94 | refreshAnimationTime: 300,
95 | value: 0,
96 | min: 0,
97 | max: 100,
98 | decimals : 2,
99 | formatNumber: true,
100 | humanFriendly : false,
101 | levelColors: [
102 | "#999999",
103 | "#993333"
104 | ]
105 | });
106 | });
107 |
108 | function updateGauge(gauge, value)
109 | {
110 | // Alway use next power of 2 as maximum
111 | var max = Math.max(Math.pow(2, Math.ceil(Math.log2(value))), gauge.config.max);
112 | // Refresh the gauge
113 | gauge.refresh(value, max);
114 | }
115 |
--------------------------------------------------------------------------------
/speedtest_worker.js:
--------------------------------------------------------------------------------
1 | /*
2 | HTML5 Speedtest v4.1
3 | by Federico Dossena
4 | https://github.com/adolfintel/speedtest/
5 | GNU LGPLv3 License
6 | */
7 |
8 | //data reported to main thread
9 | var testStatus=0, //0=not started, 1=download test, 2=ping+jitter test, 3=upload test, 4=finished, 5=abort/error
10 | dlStatus="", //download speed in megabit/s with 2 decimal digits
11 | ulStatus="", //upload speed in megabit/s with 2 decimal digits
12 | pingStatus="", //ping in milliseconds with 2 decimal digits
13 | jitterStatus="", //jitter in milliseconds with 2 decimal digits
14 | clientIp=""; //client's IP address as reported by getIP.php
15 |
16 | //test settings. can be overridden by sending specific values with the start command
17 | var settings={
18 | time_ul:15, //duration of upload test in seconds
19 | time_dl:15, //duration of download test in seconds
20 | count_ping:35, //number of pings to perform in ping test
21 | url_dl:"garbage.php", //path to a large file or garbage.php, used for download test. must be relative to this js file
22 | url_ul:"empty.dat", //path to an empty file, used for upload test. must be relative to this js file
23 | url_ping:"empty.dat", //path to an empty file, used for ping test. must be relative to this js file
24 | url_getIp:"getIP.php", //path to getIP.php relative to this js file, or a similar thing that outputs the client's ip
25 | xhr_dlMultistream:10, //number of download streams to use (can be different if enable_quirks is active)
26 | xhr_ulMultistream:3, //number of upload streams to use (can be different if enable_quirks is active)
27 | xhr_dlUseBlob:false, //if set to true, it reduces ram usage but uses the hard drive (useful with large garbagePhp_chunkSize and/or high xhr_dlMultistream)
28 | garbagePhp_chunkSize:20, //size of chunks sent by garbage.php (can be different if enable_quirks is active)
29 | 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
30 | allow_fetchAPI:false, //enables Fetch API. currently disabled because it leaks memory like no tomorrow
31 | force_fetchAPI:false //when Fetch API is enabled, it will force usage on every browser that supports it
32 | };
33 |
34 | var xhr=null, //array of currently active xhr requests
35 | interval=null; //timer used in tests
36 |
37 | /*
38 | when set to true (automatically) the download test will use the fetch api instead of xhr.
39 | fetch api is used if
40 | -allow_fetchAPI is true AND
41 | -(we're on chrome that supports fetch api AND enable_quirks is true) OR (we're on any browser that supports fetch api AND force_fetchAPI is true)
42 | */
43 | var useFetchAPI=false;
44 |
45 | /*
46 | listener for commands from main thread to this worker.
47 | commands:
48 | -status: returns the current status as a string of values spearated by a semicolon (;) in this order: testStatus;dlStatus;ulStatus;pingStatus;clientIp;jitterStatus
49 | -abort: aborts the current test
50 | -start: starts the test. optionally, settings can be passed as JSON.
51 | example: start {"time_ul":"10", "time_dl":"10", "count_ping":"50"}
52 | */
53 | this.addEventListener('message', function(e){
54 | var params=e.data.split(" ");
55 | if(params[0]=="status"){ //return status
56 | postMessage(testStatus+";"+dlStatus+";"+ulStatus+";"+pingStatus+";"+clientIp+";"+jitterStatus);
57 | }
58 | if(params[0]=="start"&&testStatus==0){ //start new test
59 | testStatus=1;
60 | try{
61 | //parse settings, if present
62 | var s=JSON.parse(e.data.substring(5));
63 | if(typeof s.url_dl != "undefined") settings.url_dl=s.url_dl; //download url
64 | if(typeof s.url_ul != "undefined") settings.url_ul=s.url_ul; //upload url
65 | if(typeof s.url_ping != "undefined") settings.url_ping=s.url_ping; //ping url
66 | if(typeof s.url_getIp != "undefined") settings.url_getIp=s.url_getIp; //url to getIP.php
67 | if(typeof s.time_dl != "undefined") settings.time_dl=s.time_dl; //duration of download test
68 | if(typeof s.time_ul != "undefined") settings.time_ul=s.time_ul; //duration of upload test
69 | if(typeof s.enable_quirks != "undefined") settings.enable_quirks=s.enable_quirks; //enable quirks or not
70 | if(typeof s.allow_fetchAPI != "undefined") settings.allow_fetchAPI=s.allow_fetchAPI; //allows fetch api to be used if supported
71 | //quirks for specific browsers. more may be added in future releases
72 | if(settings.enable_quirks){
73 | var ua=navigator.userAgent;
74 | if(/Firefox.(\d+\.\d+)/i.test(ua)){
75 | //ff more precise with 1 upload stream
76 | settings.xhr_ulMultistream=1;
77 | }
78 | if(/Edge.(\d+\.\d+)/i.test(ua)){
79 | //edge more precise with 3 download streams
80 | settings.xhr_dlMultistream=3;
81 | }
82 | if((/Safari.(\d+)/i.test(ua))&&!(/Chrome.(\d+)/i.test(ua))){
83 | //safari more precise with 10 upload streams and 5mb chunks for download test
84 | settings.xhr_ulMultistream=10;
85 | settings.garbagePhp_chunkSize=5;
86 | }
87 | if(/Chrome.(\d+)/i.test(ua)&&(!!self.fetch)){
88 | //chrome can't handle large xhr very well, use fetch api if available and allowed
89 | if(settings.allow_fetchAPI) useFetchAPI=true;
90 | //chrome more precise with 5 streams
91 | settings.xhr_dlMultistream=5;
92 | }
93 | }
94 | if(typeof s.count_ping != "undefined") settings.count_ping=s.count_ping; //number of pings for ping test
95 | if(typeof s.xhr_dlMultistream != "undefined") settings.xhr_dlMultistream=s.xhr_dlMultistream; //number of download streams
96 | if(typeof s.xhr_ulMultistream != "undefined") settings.xhr_ulMultistream=s.xhr_ulMultistream; //number of upload streams
97 | if(typeof s.xhr_dlUseBlob != "undefined") settings.xhr_dlUseBlob=s.xhr_dlUseBlob; //use blob for download test
98 | if(typeof s.garbagePhp_chunkSize != "undefined") settings.garbagePhp_chunkSize=s.garbagePhp_chunkSize; //size of garbage.php chunks
99 | if(typeof s.force_fetchAPI != "undefined") settings.force_fetchAPI=s.force_fetchAPI; //use fetch api on all browsers that support it if enabled
100 | if(settings.allow_fetchAPI&&settings.force_fetchAPI&&(!!self.fetch)) useFetchAPI=true;
101 | }catch(e){}
102 | //run the tests
103 | console.log(settings);
104 | console.log("Fetch API: "+useFetchAPI);
105 | getIp(function(){dlTest(function(){testStatus=2;pingTest(function(){testStatus=3;ulTest(function(){testStatus=4;});});})});
106 | }
107 | if(params[0]=="abort"){ //abort command
108 | clearRequests(); //stop all xhr activity
109 | if(interval)clearInterval(interval); //clear timer if present
110 | testStatus=5;dlStatus="";ulStatus="";pingStatus="";jitterStatus=""; //set test as aborted
111 | }
112 | });
113 | //stops all XHR activity, aggressively
114 | function clearRequests(){
115 | if(xhr){
116 | for(var i=0;i