diff --git a/public/userarea/gridRenderer.js b/public/userarea/gridRenderer.js
index a6d0895..004a667 100644
--- a/public/userarea/gridRenderer.js
+++ b/public/userarea/gridRenderer.js
@@ -36,6 +36,15 @@
return d.innerHTML;
}
+ function escAttr(str) {
+ if (str === null || str === undefined) return "";
+ return String(str)
+ .replace(/&/g, "&")
+ .replace(/"/g, """)
+ .replace(/'/g, "'")
+ .replace(//g, ">");
+ }
function getDetailValue(rowIndex, mappingId) {
return data[rowIndex].details[String(mappingId)] ?? "";
}
@@ -519,7 +528,7 @@
case "tested_component":
div.style.overflow = "visible";
div.innerHTML = `
-
+
@@ -565,7 +574,7 @@
const cls = col.isManual ? "manual-input" : "auto-input";
const reqCls = col.isRequired ? " required-input" : "";
const req = col.isRequired ? " required" : "";
- const v = esc(value);
+ const v = escAttr(value);
if (col.dataType === "SceltaMultipla") {
const options = buildDropdownOptionsHTML(col.fieldId, value);
@@ -590,7 +599,7 @@
if (col.dataType === "DATE") {
const reqCls = col.isRequired ? " required-input" : "";
const req = col.isRequired ? " required" : "";
- return ``;
+ return ``;
}
// Client-sourced fields → AJAX Select2 (like idclient)
@@ -603,7 +612,7 @@
const label = clientNameCache[value] || value;
opts += ``;
}
- return ``;
+ return ``;
}
// Select — build from cache
@@ -621,7 +630,7 @@
const reqCls = col.isRequired ? " required-input" : "";
const req = col.isRequired ? " required" : "";
- return ``;
+ return ``;
}
function buildDropdownOptionsHTML(fieldId, selectedValue) {
@@ -826,6 +835,75 @@
flatpickr(this, { dateFormat: "Y-m-d", allowInput: true });
});
}
+ function getInputTextWidth(input) {
+ const span = document.createElement("span");
+ const style = window.getComputedStyle(input);
+
+ span.style.position = "absolute";
+ span.style.visibility = "hidden";
+ span.style.whiteSpace = "pre";
+ span.style.font = style.font;
+ span.style.fontSize = style.fontSize;
+ span.style.fontFamily = style.fontFamily;
+ span.style.fontWeight = style.fontWeight;
+ span.textContent = input.value || input.placeholder || "";
+
+ document.body.appendChild(span);
+
+ const width = span.offsetWidth + 60;
+
+ document.body.removeChild(span);
+
+ return width;
+ }
+
+ function autoExpandColumnFromInput(input) {
+ if (!input) return;
+
+ const cell = input.closest(".grid-cell");
+ if (!cell || !cell.dataset.index) return;
+
+ const columnIndex = parseInt(cell.dataset.index, 10);
+ if (!columnIndex) return;
+
+ const wantedWidth = Math.max(120, getInputTextWidth(input));
+ const currentWidth = cell.offsetWidth || 0;
+
+ // Only expand, do not shrink automatically
+ if (wantedWidth <= currentWidth) return;
+
+ const newWidth = Math.min(wantedWidth, 900);
+
+ const header = document.querySelector(
+ `.grid-header[data-index="${columnIndex}"]`,
+ );
+
+ if (header) {
+ header.style.flex = `0 0 ${newWidth}px`;
+ }
+
+ const topCell = document.querySelector(
+ `.grid-top .grid-cell:nth-child(${columnIndex + 1})`,
+ );
+
+ if (topCell) {
+ topCell.style.flex = `0 0 ${newWidth}px`;
+ }
+
+ const cells = document.querySelectorAll(
+ `.grid-row .grid-cell[data-index="${columnIndex}"]`,
+ );
+
+ cells.forEach((c) => {
+ c.style.flex = `0 0 ${newWidth}px`;
+ });
+
+ const colPos = columnIndex - 1;
+
+ if (columns[colPos]) {
+ columns[colPos].width = newWidth;
+ }
+ }
function syncVisibleRowsToGridData() {
if (!rowContainer) return;
@@ -1127,6 +1205,10 @@
const cell = e.target.closest(".grid-cell");
if (!cell || !cell.dataset.row) return;
+ if (e.target.classList.contains("cell-input")) {
+ autoExpandColumnFromInput(e.target);
+ }
+
const rowIndex = parseInt(cell.dataset.row, 10);
const colType = cell.dataset.colType;
@@ -1138,6 +1220,16 @@
}
});
+ rowContainer.addEventListener("focusin", function (e) {
+ if (!e.target.classList.contains("cell-input")) return;
+
+ autoExpandColumnFromInput(e.target);
+
+ setTimeout(() => {
+ autoExpandColumnFromInput(e.target);
+ }, 50);
+ });
+
// Persist tested_component before clicking +
document.addEventListener("mousedown", function (e) {
const btn = e.target.closest(".add-part-btn");