fixed column imballaggi
This commit is contained in:
@@ -68,41 +68,50 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Column widths */
|
||||
#tabPackaging th:nth-child(1),
|
||||
#tabPackaging td:nth-child(1) {
|
||||
width: 60px;
|
||||
max-width: 60px;
|
||||
/* Ridimensionamento colonne: le larghezze stanno nel <colgroup> */
|
||||
#tabPackaging thead th {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#tabPackaging th:nth-child(2),
|
||||
#tabPackaging td:nth-child(2) {
|
||||
width: 170px;
|
||||
max-width: 170px;
|
||||
.pkcol-grip {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 14px;
|
||||
height: 100%;
|
||||
cursor: col-resize;
|
||||
z-index: 6;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
#tabPackaging th:nth-child(4),
|
||||
#tabPackaging td:nth-child(4) {
|
||||
width: 140px;
|
||||
max-width: 140px;
|
||||
.pkcol-grip::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 22%;
|
||||
bottom: 22%;
|
||||
right: 0;
|
||||
width: 3px;
|
||||
border-radius: 2px;
|
||||
background: #8fb3e3;
|
||||
}
|
||||
|
||||
#tabPackaging th:nth-child(5),
|
||||
#tabPackaging td:nth-child(5) {
|
||||
width: 110px;
|
||||
max-width: 110px;
|
||||
.pkcol-grip:hover::after,
|
||||
.pkcol-grip.pkcol-active::after {
|
||||
background: #0d6efd;
|
||||
}
|
||||
|
||||
#tabPackaging th:nth-child(6),
|
||||
#tabPackaging td:nth-child(6) {
|
||||
width: 120px;
|
||||
max-width: 120px;
|
||||
body.pkcol-dragging,
|
||||
body.pkcol-dragging * {
|
||||
cursor: col-resize !important;
|
||||
user-select: none !important;
|
||||
}
|
||||
|
||||
#tabPackaging th:nth-child(7),
|
||||
#tabPackaging td:nth-child(7) {
|
||||
width: 420px;
|
||||
max-width: 420px;
|
||||
/* Pulsanti azione solo icona */
|
||||
.pk-act {
|
||||
min-width: 40px;
|
||||
padding: 4px 8px;
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.back-dashboard {
|
||||
@@ -166,6 +175,7 @@
|
||||
<option value="OTHER">Altro</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" id="pkColReset" title="Riporta le colonne alla larghezza iniziale">↔ Colonne predefinite</button>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
@@ -229,6 +239,16 @@
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="tabPackaging" class="table table-striped align-middle text-center" style="width:100%;">
|
||||
<!-- Larghezze iniziali: la colonna senza width (Nome) prende lo spazio che resta -->
|
||||
<colgroup>
|
||||
<col data-w="60" style="width:60px">
|
||||
<col data-w="150" style="width:150px">
|
||||
<col data-flex="1">
|
||||
<col data-w="220" style="width:220px">
|
||||
<col data-w="120" style="width:120px">
|
||||
<col data-w="110" style="width:110px">
|
||||
<col data-w="230" data-min="210" style="width:230px">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
@@ -259,7 +279,8 @@
|
||||
? "<span class='badge bg-success'>Attivo</span>"
|
||||
: "<span class='badge bg-secondary'>Inattivo</span>";
|
||||
$toggleText = $isActive ? "Disattiva" : "Attiva";
|
||||
$toggleClass = $isActive ? "btn-outline-warning" : "btn-outline-success";
|
||||
$toggleClass = $isActive ? "btn-outline-danger" : "btn-outline-success";
|
||||
$toggleIcon = $isActive ? "🚫" : "✅";
|
||||
|
||||
$qtyTot = number_format((float)$r['qty_totale'], 3, ',', '.');
|
||||
$trClass = $isActive ? "" : " class='inactive-item'";
|
||||
@@ -272,23 +293,19 @@
|
||||
<td><span class='qty-badge'>{$qtyTot}</span></td>
|
||||
<td>{$badge}</td>
|
||||
<td>
|
||||
<button class='btn btn-sm btn-outline-primary edit-item'
|
||||
<button class='btn btn-sm btn-outline-primary pk-act edit-item'
|
||||
title='Modifica' aria-label='Modifica'
|
||||
data-id='{$r['id']}'
|
||||
data-category='" . htmlspecialchars($r['category'], ENT_QUOTES) . "'
|
||||
data-name='" . htmlspecialchars($r['item_name'], ENT_QUOTES) . "'
|
||||
data-code='" . htmlspecialchars($r['item_code'], ENT_QUOTES) . "'>
|
||||
✏️ Modifica
|
||||
</button>
|
||||
<button class='btn btn-sm btn-outline-dark manage-stock'
|
||||
data-code='" . htmlspecialchars($r['item_code'], ENT_QUOTES) . "'>✏️</button>
|
||||
<button class='btn btn-sm btn-outline-dark pk-act manage-stock'
|
||||
title='Stock' aria-label='Stock'
|
||||
data-id='{$r['id']}'
|
||||
data-name='" . htmlspecialchars($r['item_name'], ENT_QUOTES) . "'>
|
||||
📦 Stock
|
||||
</button>
|
||||
|
||||
<button class='btn btn-sm {$toggleClass} toggle-item'
|
||||
data-id='{$r['id']}'>
|
||||
🔁 {$toggleText}
|
||||
</button>
|
||||
data-name='" . htmlspecialchars($r['item_name'], ENT_QUOTES) . "'>📦 Stock</button>
|
||||
<button class='btn btn-sm {$toggleClass} pk-act toggle-item'
|
||||
title='{$toggleText}' aria-label='{$toggleText}'
|
||||
data-id='{$r['id']}'>{$toggleIcon}</button>
|
||||
</td>
|
||||
</tr>";
|
||||
}
|
||||
@@ -454,6 +471,7 @@
|
||||
|
||||
<script>
|
||||
let dt;
|
||||
let pkCols = null;
|
||||
|
||||
function refreshUrlParams() {
|
||||
const url = new URL(window.location.href);
|
||||
@@ -534,6 +552,153 @@
|
||||
});
|
||||
}
|
||||
|
||||
// ===== Colonne ridimensionabili =====
|
||||
// Le larghezze stanno nel <colgroup>. La colonna "flex" (Nome) assorbe le differenze,
|
||||
// quindi la tabella resta sempre larga quanto lo schermo e Azioni non esce mai.
|
||||
// Trascinando un bordo, lo spazio si sposta tra le due colonne vicine.
|
||||
function pkColResize(tableId) {
|
||||
var table = document.getElementById(tableId);
|
||||
if (!table) return null;
|
||||
|
||||
var KEY = 'zibo_pkcols_' + tableId;
|
||||
var FLEX_MIN = 120;
|
||||
var cols = Array.prototype.slice.call(table.querySelectorAll('colgroup col'));
|
||||
var ths = Array.prototype.slice.call(table.querySelectorAll('thead tr:first-child th'));
|
||||
var defaults = cols.map(function(c) {
|
||||
return c.hasAttribute('data-flex') ? null : parseInt(c.getAttribute('data-w'), 10);
|
||||
});
|
||||
var justDragged = false;
|
||||
|
||||
function isFlex(i) {
|
||||
return cols[i].hasAttribute('data-flex');
|
||||
}
|
||||
|
||||
function minOf(i) {
|
||||
if (isFlex(i)) return FLEX_MIN;
|
||||
return parseInt(cols[i].getAttribute('data-min') || '50', 10);
|
||||
}
|
||||
|
||||
function setW(i, w) {
|
||||
if (!isFlex(i)) cols[i].style.width = Math.round(w) + 'px';
|
||||
}
|
||||
|
||||
function realW(i) {
|
||||
return ths[i].getBoundingClientRect().width;
|
||||
}
|
||||
|
||||
function apply(widths) {
|
||||
widths.forEach(function(w, i) {
|
||||
if (w !== null) setW(i, w);
|
||||
});
|
||||
}
|
||||
|
||||
function current() {
|
||||
return cols.map(function(c, i) {
|
||||
return isFlex(i) ? null : parseInt(c.style.width, 10);
|
||||
});
|
||||
}
|
||||
|
||||
function save() {
|
||||
try {
|
||||
localStorage.setItem(KEY, JSON.stringify(current()));
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function reset() {
|
||||
apply(defaults);
|
||||
try {
|
||||
localStorage.removeItem(KEY);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Ripristino: solo se le colonne salvate stanno nello schermo attuale
|
||||
try {
|
||||
var saved = JSON.parse(localStorage.getItem(KEY) || 'null');
|
||||
if (Array.isArray(saved) && saved.length === cols.length) {
|
||||
var sum = saved.reduce(function(a, b) {
|
||||
return a + (b || 0);
|
||||
}, 0);
|
||||
if (sum + FLEX_MIN <= table.parentNode.clientWidth) apply(saved);
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
ths.forEach(function(th, i) {
|
||||
if (i === ths.length - 1) return; // ultima colonna: nessun bordo a destra
|
||||
|
||||
var grip = document.createElement('span');
|
||||
grip.className = 'pkcol-grip';
|
||||
grip.title = 'Trascina per allargare o stringere';
|
||||
th.appendChild(grip);
|
||||
|
||||
grip.addEventListener('pointerdown', function(e) {
|
||||
if (e.button !== undefined && e.button !== 0) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var j = i + 1;
|
||||
var startX = e.clientX;
|
||||
var a0 = realW(i);
|
||||
var b0 = realW(j);
|
||||
var lo = minOf(i) - a0; // spostamento minimo (negativo)
|
||||
var hi = b0 - minOf(j); // spostamento massimo
|
||||
if (hi < 0) hi = 0;
|
||||
if (lo > 0) lo = 0;
|
||||
|
||||
// fissa le due colonne alla larghezza reale attuale
|
||||
setW(i, a0);
|
||||
setW(j, b0);
|
||||
|
||||
try {
|
||||
grip.setPointerCapture(e.pointerId);
|
||||
} catch (err) {}
|
||||
grip.classList.add('pkcol-active');
|
||||
document.body.classList.add('pkcol-dragging');
|
||||
|
||||
function onMove(ev) {
|
||||
var d = ev.clientX - startX;
|
||||
if (d < lo) d = lo;
|
||||
if (d > hi) d = hi;
|
||||
setW(i, a0 + d);
|
||||
setW(j, b0 - d);
|
||||
}
|
||||
|
||||
function onUp() {
|
||||
grip.removeEventListener('pointermove', onMove);
|
||||
grip.removeEventListener('pointerup', onUp);
|
||||
grip.removeEventListener('pointercancel', onUp);
|
||||
grip.classList.remove('pkcol-active');
|
||||
document.body.classList.remove('pkcol-dragging');
|
||||
justDragged = true;
|
||||
setTimeout(function() {
|
||||
justDragged = false;
|
||||
}, 300);
|
||||
save();
|
||||
}
|
||||
|
||||
grip.addEventListener('pointermove', onMove);
|
||||
grip.addEventListener('pointerup', onUp);
|
||||
grip.addEventListener('pointercancel', onUp);
|
||||
});
|
||||
|
||||
grip.addEventListener('dblclick', function(e) {
|
||||
e.stopPropagation();
|
||||
reset();
|
||||
});
|
||||
});
|
||||
|
||||
// Il trascinamento non deve far partire l'ordinamento di DataTables
|
||||
table.querySelector('thead').addEventListener('click', function(e) {
|
||||
if (justDragged || (e.target.classList && e.target.classList.contains('pkcol-grip'))) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}, true);
|
||||
|
||||
return {
|
||||
reset: reset
|
||||
};
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
// Init filters from URL
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
@@ -545,11 +710,24 @@
|
||||
[2, 'asc']
|
||||
],
|
||||
pageLength: 50,
|
||||
autoWidth: false,
|
||||
columnDefs: [{
|
||||
targets: -1,
|
||||
orderable: false
|
||||
}],
|
||||
language: {
|
||||
url: 'https://cdn.datatables.net/plug-ins/1.13.6/i18n/it-IT.json'
|
||||
},
|
||||
initComplete: function() {
|
||||
// dopo che DataTables ha costruito le intestazioni
|
||||
pkCols = pkColResize('tabPackaging');
|
||||
}
|
||||
});
|
||||
|
||||
$('#pkColReset').on('click', function() {
|
||||
if (pkCols) pkCols.reset();
|
||||
});
|
||||
|
||||
$('#filterActive, #filterCategory').on('change', refreshUrlParams);
|
||||
});
|
||||
// Open edit item modal
|
||||
|
||||
Reference in New Issue
Block a user