fix render gird for doppi apici

This commit is contained in:
2026-05-18 15:38:43 +02:00
parent df075dd76a
commit 4f2cfc1930
+97 -5
View File
@@ -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, "&lt;")
.replace(/>/g, "&gt;");
}
function getDetailValue(rowIndex, mappingId) {
return data[rowIndex].details[String(mappingId)] ?? "";
}
@@ -519,7 +528,7 @@
case "tested_component":
div.style.overflow = "visible";
div.innerHTML = `<div style="display:flex; align-items:center; gap:4px; width:100%; height:100%;">
<input type="text" class="cell-input manual-input tested-component-input" value="${esc(row.tested_component || "")}" style="flex:1; min-width:0; height:28px;">
<input type="text" class="cell-input manual-input tested-component-input" value="${escAttr(row.tested_component || "")}" style="flex:1; min-width:0; height:28px;">
<button type="button" class="add-part-btn btn btn-sm btn-primary" data-row="${rowIndex}" data-iddatadb="${row.iddatadb}" style="display:inline-flex; align-items:center; justify-content:center; min-width:28px; width:28px; height:28px; padding:0; font-size:12px; flex-shrink:0; text-align:center;">
<i class="fas fa-plus" style="margin:0; padding:0;"></i>
</button>
@@ -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 `<input type="text" class="cell-input date-picker manual-input${reqCls} fixed-input" data-fixed-key="${col.key}" value="${esc(value)}"${req}>`;
return `<input type="text" class="cell-input date-picker manual-input${reqCls} fixed-input" data-fixed-key="${escAttr(col.key)}" value="${escAttr(value)}"${req}>`;
}
// Client-sourced fields → AJAX Select2 (like idclient)
@@ -603,7 +612,7 @@
const label = clientNameCache[value] || value;
opts += `<option value="${esc(String(value))}" selected>${esc(String(label))}</option>`;
}
return `<select class="cell-input manual-input fixed-input searchable-client api-fixed-select${reqCls}" data-fixed-key="${col.key}" data-current-value="${esc(value)}"${req}>${opts}</select>`;
return `<select class="cell-input manual-input fixed-input searchable-client api-fixed-select${reqCls}" data-fixed-key="${escAttr(col.key)}" data-current-value="${escAttr(value)}"${req}>${opts}</select>`;
}
// Select — build from cache
@@ -621,7 +630,7 @@
const reqCls = col.isRequired ? " required-input" : "";
const req = col.isRequired ? " required" : "";
return `<select class="cell-input manual-input fixed-input ${selectClass}${reqCls}" data-fixed-key="${col.key}" data-current-value="${esc(value)}"${req}>${options}</select>`;
return `<select class="cell-input manual-input fixed-input ${selectClass}${reqCls}" data-fixed-key="${escAttr(col.key)}" data-current-value="${escAttr(value)}"${req}>${options}</select>`;
}
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");