scroll table parts
This commit is contained in:
parent
ce00247d1c
commit
813bd66f96
@ -32,6 +32,10 @@
|
||||
<button type="button" class="btn btn-secondary btn-sm ms-2" id="toggleVoiceBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">
|
||||
<i class="fas fa-microphone"></i> Voce
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm ms-2" id="showHideImageBtn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;">
|
||||
<i class="fas fa-eye-slash" style="font-size: 0.8rem;"></i>
|
||||
<i class="fas fa-image ms-1" style="font-size: 0.8rem;"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Seconda riga: +, M, MacroMatrice, Matrice globale, Propaga -->
|
||||
@ -44,45 +48,54 @@
|
||||
<select id="global-matrice" class="form-control form-control-sm" style="width: 350px !important; margin-right: 10px;"></select>
|
||||
<button type="button" class="btn btn-primary btn-sm propagate-all-btn" style="padding: 0.1rem 0.5rem; font-size: 0.8rem;"><i class="fas fa-arrow-right"></i> Propaga a tutte</button>
|
||||
</div>
|
||||
<table class="table table-striped table-sm" id="partsTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 55px;">Num</th>
|
||||
<th>Descrizione</th>
|
||||
<th style="width: 200px;">Matrice</th>
|
||||
<th style="width: 150px;">
|
||||
<input type="date" class="form-control form-control-sm propagate-date-input" style="width: 130px; margin-left: 5px; display: inline-block;" title="Propaga data a tutte le parti">
|
||||
</th>
|
||||
<th style="width: 200px;">
|
||||
<button type="button" class="btn btn-light btn-sm propagate-note-btn" style="padding: 0.2rem 0.4rem; font-size: 0.9rem; margin-left: 5px;" title="Propaga nota a tutte le parti">
|
||||
<i class="fas fa-sticky-note"></i>
|
||||
</button>
|
||||
Azioni
|
||||
<div class="parts-table-scroll">
|
||||
<table class="table table-striped table-sm" id="partsTable">
|
||||
<colgroup id="partsTableColgroup">
|
||||
<col class="parts-col-num">
|
||||
<col class="parts-col-description">
|
||||
<col class="parts-col-matrice">
|
||||
<col class="parts-col-date">
|
||||
<col class="parts-col-actions">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 55px;">Num</th>
|
||||
<th>Descrizione</th>
|
||||
<th style="width: 200px;">Matrice</th>
|
||||
<th style="width: 150px;">
|
||||
<input type="date" class="form-control form-control-sm propagate-date-input" style="width: 130px; margin-left: 5px; display: inline-block;" title="Propaga data a tutte le parti">
|
||||
</th>
|
||||
<th style="width: 200px;">
|
||||
<button type="button" class="btn btn-light btn-sm propagate-note-btn" style="padding: 0.2rem 0.4rem; font-size: 0.9rem; margin-left: 5px;" title="Propaga nota a tutte le parti">
|
||||
<i class="fas fa-sticky-note"></i>
|
||||
</button>
|
||||
Azioni
|
||||
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="partsTableBody">
|
||||
<tr data-part-id="new">
|
||||
<td><input type="number" class="form-control form-control-sm part-number" value="1" style="width: 55px;"></td>
|
||||
<td><input type="text" class="form-control form-control-sm part-description" placeholder="Inserisci descrizione"></td>
|
||||
<td>
|
||||
<div style="display: flex; align-items: center;">
|
||||
<button type="button" class="btn btn-primary btn-sm propagate-matrice-btn" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; margin-right: 3px;"><i class="fas fa-arrow-right"></i></button>
|
||||
<select class="part-matrice form-control form-control-sm" style="width: 150px;"></select>
|
||||
</div>
|
||||
</td>
|
||||
<td><input type="date" class="form-control form-control-sm part-dateexpiry" style="width: 130px;"></td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-light btn-sm note-btn" style="padding: 0.2rem 0.4rem; font-size: 0.9rem;" title="Aggiungi/Modifica nota"><i class="fas fa-sticky-note"></i></button>
|
||||
<button type="button" class="btn btn-warning btn-sm add-mix-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;">M+</button>
|
||||
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; display: none;"><i class="fas fa-trash"></i></button>
|
||||
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check"></i></span>
|
||||
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin"></i></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="partsTableBody">
|
||||
<tr data-part-id="new">
|
||||
<td><input type="number" class="form-control form-control-sm part-number" value="1" style="width: 55px;"></td>
|
||||
<td><input type="text" class="form-control form-control-sm part-description" placeholder="Inserisci descrizione"></td>
|
||||
<td>
|
||||
<div style="display: flex; align-items: center;">
|
||||
<button type="button" class="btn btn-primary btn-sm propagate-matrice-btn" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; margin-right: 3px;"><i class="fas fa-arrow-right"></i></button>
|
||||
<select class="part-matrice form-control form-control-sm" style="width: 150px;"></select>
|
||||
</div>
|
||||
</td>
|
||||
<td><input type="date" class="form-control form-control-sm part-dateexpiry" style="width: 130px;"></td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-light btn-sm note-btn" style="padding: 0.2rem 0.4rem; font-size: 0.9rem;" title="Aggiungi/Modifica nota"><i class="fas fa-sticky-note"></i></button>
|
||||
<button type="button" class="btn btn-warning btn-sm add-mix-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem;">M+</button>
|
||||
<button type="button" class="btn btn-danger btn-sm remove-row" style="padding: 0.1rem 0.3rem; font-size: 0.8rem; display: none;"><i class="fas fa-trash"></i></button>
|
||||
<span class="save-status text-success" style="display: none; margin-left: 5px;"><i class="fas fa-check"></i></span>
|
||||
<span class="save-loading text-warning" style="display: none; margin-left: 5px;"><i class="fas fa-spinner fa-spin"></i></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<h6>Foto del Campione</h6>
|
||||
@ -290,28 +303,20 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* Select delle righe (colonna Matrice) = 150px */
|
||||
/* Select delle righe Matrice: si adatta alla colonna */
|
||||
.part-matrice {
|
||||
width: 300px !important;
|
||||
min-width: 300px !important;
|
||||
max-width: 300px !important;
|
||||
flex: 0 0 300px !important;
|
||||
width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.part-matrice.select2-hidden-accessible+.select2 {
|
||||
width: 300px !important;
|
||||
min-width: 300px !important;
|
||||
max-width: 300px !important;
|
||||
flex: 0 0 300px !important;
|
||||
width: 100% !important;
|
||||
min-width: 0 !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
/* Colonna Descrizione (2ª colonna) = 420px */
|
||||
#partsTable th:nth-child(2),
|
||||
#partsTable td:nth-child(2) {
|
||||
width: 300px !important;
|
||||
min-width: 300px !important;
|
||||
max-width: 300px !important;
|
||||
}
|
||||
|
||||
|
||||
#partsTable .part-number {
|
||||
text-align: center;
|
||||
@ -516,6 +521,77 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* Resizable parts table - stable */
|
||||
.parts-table-scroll {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
overflow-y: visible;
|
||||
contain: inline-size;
|
||||
}
|
||||
|
||||
#partsTable {
|
||||
table-layout: fixed !important;
|
||||
width: max-content !important;
|
||||
min-width: unset !important;
|
||||
}
|
||||
|
||||
#partsTable col.parts-col-num {
|
||||
width: 55px;
|
||||
}
|
||||
|
||||
#partsTable col.parts-col-description {
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
#partsTable col.parts-col-matrice {
|
||||
width: 360px;
|
||||
}
|
||||
|
||||
#partsTable col.parts-col-date {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#partsTable col.parts-col-actions {
|
||||
width: 230px;
|
||||
}
|
||||
|
||||
#partsTable th,
|
||||
#partsTable td {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#partsTable th {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#partsTable th .parts-resizer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 9px;
|
||||
height: 100%;
|
||||
cursor: col-resize;
|
||||
z-index: 50;
|
||||
background: rgba(108, 117, 125, 0.12);
|
||||
border-right: 1px solid rgba(108, 117, 125, 0.45);
|
||||
}
|
||||
|
||||
#partsTable th .parts-resizer:hover {
|
||||
background: rgba(108, 117, 125, 0.25);
|
||||
border-right: 2px solid rgba(73, 80, 87, 0.7);
|
||||
}
|
||||
|
||||
#partsTable td {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
#partsTable td input,
|
||||
#partsTable td select,
|
||||
#partsTable td .select2-container {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
/* rosso */
|
||||
</style>
|
||||
@ -2463,4 +2463,142 @@ $(document).on("click", "#showHideImageBtn", function () {
|
||||
"<i class='fas fa-eye' style='font-size: 0.8rem;'></i><i class='fas fa-image ms-1' style='font-size: 0.8rem;'></i>",
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof window.applyPartsColumnWidths === "function") {
|
||||
setTimeout(window.applyPartsColumnWidths, 150);
|
||||
}
|
||||
});
|
||||
// ===================
|
||||
// RESIZABLE PARTS TABLE COLUMNS - FIXED COLGROUP VERSION
|
||||
// ===================
|
||||
(function () {
|
||||
// Larghezze default per indice colonna (0-based)
|
||||
const defaultWidths = [55, 320, 360, 150, 230];
|
||||
const savedWidths = [...defaultWidths];
|
||||
|
||||
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 <col> quante <th>
|
||||
while ($colgroup.find("col").length < thCount) {
|
||||
$colgroup.append("<col>");
|
||||
}
|
||||
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 applyColumnWidth(colIndex, newWidth) {
|
||||
const w = Math.max(40, Math.round(newWidth));
|
||||
savedWidths[colIndex] = w;
|
||||
|
||||
const $col = getColgroup().find("col").eq(colIndex);
|
||||
if ($col.length) {
|
||||
$col.css("width", w + "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 addResizers() {
|
||||
const $table = $("#partsTable");
|
||||
if (!$table.length) 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;
|
||||
|
||||
const $resizer = $("<span class='parts-resizer'></span>");
|
||||
$th.css("position", "relative"); // necessario per il posizionamento assoluto
|
||||
$th.append($resizer);
|
||||
|
||||
$resizer.on("mousedown", function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const startX = e.pageX;
|
||||
// Leggi la larghezza ESATTA dalla <col>, non dal <th>
|
||||
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");
|
||||
|
||||
$(document).on("mousemove.partsResize", function (ev) {
|
||||
const delta = ev.pageX - startX;
|
||||
applyColumnWidth(colIndex, startWidth + delta);
|
||||
});
|
||||
|
||||
$(document).on("mouseup.partsResize", function () {
|
||||
$("body").css("user-select", "").css("cursor", "");
|
||||
$(document).off(".partsResize");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
syncColgroupToHeaders();
|
||||
addResizers();
|
||||
}
|
||||
|
||||
// Init al primo show del modale
|
||||
$(document).on("shown.bs.modal", "#partsModal", function () {
|
||||
setTimeout(init, 120);
|
||||
});
|
||||
|
||||
// Re-init dopo ogni AJAX (nuove righe, caricamenti)
|
||||
$(document).ajaxComplete(function () {
|
||||
if ($("#partsModal").hasClass("show")) {
|
||||
setTimeout(syncColgroupToHeaders, 200);
|
||||
setTimeout(addResizers, 220);
|
||||
}
|
||||
});
|
||||
|
||||
// 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);
|
||||
},
|
||||
);
|
||||
|
||||
window.initPartsResizableColumns = init;
|
||||
window.applyPartsColumnWidths = syncColgroupToHeaders;
|
||||
})();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user