You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
12 KiB

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  6. <meta http-equiv="cache-control" content="no-cache,no-store,must-revalidate" />
  7. <meta http-equiv="expires" content="0" />
  8. <meta http-equiv="pragma" content="no-cache" />
  9. <meta name="format-detection" content="telephone=no" />
  10. <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
  11. <meta name="renderer" content="webkit">
  12. <meta name="mobileoptimized" content="0" />
  13. <link rel="shortcut icon" href="favicon.ico">
  14. <script type="text/javascript" src="speedtest.js"></script>
  15. <script type="text/javascript">
  16. function I(i) { return document.getElementById(i); }
  17. //INITIALIZE SPEEDTEST
  18. var s = new Speedtest(); //create speedtest object
  19. var meterBk = /Trident.*rv:(\d+\.\d+)/i.test(navigator.userAgent) ? "#EAEAEA" : "#80808040";
  20. var dlColor = "#6060AA",
  21. ulColor = "#616161";
  22. var progColor = meterBk;
  23. //CODE FOR GAUGES
  24. function drawMeter(c, amount, bk, fg, progress, prog) {
  25. var ctx = c.getContext("2d");
  26. var dp = window.devicePixelRatio || 1;
  27. var cw = c.clientWidth * dp, ch = c.clientHeight * dp;
  28. var sizScale = ch * 0.0055;
  29. if (c.width == cw && c.height == ch) {
  30. ctx.clearRect(0, 0, cw, ch);
  31. } else {
  32. c.width = cw;
  33. c.height = ch;
  34. }
  35. ctx.beginPath();
  36. ctx.strokeStyle = bk;
  37. ctx.lineWidth = 12 * sizScale;
  38. ctx.arc(c.width / 2, c.height - 58 * sizScale, c.height / 1.8 - ctx.lineWidth, -Math.PI * 1.1, Math.PI * 0.1);
  39. ctx.stroke();
  40. ctx.beginPath();
  41. ctx.strokeStyle = fg;
  42. ctx.lineWidth = 12 * sizScale;
  43. 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);
  44. ctx.stroke();
  45. if (typeof progress !== "undefined") {
  46. ctx.fillStyle = prog;
  47. ctx.fillRect(c.width * 0.3, c.height - 16 * sizScale, c.width * 0.4 * progress, 4 * sizScale);
  48. }
  49. }
  50. function mbpsToAmount(s) {
  51. return 1 - (1 / (Math.pow(1.3, Math.sqrt(s))));
  52. }
  53. function format(d) {
  54. d = Number(d);
  55. if (d < 10) return d.toFixed(2);
  56. if (d < 100) return d.toFixed(1);
  57. return d.toFixed(0);
  58. }
  59. //UI CODE
  60. var uiData = null;
  61. function startStop() {
  62. if (s.getState() == 3) {
  63. //speedtest is running, abort
  64. s.abort();
  65. data = null;
  66. I("startStopBtn").className = "";
  67. initUI();
  68. } else {
  69. //test is not running, begin
  70. I("startStopBtn").className = "running";
  71. I("shareArea").style.display = "none";
  72. s.onupdate = function (data) {
  73. uiData = data;
  74. };
  75. s.onend = function (aborted) {
  76. I("startStopBtn").className = "";
  77. updateUI(true);
  78. if (!aborted) {
  79. //if testId is present, show sharing panel, otherwise do nothing
  80. try {
  81. var testId = uiData.testId;
  82. if (testId != null) {
  83. var shareURL = window.location.href.substring(0, window.location.href.lastIndexOf("/")) + "/results/?id=" + testId;
  84. I("resultsImg").src = shareURL;
  85. I("resultsURL").value = shareURL;
  86. I("testId").innerHTML = testId;
  87. I("shareArea").style.display = "";
  88. }
  89. } catch (e) { }
  90. }
  91. };
  92. s.start();
  93. }
  94. }
  95. //this function reads the data sent back by the test and updates the UI
  96. function updateUI(forced) {
  97. if (!forced && s.getState() != 3) return;
  98. if (uiData == null) return;
  99. var status = uiData.testState;
  100. I("ip").textContent = uiData.clientIp;
  101. I("dlText").textContent = (status == 1 && uiData.dlStatus == 0) ? "..." : format(uiData.dlStatus);
  102. drawMeter(I("dlMeter"), mbpsToAmount(Number(uiData.dlStatus * (status == 1 ? oscillate() : 1))), meterBk, dlColor, Number(uiData.dlProgress), progColor);
  103. I("ulText").textContent = (status == 3 && uiData.ulStatus == 0) ? "..." : format(uiData.ulStatus);
  104. drawMeter(I("ulMeter"), mbpsToAmount(Number(uiData.ulStatus * (status == 3 ? oscillate() : 1))), meterBk, ulColor, Number(uiData.ulProgress), progColor);
  105. I("pingText").textContent = format(uiData.pingStatus);
  106. I("jitText").textContent = format(uiData.jitterStatus);
  107. }
  108. function oscillate() {
  109. return 1 + 0.02 * Math.sin(Date.now() / 100);
  110. }
  111. //update the UI every frame
  112. window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || (function (callback, element) { setTimeout(callback, 1000 / 60); });
  113. function frame() {
  114. requestAnimationFrame(frame);
  115. updateUI();
  116. }
  117. frame(); //start frame loop
  118. //function to (re)initialize UI
  119. function initUI() {
  120. drawMeter(I("dlMeter"), 0, meterBk, dlColor, 0);
  121. drawMeter(I("ulMeter"), 0, meterBk, ulColor, 0);
  122. I("dlText").textContent = "";
  123. I("ulText").textContent = "";
  124. I("pingText").textContent = "";
  125. I("jitText").textContent = "";
  126. I("ip").textContent = "";
  127. }
  128. </script>
  129. <style type="text/css">
  130. html, body {
  131. border: none;
  132. padding: 0;
  133. margin: 0;
  134. background: #FFFFFF;
  135. color: #202020;
  136. }
  137. body {
  138. text-align: center;
  139. font-family: "Roboto",sans-serif;
  140. }
  141. h1 {
  142. color: #404040;
  143. }
  144. #startStopBtn {
  145. display: inline-block;
  146. margin: 0 auto;
  147. color: #6060AA;
  148. background-color: rgba(0,0,0,0);
  149. border: 0.15em solid #6060FF;
  150. border-radius: 0.3em;
  151. transition: all 0.3s;
  152. box-sizing: border-box;
  153. width: 8em;
  154. height: 3em;
  155. line-height: 2.7em;
  156. cursor: pointer;
  157. box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
  158. }
  159. #startStopBtn:hover {
  160. box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
  161. }
  162. #startStopBtn.running {
  163. background-color: #FF3030;
  164. border-color: #FF6060;
  165. color: #FFFFFF;
  166. }
  167. #startStopBtn:before {
  168. content: "Start";
  169. }
  170. #startStopBtn.running:before {
  171. content: "Abort";
  172. }
  173. #test {
  174. margin-top: 2em;
  175. margin-bottom: 12em;
  176. }
  177. div.testArea {
  178. display: inline-block;
  179. width: 16em;
  180. height: 12.5em;
  181. margin: 1em 0em;
  182. position: relative;
  183. box-sizing: border-box;
  184. }
  185. div.testArea2 {
  186. display: inline-block;
  187. width: 14em;
  188. height: 7em;
  189. position: relative;
  190. box-sizing: border-box;
  191. text-align: center;
  192. }
  193. div.testArea div.testName {
  194. position: absolute;
  195. top: -0.5em;
  196. left: 0;
  197. width: 100%;
  198. font-size: 1.4em;
  199. z-index: 9;
  200. }
  201. div.testArea2 div.testName {
  202. display: block;
  203. text-align: center;
  204. font-size: 1.4em;
  205. }
  206. div.testArea div.meterText {
  207. position: absolute;
  208. bottom: 1.55em;
  209. left: 0;
  210. width: 100%;
  211. font-size: 2.5em;
  212. z-index: 9;
  213. }
  214. div.testArea2 div.meterText {
  215. display: inline-block;
  216. font-size: 2.5em;
  217. }
  218. div.meterText:empty:before {
  219. content: "0.00";
  220. }
  221. div.testArea div.unit {
  222. position: absolute;
  223. bottom: 2em;
  224. left: 0;
  225. width: 100%;
  226. z-index: 9;
  227. }
  228. div.testArea2 div.unit {
  229. display: inline-block;
  230. }
  231. div.testArea canvas {
  232. position: absolute;
  233. top: 0;
  234. left: 0;
  235. width: 100%;
  236. height: 100%;
  237. z-index: 1;
  238. }
  239. div.testGroup {
  240. display: block;
  241. margin: 0 auto;
  242. }
  243. #shareArea {
  244. width: 95%;
  245. max-width: 40em;
  246. margin: 0 auto;
  247. margin-top: 2em;
  248. }
  249. #shareArea > * {
  250. display: block;
  251. width: 100%;
  252. height: auto;
  253. margin: 0.25em 0;
  254. }
  255. #privacyPolicy {
  256. position: fixed;
  257. top: 2em;
  258. bottom: 2em;
  259. left: 2em;
  260. right: 2em;
  261. overflow-y: auto;
  262. width: auto;
  263. height: auto;
  264. box-shadow: 0 0 3em 1em #000000;
  265. z-index: 999999;
  266. text-align: left;
  267. background-color: #FFFFFF;
  268. padding: 1em;
  269. }
  270. a.privacy {
  271. text-align: center;
  272. font-size: 0.8em;
  273. color: #808080;
  274. display: block;
  275. }
  276. @media all and (max-width:40em) {
  277. body {
  278. font-size: 0.8em;
  279. }
  280. }
  281. </style>
  282. <title>Speedtest</title>
  283. </head>
  284. <body>
  285. <h1>Speedtest</h1>
  286. <div id="testWrapper">
  287. <div id="startStopBtn" onclick="startStop()"></div><br />
  288. <div id="test">
  289. <div class="testGroup">
  290. <div class="testArea2">
  291. <div class="testName">Ping</div>
  292. <div id="pingText" class="meterText" style="color:#AA6060"></div>
  293. <div class="unit">ms</div>
  294. </div>
  295. <div class="testArea2">
  296. <div class="testName">Jitter</div>
  297. <div id="jitText" class="meterText" style="color:#AA6060"></div>
  298. <div class="unit">ms</div>
  299. </div>
  300. </div>
  301. <div class="testGroup">
  302. <div class="testArea">
  303. <div class="testName">Download</div>
  304. <canvas id="dlMeter" class="meter"></canvas>
  305. <div id="dlText" class="meterText"></div>
  306. <div class="unit">Mbps</div>
  307. </div>
  308. <div class="testArea">
  309. <div class="testName">Upload</div>
  310. <canvas id="ulMeter" class="meter"></canvas>
  311. <div id="ulText" class="meterText"></div>
  312. <div class="unit">Mbps</div>
  313. </div>
  314. </div>
  315. <div id="ipArea">
  316. <span id="ip"></span>
  317. </div>
  318. <div id="shareArea" style="display:none">
  319. <h3>Share results</h3>
  320. <p>Test ID: <span id="testId"></span></p>
  321. <input type="text" value="" id="resultsURL" readonly="readonly" onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')" />
  322. <img src="" id="resultsImg" />
  323. </div>
  324. </div>
  325. </div>
  326. <script type="text/javascript">setTimeout(function () { initUI() }, 100);</script>
  327. </body>
  328. </html>