improved WebUI
This commit is contained in:
		| @@ -84,7 +84,6 @@ function onMessage(event) { | ||||
|  | ||||
|     processDTCNotifications(dtcArray); | ||||
|     fillDTCTable(dtcArray); | ||||
|  | ||||
|   } else if (data.startsWith("MAPPING_STATUS:")) { | ||||
|     const data_sliced = data.slice(15); | ||||
|     statusMapping = createMapping(data_sliced); | ||||
| @@ -100,19 +99,15 @@ function onMessage(event) { | ||||
|     const data_sliced = data.slice(7); | ||||
|     const result = processDataString(data_sliced, staticMapping); | ||||
|     fillValuesToHTML(result); | ||||
|     console.log(result); | ||||
|     overlay.style.display = "none"; | ||||
|   } | ||||
| } | ||||
|  | ||||
| function createMapping(mappingString) { | ||||
|   const mappingArray = mappingString.split(";"); | ||||
|   const mapping = []; | ||||
|  | ||||
|   mappingArray.forEach((variable) => { | ||||
|     if (variable !== null) mapping.push(variable.trim()); | ||||
|   }); | ||||
|   return mapping; | ||||
|   return mappingString | ||||
|     .split(";") | ||||
|     .map((s) => s.trim()) | ||||
|     .filter((s) => s !== ""); | ||||
| } | ||||
|  | ||||
| function processDataString(dataString, mapping) { | ||||
| @@ -157,43 +152,136 @@ function do_resize(textbox) { | ||||
|   else textbox.rows = rows; | ||||
| } | ||||
|  | ||||
| function fillValuesToHTML(dataset) { | ||||
|   for (var key in dataset) { | ||||
|     var key_prefixed = "data-" + key; | ||||
|     var elements = document.getElementsByClassName(key_prefixed); | ||||
| // --- Globale Puffer für Select-Handling --- | ||||
| const selectDesiredValue = Object.create(null); // keyBase -> desired value ("speedsource" -> "GPS") | ||||
| const selectOptionsReady = Object.create(null); // keyBase -> true/false | ||||
|  | ||||
|     if (elements.length > 0) { | ||||
|       for (var i = 0; i < elements.length; i++) { | ||||
|         var element = elements[i]; | ||||
| function splitCsv(s) { | ||||
|   return (s || "") | ||||
|     .split(",") | ||||
|     .map((x) => x.trim()) | ||||
|     .filter(Boolean); | ||||
| } | ||||
|  | ||||
|         if (element.type === "checkbox") { | ||||
|           // Wenn das Element ein Kontrollkästchen ist | ||||
|           element.checked = dataset[key] == 1 ? true : false; | ||||
|         } else if (element.tagName === "SELECT") { | ||||
|           // Wenn das Element ein Dropdown ist | ||||
|           setDropdownValue(element, dataset[key]); | ||||
|         } else if (element.classList.contains("progress-bar")) { | ||||
|           // Wenn das Element eine Fortschrittsleiste ist | ||||
|           updateProgressBar(element, dataset[key]); | ||||
|         } else if (element.classList.contains("hideable")) { | ||||
|           // Wenn das Element ein Settingsabschnitt-div ist | ||||
|           if (dataset[key] == 0) element.style.display = "none"; | ||||
|           else element.style.display = ""; | ||||
|         } else { | ||||
|           // Standardmäßig für Textfelder und andere Elemente | ||||
|           element.value = dataset[key]; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| function hasOption(selectEl, value) { | ||||
|   for (let i = 0; i < selectEl.options.length; i++) { | ||||
|     if (selectEl.options[i].value === value) return true; | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
|  | ||||
| function addOption(selectEl, value, selectIt = false) { | ||||
|   const o = document.createElement("option"); | ||||
|   o.value = value; | ||||
|   o.textContent = value; | ||||
|   selectEl.appendChild(o); | ||||
|   if (selectIt) { | ||||
|     selectEl.value = value; | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Funktion zum Setzen des ausgewählten Werts für Dropdowns | ||||
| function populateSelect(selectId, options, currentValue) { | ||||
|   const sel = document.getElementById(selectId); | ||||
|   if (!sel) return; | ||||
|  | ||||
|   // 1) komplett ersetzen | ||||
|   sel.innerHTML = ""; | ||||
|   options.forEach((opt) => addOption(sel, opt, false)); | ||||
|  | ||||
|   // 2) Zielwert bestimmen (currentValue > bereits gepuffert > vorhandener Wert > erste Option) | ||||
|   const wanted = | ||||
|     (currentValue && currentValue.length ? currentValue : null) ?? | ||||
|     selectDesiredValue[selectId] ?? | ||||
|     sel.value ?? | ||||
|     (options[0] || ""); | ||||
|  | ||||
|   // 3) Falls gewünschte Option fehlt, hinzufügen | ||||
|   if (wanted && !hasOption(sel, wanted)) addOption(sel, wanted, false); | ||||
|  | ||||
|   // 4) Setzen | ||||
|   sel.value = wanted; | ||||
|  | ||||
|   // 5) Markieren: Optionen sind ready | ||||
|   selectOptionsReady[selectId] = true; | ||||
|   // Verbrauchte Wunschwerte löschen | ||||
|   delete selectDesiredValue[selectId]; | ||||
| } | ||||
|  | ||||
| // Robust: setzt den Wert; wenn Option fehlt, füge sie hinzu | ||||
| function setDropdownValue(selectElement, value) { | ||||
|   for (var i = 0; i < selectElement.options.length; i++) { | ||||
|     if (selectElement.options[i].value === value) { | ||||
|       selectElement.selectedIndex = i; | ||||
|       break; | ||||
|   if (!value) return; | ||||
|   if (!hasOption(selectElement, value)) { | ||||
|     addOption(selectElement, value, false); | ||||
|   } | ||||
|   selectElement.value = value; | ||||
| } | ||||
|  | ||||
| // Core: schreibt Werte in DOM, erkennt *-options und füllt Selects | ||||
| function fillValuesToHTML(dataset) { | ||||
|   for (const key in dataset) { | ||||
|     const val = dataset[key]; | ||||
|  | ||||
|     // A) Optionen-Feld? (z.B. "speedsource-options") | ||||
|     if (key.endsWith("-options")) { | ||||
|       const base = key.slice(0, -"-options".length); // "speedsource" | ||||
|       const selectId = base; // ID = keyBase | ||||
|       populateSelect( | ||||
|         selectId, | ||||
|         splitCsv(val), | ||||
|         selectDesiredValue[selectId] || undefined | ||||
|       ); | ||||
|       continue; // fertig mit diesem key | ||||
|     } | ||||
|  | ||||
|     // B) Normales Feld | ||||
|     const key_prefixed = "data-" + key; | ||||
|     const elements = document.getElementsByClassName(key_prefixed); | ||||
|     if (elements.length === 0) continue; | ||||
|  | ||||
|     for (let i = 0; i < elements.length; i++) { | ||||
|       const el = elements[i]; | ||||
|  | ||||
|       // Checkbox? | ||||
|       if (el.type === "checkbox") { | ||||
|         el.checked = val == 1; | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       // Select? | ||||
|       if (el.tagName === "SELECT") { | ||||
|         const selectId = el.id || key; // ID hat Vorrang, sonst key | ||||
|         // Wenn die Optionen für dieses Select noch NICHT bereit sind, Wunschwert puffern | ||||
|         if (!selectOptionsReady[selectId]) { | ||||
|           selectDesiredValue[selectId] = val; | ||||
|           // Sicherheitsnetz: falls doch schon Optionen existieren, sofort setzen | ||||
|           setDropdownValue(el, val); | ||||
|         } else { | ||||
|           // Optionen sind ready -> ganz normal setzen (ggf. Option ergänzen) | ||||
|           setDropdownValue(el, val); | ||||
|         } | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       // Progress-Bar? | ||||
|       if (el.classList.contains("progress-bar")) { | ||||
|         updateProgressBar(el, val); | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       // Hideable-Section? | ||||
|       if (el.classList.contains("hideable")) { | ||||
|         el.style.display = val == 0 ? "none" : ""; | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       // Input/Textarea? | ||||
|       if ("value" in el) { | ||||
|         el.value = val; | ||||
|         continue; | ||||
|       } | ||||
|  | ||||
|       // Fallback: content nodes (td, span, div) | ||||
|       el.textContent = val; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -212,15 +300,15 @@ function showNotification(message, type) { | ||||
|   // Erstellen Sie ein Bootstrap-Alert-Element | ||||
|   var alertElement = $( | ||||
|     '<div class="alert alert-' + | ||||
|     type + | ||||
|     ' alert-dismissible fade show notification" role="alert">' + | ||||
|     "<strong>" + | ||||
|     message + | ||||
|     "</strong>" + | ||||
|     '<button type="button" class="close" data-dismiss="alert" aria-label="Close">' + | ||||
|     '<span aria-hidden="true">×</span>' + | ||||
|     "</button>" + | ||||
|     "</div>" | ||||
|       type + | ||||
|       ' alert-dismissible fade show notification" role="alert">' + | ||||
|       "<strong>" + | ||||
|       message + | ||||
|       "</strong>" + | ||||
|       '<button type="button" class="close" data-dismiss="alert" aria-label="Close">' + | ||||
|       '<span aria-hidden="true">×</span>' + | ||||
|       "</button>" + | ||||
|       "</div>" | ||||
|   ); | ||||
|  | ||||
|   // Fügen Sie das Alert-Element dem Container hinzu | ||||
|   | ||||
		Reference in New Issue
	
	Block a user