1let recorder 2 3//Navigator benötigt HTTPS!! 4function startRecording(obj) { 5 // Older browsers might not implement mediaDevices at all, so we set an empty object first 6 if (navigator.mediaDevices === undefined) navigator.mediaDevices = {}; 7 8 // Some browsers partially implement mediaDevices. We can't just assign an object 9 // with getUserMedia as it would overwrite existing properties. 10 // Here, we will just add the getUserMedia property if it's missing. 11 if (navigator.mediaDevices.getUserMedia === undefined) { 12 navigator.mediaDevices.getUserMedia = function (constraints) { 13 14 // First get ahold of the legacy getUserMedia, if present 15 const getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia; 16 17 // Some browsers just don't implement it - return a rejected promise with an error 18 // to keep a consistent interface 19 if (!getUserMedia) return Promise.reject(new Error('getUserMedia is not implemented in this browser')); 20 21 // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise 22 return new Promise(function (resolve, reject) { 23 getUserMedia.call(navigator, constraints, resolve, reject); 24 }); 25 } 26 } 27 28 navigator.mediaDevices.getUserMedia({ audio: true }) 29 .then(function (stream) { 30 showRecordingStarted(obj) 31 // store streaming data chunks in array 32 const chunks = []; 33 // create media recorder instance to initialize recording 34 recorder = new MediaRecorder(stream); 35 // function to be called when data is received 36 recorder.ondataavailable = function (e) { 37 // add stream data to chunks 38 chunks.push(e.data); 39 if (!recorder) return 40 // if recorder is 'inactive' then recording has finished 41 if (recorder.state == 'inactive') { 42 recorder = null 43 const blob = new Blob(chunks, { type: 'audio/mpeg' }); //webm 44 const reader = new FileReader(); 45 reader.readAsDataURL(blob); 46 reader.onloadend = function () { 47 base64data = reader.result.split(";")[1].split(",")[1]; 48 saveMemo(base64data, obj); 49 } 50 } 51 }; 52 // start recording with 1 second time between receiving 'ondataavailable' events 53 recorder.start(1000); 54 }) 55 .catch(function (err) { 56 if (err.name == "NotFoundError" || err.name == "DevicesNotFoundError") { 57 //required track is missing 58 sendAlert("Kein Aufnahmegerät gefunden!") 59 } else if (err.name == "NotReadableError" || err.name == "TrackStartError") { 60 //webcam or mic are already in use 61 sendAlert("Aufnahmegerät wird bereits genutzt!") 62 } else if (err.name == "OverconstrainedError" || err.name == "ConstraintNotSatisfiedError") { 63 //constraints can not be satisfied by avb. devices 64 sendAlert("Es konnten nicht alle Anforderungen zum Start der Aufnahme erfüllt werden!") 65 } else if (err.name == "NotAllowedError" || err.name == "PermissionDeniedError") { 66 //permission denied in browser 67 sendAlert("Fehlende Berechtigung für Aufnahmegerät!") 68 } else { 69 //other errors 70 sendAlert("Fehler beim Start der Aufnahme!") 71 } 72 }); 73} 74 75//Darstellung des Mikros => Aufnahme gestartet 76function showRecordingStarted(obj) { 77 if (obj.target === 'map') { 78 $('#memopicMap').show() 79 } else if (obj.target === 'popup') { 80 // Hauptinhalt verstecken 81 $(".downcontainer").css("height", "0px") 82 // Buttons verstecken 83 $("#memo").hide() 84 $("#bewertungstarten").hide() 85 $("#memofeedbacktext").hide() 86 // Mikro anzeigen 87 $('.buttoncontainer').css('height', 'calc(100% - 70px)') 88 $("#memopic_on").show() 89 } 90} 91 92//Aufnahmestopp und Verstecken des Mikrobildes 93function stopRecording(target) { 94 recorder.stop() 95 showRecordingStopped(target) 96} 97 98function showRecordingStopped(target) { 99 if (target === 'map') { 100 $('#memopicMap').hide() 101 } else if (obj.target === 'popup') { 102 // Hauptinhalt darstellen 103 $(".downcontainer").css("height", "calc(100% - 75px - 80px - 25px)") 104 // Buttons darstellen 105 $('.buttoncontainer').css('height', isMobile() ? '80px' : '60px') 106 $("#memo").show() 107 $("#bewertungstarten").show() 108 $("#memofeedbacktext").show() 109 // Mikro verstecken 110 $("#memopic_on").hide() 111 } 112} 113 114//Speicherung der Aufnahmedaten 115function saveMemo(base64data, obj) { 116 let src = '' 117 if (obj.target === 'map') { 118 src += Math.random().toString(36).substr(2, 5) 119 } else if (obj.target === 'popup') { 120 src += bObjConst.roadnumber.trim() + "-" + 121 bObjConst.state.split('.')[1].trim() + "-" + 122 bObjConst.basisdaten_destination.trim() + "-" + 123 Math.random().toString(36).substr(2, 5) + "_" + 124 bObjConst.profundid.trim() 125 } 126 $.ajax({
127 url: "php/saveMemo.php", 128 method: "POST", 129 data: { 130 base64data: base64data, 131 user: sessionStorage.getItem("username"), 132 baustelle: src 133 }, 134 dataType: "text", 135 success: function (data) { }, 136 error: function (jqXHR, status, error) { 137 sendAlert("Ein Fehler ist aufgetreten") 138 } 139 }); 140} 141 142function getMemos() { 143 $.ajax({ 144 url: "php/getMemo.php", 145 method: "POST", 146 data: { 147 user: sessionStorage.getItem("username") 148 }, 149 dataType: "text", 150 success: function (data) { 151 let html 152 let memoÃbersicht = $("#memoÃbersicht") 153 if (data.length > 2) { 154 memoÃbersicht.empty() 155 const json = JSON.parse(data) 156 const keys = Object.keys(json) 157 html = "<ol style='list-style-type: none;padding: 0;'>" 158 for (let i = 0; i < keys.length; i++) { 159 const key = keys[i] 160 const keyArr = key.split('-') 161 162 const roadnumber = keyArr[0] 163 const state = states['D.' + keyArr[1]] 164 const destination = keyArr[2] === 'undefined' ? '' : " - " + keyArr[2] 165 const profundid = keyArr[3] 166 167 const val = json[key] 168 const timestamp = val["timestamp"].split("T") 169 const filetype = val["filetype"] 170 const datearr = timestamp[0].split("-") 171 const timearr = timestamp[1].split("-") 172 const date = datearr[2] + "-" + datearr[1] + "-" + datearr[0] 173 const time = timearr[0] + ":" + timearr[1] 174 const src = "audio/" + sessionStorage.getItem("username") + "_" + encodeURIComponent(key) + "_" + val["timestamp"] + "." + filetype 175 176 const text = keyArr.length <= 4 177 ? date + " " + time 178 : '<a style="cursor:pointer;" onclick="openLeafletPopupOnMemoClick(\'' + profundid + '\',\'' + src + '\',\'' + key + '\')">' + 179 roadnumber + " - " + state + destination + " -> " + date + " " + time + 180 "</a></br>" 181 182 html += "<li name='memoElement' datakey='" + key + "'>" + 183 text + 184 "<div class='flexcontainer'>" + 185 " <audio src=" + src + " controls='true' style='max-width:90%;'>" + 186 " Your browser does not support the <code>audio</code> element." + 187 " </audio>" + 188 ' <div style="width:10%; cursor:pointer; display:flex;flex-direction:column; justify-content:center;" onclick="deleteMemo(\'' + src + '\', \'' + key + '\')">' + 189 " <div data-icon='h' class='fonticon xs' style='text-align:center'></div>" + 190 " </div>" + 191 "</div>" + 192 "</li>" 193 } 194 html += "</ol>" 195 memoÃbersicht.append(html) //Muss 2 mal vorhanden sein sonst rendert html nicht sondern wird als String ausgegeben... 196 } else { 197 html = "<h4 style='text-align:center'>Keine vorhandenen Memos gefunden<h4>" 198 memoÃbersicht.html(html) //Muss 2 mal vorhanden sein sonst rendert html nicht sondern wird als String ausgegeben... 199 } 200 }, 201 error: function (jqXHR, status, error) { 202 sendAlert("Ein Fehler ist aufgetreten") 203 } 204 }) 205} 206 207function openLeafletPopupOnMemoClick(profundid, src, key) { 208 let foundfeature = null 209 for (let i = 0; i < myjson.features.length; i++) { 210 const feature = myjson.features[i] 211 if (feature.properties.profundid == profundid) { 212 foundfeature = feature 213 break 214 } 215 } 216 if (foundfeature) { 217 $('#userprofile').hide() 218 map.flyTo({ 219 center: foundfeature.geometry.coordinates, 220 zoom: maxZoom
221 }) 222 } else { 223 deleteMemo(src, key, 'Diese Baustelle ist aktuell nicht mehr vorhanden, möchten Sie diese löschen?') 224 } 225} 226 227function deleteMemo(src, datakey, text) { 228 if (confirm((text ? text : "Möchten Sie das Memo wirklich löschen?"))) { 229 $.ajax({ 230 url: "php/deleteMemo.php", 231 method: "POST", 232 data: { 233 src: src, 234 srcUser: sessionStorage.getItem("username"), 235 user: sessionStorage.getItem("user") 236 }, 237 dataType: "text", 238 success: function (data) { 239 const json = JSON.parse(data) 240 if (json.success) { 241 $("li[name='memoElement'][datakey='" + datakey + "']").remove() 242 if ($("li[name='memoElement']").length === 0) { 243 // Keine Memos mehr vorhanden 244 $("#memoÃbersicht").html("<h4 style='text-align:center'>Keine vorhandenen Memos gefunden<h4>") 245 } 246 sendAlert(json.success, 'success') 247 } else if (json.error) { 248 sendAlert(json.error) 249 } else { 250 sendAlert("Ein Fehler ist aufgetreten") 251 } 252 }, 253 error: function (jqXHR, status, error) { 254 sendAlert("Ein Fehler ist aufgetreten") 255 } 256 }) 257 } else { 258 } 259}
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.