1function toJSON(form) { 2 var obj = {}; 3 var elements = form.querySelectorAll("input, select, textarea"); 4 for (var i = 0; i < elements.length; ++i) { 5 var element = elements[i]; 6 var name = element.name; 7 var value = element.value; 8 9 if (name) { 10 if (element.dataset.type == 'number') { 11 obj[name] = 1*value; 12 } else { 13 obj[name] = value; 14 } 15 } 16 } 17 18 return obj; 19} 20 21function get_location() { 22 return new Promise ((resolve, reject) => { 23 navigator.geolocation.getCurrentPosition(position => { 24 resolve({lng: position.coords.longitude, lat: position.coords.latitude}) 25 }, error => { 26 resolve(null) 27 }) 28 }) 29} 30 31document.querySelector('#comment-button').addEventListener('click', async function (evt) { 32 var location = await get_location() 33 if (location == null) { 34 const hash = JSON.parse(decodeURIComponent(window.location.hash.substring(1)) || '{}') 35 location = hash.marker 36 } 37 if (location == null) { 38 const messageDiv = document.getElementById('message') 39 messageDiv.classList.remove('is-hidden') 40 setTimeout(() => messageDiv.classList.add('is-hidden'), 2500) 41 return 42 } 43 const form = document.querySelector('#comment-form form') 44 form.reset() 45 document.getElementById('latlon').value = `${location.lng.toFixed(5)}, ${location.lat.toFixed(5)}` 46 document.getElementById('lon').value = location.lng.toFixed(5) 47 document.getElementById('lat').value = location.lat.toFixed(5) 48 document.getElementById('comment-form').classList.add('is-active') 49}) 50 51document.querySelector('#comment-form .delete').addEventListener('click', function () { 52 document.getElementById('comment-form').classList.remove('is-active') 53}) 54 55//speedtest button in the form 56document.getElementById('speed-test-button').addEventListener('click', function (evt) { 57 const submitFormButton = document.getElementById('submit-comment-form') 58 submitFormButton.disabled=true 59 60 const testButton = evt.target 61 testButton.disabled = true 62 const download = 0 63 const upload = 0 64 const downloadBar = document.getElementById('download-bar') 65 const uploadBar = document.getElementById('upload-bar') 66 const downloadText = document.getElementById('download-text') 67 const uploadText = document.getElementById('upload-text') 68 const downloadResultElement = document.getElementById('speed-test-result-down') 69 const uploadResultElement = document.getElementById('speed-test-result-up') 70 var maxSpeed = 100 71 ndt7.test( 72 { 73 userAcceptedDataPolicy: true, 74 }, { 75 serverChosen: function (server) { 76 document.getElementById('server-name').innerText = `${server.machine}@${server.location.city}(${server.location.country})` 77 console.log('Testing to:', { 78 machine: server.machine, 79 locations: server.location, 80 }); 81 }, 82 downloadComplete: function (data) { 83 // (bytes/second) * (bits/byte) / (megabits/bit) = Mbps 84 const serverBw = data.LastServerMeasurement.BBRInfo.BW * 8 / 1000000; 85 const clientGoodput = data.LastClientMeasurement.MeanClientMbps; 86 downloadText.innerText = clientGoodput.toFixed(2) 87 downloadBar.value = clientGoodput 88 downloadResultElement.value = clientGoodput.toFixed(2) 89 }, 90 uploadComplete: function (data) { 91 // TODO: used actual upload duration for rate calculation. 92 // bytes * (bits/byte() * (megabits/bit) * (1/seconds) = Mbps 93 const serverBw = data.LastServerMeasurement.TCPInfo.BytesReceived * 8 / 1000000 / 10; 94 const clientGoodput = data.LastClientMeasurement.MeanClientMbps; 95 uploadText.innerText = clientGoodput.toFixed(2) 96 uploadBar.value = clientGoodput 97 uploadResultElement.value = clientGoodput.toFixed(2) 98 }, 99 downloadMeasurement: function (data) { 100 console.log(data) 101 if (data.Source === 'client') { 102 if (data.Data.MeanClientMbps >= maxSpeed) { 103 maxSpeed = data.Data.MeanClientMbps * 1.3 104 downloadBar.max = maxSpeed 105 uploadBar.max = maxSpeed 106 } 107 downloadBar.value = data.Data.MeanClientMbps 108 downloadText.innerText = data.Data.MeanClientMbps.toFixed(2) 109 } 110 }, 111 uploadMeasurement: function (data) { 112 console.log(data) 113 if (data.Source === 'client') { 114 if (data.Data.MeanClientMbps >= maxSpeed) { 115 maxSpeed = data.Data.MeanClientMbps * 1.3 116 downloadBar.max = maxSpeed 117 uploadBar.max = maxSpeed 118 } 119 uploadBar.value = data.Data.MeanClientMbps 120 uploadText.innerText = data.Data.MeanClientMbps.toFixed(2) 121 } 122 } 123 }, 124 ).then(result => { 125 submitFormButton.disabled = false 126 testButton.disabled = false 127 if (result != 0) { 128 alert('There was an error while measuring connection speed') 129 } 130 }) 131}) 132 133document.getElementById('submit-comment-form').addEventListener('click', function () { 134 const form = document.getElementById('comment-feedback-form') 135 fetch('/api/user_feedback', { 136 method: 'POST', 137 headers: { 138 'Content-Type': 'application/json', 139 }, 140 body: JSON.stringify(toJSON(form)) 141 }) 142 143 document.getElementById('comment-form').classList.remove('is-active') 144}) 145
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.