Foto del Campione
@@ -432,7 +432,7 @@
}
/* Evita stretching del flex nella riga dei filtri */
- #partsModal .modal-body>.row .col-md-9>div[style*="display: flex"]>* {
+ #partsModal .parts-row>div:first-child>div[style*="display: flex"]>* {
flex: 0 0 auto;
}
@@ -611,7 +611,7 @@
#partsTable {
table-layout: fixed !important;
- width: max-content !important;
+ width: 100% !important;
min-width: unset !important;
}
@@ -733,9 +733,6 @@
/* Extra field propagation header - full column width */
#partsTable th.extra-field-th {
- width: auto !important;
- min-width: 220px !important;
- max-width: none !important;
padding: 0.25rem !important;
}
@@ -757,9 +754,9 @@
font-weight: 700;
line-height: 1.15;
color: #222;
- white-space: nowrap !important;
- overflow: visible !important;
- text-overflow: unset !important;
+ white-space: normal !important;
+ word-break: break-word;
+ overflow: hidden !important;
text-align: center;
}
@@ -806,5 +803,69 @@
z-index: 1065 !important
}
+ /* Campi nelle celle: occupano tutta la cella */
+ #partsTable td input.form-control,
+ #partsTable td textarea.form-control {
+ width: 100% !important;
+ max-width: 100% !important;
+ }
+
+ #partsTable td>div[style*="display: flex"] {
+ width: 100%;
+ min-width: 0;
+ }
+
+ /* Select2 nelle celle (Matrice ed Extra): occupano la cella e vanno a capo */
+ #partsTable td .select2-container {
+ width: 100% !important;
+ min-width: 0 !important;
+ max-width: 100% !important;
+ }
+
+ #partsTable td .part-matrice+.select2 {
+ flex: 1 1 auto !important;
+ width: auto !important;
+ }
+
+ #partsTable td .select2-selection--single {
+ height: auto !important;
+ min-height: 24px !important;
+ display: flex !important;
+ align-items: center;
+ }
+
+ #partsTable td .select2-selection__rendered {
+ flex: 1 1 auto;
+ white-space: normal !important;
+ word-break: break-word;
+ overflow: visible !important;
+ text-overflow: clip !important;
+ line-height: 1.2 !important;
+ padding: 2px 22px 2px 4px !important;
+ }
+
+ #partsTable td .select2-selection__arrow {
+ height: 100% !important;
+ top: 0 !important;
+ }
+
+ /* Campo extra di tipo testo: textarea che cresce col contenuto */
+ #partsTable textarea.part-extra-field {
+ field-sizing: content;
+ min-height: 24px;
+ height: auto;
+ padding: 0.1rem 0.3rem;
+ line-height: 1.2;
+ font-size: 0.8rem;
+ resize: none;
+ overflow: hidden;
+ }
+
+ /* Voci del dropdown che vanno a capo */
+ .select2-results__option {
+ white-space: normal;
+ word-break: break-word;
+ }
+
/* rosso */
\ No newline at end of file
diff --git a/public/userarea/partsTable.js b/public/userarea/partsTable.js
index 42430149..2a5da7c7 100644
--- a/public/userarea/partsTable.js
+++ b/public/userarea/partsTable.js
@@ -147,10 +147,9 @@ $(document).ready(function () {
return `
`;
}
-
function buildExtraFieldHeaderHtml() {
if (!partsExtraField) return "";
@@ -888,6 +887,17 @@ $(document).ready(function () {
$("#partsTableBody").empty();
$("#global-matrice").empty();
$("#macro-matrice-filter").empty();
+
+ // Ripristina lo stato di default: foto nascosta
+ const $partsRow = $("#partsModal .parts-row");
+ $partsRow.find("> .col-md-3").addClass("d-none");
+ $partsRow
+ .find("> div:first-child")
+ .removeClass("col-md-9")
+ .addClass("col-md-12");
+ $("#showHideImageBtn").html(
+ "",
+ );
$(".temp-alert").remove();
$(".modal-backdrop").remove();
$("body").removeClass("modal-open").css("padding-right", "");
@@ -2154,6 +2164,9 @@ $(document).ready(function () {
});
window.saveAllParts = saveAllParts;
+ window.markUnsaved = function () {
+ markUnsaved();
+ };
function renumberParts() {
console.log(
"Inizio rinumera parts, numero righe:",
@@ -2672,135 +2685,171 @@ $(document).on("click", "#showHideImageBtn", function () {
// RESIZABLE PARTS TABLE COLUMNS - FIXED COLGROUP VERSION
// ===================
(function () {
- // Larghezze default per indice colonna (0-based)
- const defaultWidths = [55, 320, 360, 150, 220, 230];
- const savedWidths = [...defaultWidths];
+ const NUM_W = 55; // colonna Num fissa
+ const MIN_W = 70; // larghezza minima di ogni colonna
+
+ // Pesi di default delle colonne dopo Num
+ // senza extra: Descrizione, Matrice, Data, Azioni
+ // con extra: Descrizione, Matrice, Data, Extra, Azioni
+ const DEFAULT_NO_EXTRA = [320, 360, 150, 200];
+ const DEFAULT_EXTRA = [280, 320, 140, 240, 180];
+
+ let weights = null;
+ let weightsCount = 0;
function getColgroup() {
return $("#partsTableColgroup");
}
- function syncColgroupToHeaders() {
- const $table = $("#partsTable");
- const $ths = $table.find("thead tr:first th");
- const $colgroup = getColgroup();
- const thCount = $ths.length;
-
- // Assicura che ci siano esattamente tante
quante
- while ($colgroup.find("col").length < thCount) {
- $colgroup.append("");
- }
- while ($colgroup.find("col").length > thCount) {
- $colgroup.find("col:last").remove();
- }
-
- // Applica le larghezze salvate
- $colgroup.find("col").each(function (i) {
- const w = savedWidths[i] !== undefined ? savedWidths[i] : 150;
- $(this).css("width", w + "px");
- });
-
- // Imposta larghezza totale della tabella = somma colonne (evita reflow)
- const total = savedWidths.slice(0, thCount).reduce((a, b) => a + b, 0);
- $table.css("width", total + "px");
+ function getThs() {
+ return $("#partsTable thead tr:first th");
}
- function applyColumnWidth(colIndex, newWidth) {
- const w = Math.max(40, Math.round(newWidth));
- savedWidths[colIndex] = w;
+ function getAvail() {
+ const w = $("#partsModal .parts-table-scroll").innerWidth();
+ return w > 0 ? Math.floor(w) : 0;
+ }
- const $col = getColgroup().find("col").eq(colIndex);
- if ($col.length) {
- $col.css("width", w + "px");
+ function ensureCols(n) {
+ const $cg = getColgroup();
+ while ($cg.find("col").length < n) $cg.append("");
+ while ($cg.find("col").length > n) $cg.find("col:last").remove();
+ }
+
+ function ensureWeights(n) {
+ const k = n - 1;
+ if (weights && weightsCount === k) return;
+ if (k === 4) weights = DEFAULT_NO_EXTRA.slice();
+ else if (k === 5) weights = DEFAULT_EXTRA.slice();
+ else weights = Array(k).fill(150);
+ weightsCount = k;
+ }
+
+ // Converte i pesi in pixel: la somma è sempre = larghezza disponibile
+ function computePx(n) {
+ const avail = getAvail();
+ const rest = Math.max(avail - NUM_W, MIN_W * (n - 1));
+ const sum = weights.reduce((a, b) => a + b, 0) || 1;
+ const px = [NUM_W];
+ let used = 0;
+ for (let i = 0; i < weights.length; i++) {
+ const v =
+ i === weights.length - 1
+ ? rest - used
+ : Math.floor((rest * weights[i]) / sum);
+ px.push(v);
+ used += v;
}
+ return px;
+ }
- // Aggiorna larghezza totale tabella senza toccare le altre colonne
- const thCount = $("#partsTable thead tr:first th").length;
- const total = savedWidths.slice(0, thCount).reduce((a, b) => a + b, 0);
- $("#partsTable").css("width", total + "px");
+ function render() {
+ const n = getThs().length;
+ if (!n || !getAvail()) return;
+ ensureCols(n);
+ ensureWeights(n);
+ const px = computePx(n);
+ getColgroup()
+ .find("col")
+ .each(function (i) {
+ $(this).css("width", px[i] + "px");
+ });
}
function addResizers() {
- const $table = $("#partsTable");
- if (!$table.length) return;
+ const $ths = getThs();
+ const n = $ths.length;
+ if (!n) return;
+
+ $ths.find(".parts-resizer").remove();
+
+ // Resizer sul bordo destro delle colonne da 1 a n-2:
+ // sposta spazio tra la colonna e quella alla sua destra
+ $ths.each(function (i) {
+ if (i === 0 || i >= n - 1) return;
- $table.find("thead tr:first th").each(function (colIndex) {
const $th = $(this);
-
- // Salta colonna Num (indice 0) — non ridimensionabile
- if (colIndex === 0) return;
-
- // Non aggiungere due volte
- if ($th.find(".parts-resizer").length) return;
-
+ $th.css("position", "relative");
const $resizer = $("");
- $th.css("position", "relative"); // necessario per il posizionamento assoluto
$th.append($resizer);
$resizer.on("mousedown", function (e) {
e.preventDefault();
e.stopPropagation();
+ ensureWeights(n);
+ const startPx = computePx(n);
+ const a = startPx[i];
+ const b = startPx[i + 1];
const startX = e.pageX;
- // Leggi la larghezza ESATTA dalla , non dal |
- const startWidth =
- savedWidths[colIndex] !== undefined
- ? savedWidths[colIndex]
- : parseInt(
- getColgroup()
- .find("col")
- .eq(colIndex)
- .css("width"),
- 10,
- ) || 150;
- $("body")
- .css("user-select", "none")
- .css("cursor", "col-resize");
+ $("body").css({ "user-select": "none", cursor: "col-resize" });
$(document).on("mousemove.partsResize", function (ev) {
const delta = ev.pageX - startX;
- applyColumnWidth(colIndex, startWidth + delta);
+ const newA = Math.min(
+ Math.max(a + delta, MIN_W),
+ a + b - MIN_W,
+ );
+ const newB = a + b - newA;
+
+ const px = startPx.slice();
+ px[i] = newA;
+ px[i + 1] = newB;
+ weights = px.slice(1); // i pixel diventano i nuovi pesi
+ render();
});
$(document).on("mouseup.partsResize", function () {
- $("body").css("user-select", "").css("cursor", "");
+ $("body").css({ "user-select": "", cursor: "" });
$(document).off(".partsResize");
});
});
});
}
- function init() {
- syncColgroupToHeaders();
+ function refresh() {
+ render();
addResizers();
}
- // Init al primo show del modale
$(document).on("shown.bs.modal", "#partsModal", function () {
- setTimeout(init, 120);
+ setTimeout(refresh, 120);
});
- // Re-init dopo ogni AJAX (nuove righe, caricamenti)
$(document).ajaxComplete(function () {
if ($("#partsModal").hasClass("show")) {
- setTimeout(syncColgroupToHeaders, 200);
- setTimeout(addResizers, 220);
+ setTimeout(refresh, 200);
}
});
- // Re-init dopo aggiunta/rimozione righe
$(document).on(
"click",
".add-row-global, .add-mix-global, .add-mix-row, .remove-row, #renumberPartsBtn, #clonePartsBtn",
function () {
- setTimeout(syncColgroupToHeaders, 120);
- setTimeout(addResizers, 140);
+ setTimeout(refresh, 120);
},
);
- window.initPartsResizableColumns = init;
- window.applyPartsColumnWidths = syncColgroupToHeaders;
+ let resizeTimer = null;
+ $(window).on("resize.partsCols", function () {
+ if (!$("#partsModal").hasClass("show")) return;
+ clearTimeout(resizeTimer);
+ resizeTimer = setTimeout(render, 150);
+ });
+
+ // Textarea campo extra: auto-altezza (per browser senza field-sizing)
+ $(document).on(
+ "input focus",
+ "#partsTable textarea.part-extra-field",
+ function () {
+ this.style.height = "auto";
+ this.style.height = this.scrollHeight + "px";
+ },
+ );
+
+ window.initPartsResizableColumns = refresh;
+ window.applyPartsColumnWidths = refresh;
})();
// ===================
// NAVIGAZIONE TABELLA PARTI CON FRECCE TASTIERA
|