Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 485f0b69c8 | |||
| f380c152ca | |||
| 79c8c7e6a4 | |||
| 6cf355071b |
@@ -501,11 +501,19 @@ public class JobsController : Controller
|
|||||||
// Inventory items for the manual log-material modal
|
// Inventory items for the manual log-material modal
|
||||||
var inventoryItemsForModal = (await _unitOfWork.InventoryItems.GetAllAsync())
|
var inventoryItemsForModal = (await _unitOfWork.InventoryItems.GetAllAsync())
|
||||||
.OrderBy(i => i.Name)
|
.OrderBy(i => i.Name)
|
||||||
.Select(i => new { i.Id, i.Name, i.UnitOfMeasure, i.QuantityOnHand })
|
.Select(i => new { i.Id, i.Name, i.Manufacturer, i.UnitOfMeasure, i.QuantityOnHand })
|
||||||
.ToList();
|
.ToList();
|
||||||
ViewBag.InventoryItemsForModal = System.Text.Json.JsonSerializer.Serialize(
|
var jsonOpts = new System.Text.Json.JsonSerializerOptions { PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase };
|
||||||
inventoryItemsForModal,
|
ViewBag.InventoryItemsForModal = System.Text.Json.JsonSerializer.Serialize(inventoryItemsForModal, jsonOpts);
|
||||||
new System.Text.Json.JsonSerializerOptions { PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase });
|
|
||||||
|
// IDs of powders already assigned to this job's coats — shown at top of log-material dropdown
|
||||||
|
var jobPowderIds = (jobDto.Items ?? new List<PowderCoating.Application.DTOs.Job.JobItemDto>())
|
||||||
|
.SelectMany(i => i.Coats ?? new List<PowderCoating.Application.DTOs.Job.JobItemCoatDto>())
|
||||||
|
.Where(c => c.InventoryItemId.HasValue)
|
||||||
|
.Select(c => c.InventoryItemId!.Value)
|
||||||
|
.Distinct()
|
||||||
|
.ToList();
|
||||||
|
ViewBag.JobPowderIds = System.Text.Json.JsonSerializer.Serialize(jobPowderIds, jsonOpts);
|
||||||
|
|
||||||
// Pre-logged powder grouped by InventoryItemId (for Complete Job modal pre-fill)
|
// Pre-logged powder grouped by InventoryItemId (for Complete Job modal pre-fill)
|
||||||
ViewBag.PreLoggedPowder = allJobTransactions
|
ViewBag.PreLoggedPowder = allJobTransactions
|
||||||
|
|||||||
@@ -1105,9 +1105,22 @@
|
|||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label class="form-label fw-semibold">Inventory Item <span class="text-danger">*</span></label>
|
<label class="form-label fw-semibold">Inventory Item <span class="text-danger">*</span></label>
|
||||||
<select id="lmInventoryItem" class="form-select">
|
<div class="position-relative">
|
||||||
<option value="">-- Select item --</option>
|
<div class="input-group">
|
||||||
</select>
|
<input type="text" class="form-control" id="lmItemSearch"
|
||||||
|
placeholder="Search by name or manufacturer…" autocomplete="off"
|
||||||
|
oninput="lmComboInput()"
|
||||||
|
onfocus="lmComboOpen()"
|
||||||
|
onkeydown="lmComboKey(event)">
|
||||||
|
<button class="btn btn-outline-secondary" type="button" tabindex="-1"
|
||||||
|
id="lmItemDropdownToggle" onclick="lmComboToggle()">
|
||||||
|
<i class="bi bi-chevron-down" style="font-size:.75rem;"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="lmItemDropdown"
|
||||||
|
style="display:none;max-height:220px;overflow-y:auto;z-index:1070;background:#fff;border:1px solid rgba(0,0,0,.15);border-radius:.375rem;box-shadow:0 4px 12px rgba(0,0,0,.12);">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div id="lmItemBalance" class="form-text text-muted d-none"></div>
|
<div id="lmItemBalance" class="form-text text-muted d-none"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
@@ -3149,10 +3162,11 @@
|
|||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
const inventoryItems = @Html.Raw(ViewBag.InventoryItemsForModal ?? "[]");
|
const inventoryItems = @Html.Raw(ViewBag.InventoryItemsForModal ?? "[]");
|
||||||
|
const jobPowderIds = @Html.Raw(ViewBag.JobPowderIds ?? "[]");
|
||||||
const jobId = @Model.Id;
|
const jobId = @Model.Id;
|
||||||
const logUrl = '@Url.Action("LogMaterial", "Jobs")';
|
const logUrl = '@Url.Action("LogMaterial", "Jobs")';
|
||||||
const token = document.querySelector('input[name="__RequestVerificationToken"]')?.value ?? '';
|
const token = document.querySelector('input[name="__RequestVerificationToken"]')?.value ?? '';
|
||||||
window.__logMaterial = { inventoryItems, jobId, logUrl, token };
|
window.__logMaterial = { inventoryItems, jobPowderIds, jobId, logUrl, token };
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -4,62 +4,173 @@
|
|||||||
*/
|
*/
|
||||||
(function () {
|
(function () {
|
||||||
let _items = [];
|
let _items = [];
|
||||||
|
let _jobPowderIds = new Set();
|
||||||
let _modal = null;
|
let _modal = null;
|
||||||
|
|
||||||
function init() {
|
// ── Combobox state ────────────────────────────────────────────────────────
|
||||||
const cfg = window.__logMaterial;
|
let _selectedItemId = 0;
|
||||||
if (!cfg) return;
|
|
||||||
|
|
||||||
_items = cfg.inventoryItems || [];
|
function lmComboInput() {
|
||||||
_modal = new bootstrap.Modal(document.getElementById('logMaterialModal'));
|
const q = document.getElementById('lmItemSearch')?.value?.toLowerCase() || '';
|
||||||
|
lmComboRender(q);
|
||||||
const sel = document.getElementById('lmInventoryItem');
|
lmComboShow();
|
||||||
_items.forEach(function (item) {
|
_selectedItemId = 0;
|
||||||
const opt = document.createElement('option');
|
document.getElementById('lmItemBalance').classList.add('d-none');
|
||||||
opt.value = item.id;
|
|
||||||
opt.textContent = item.name + (item.unitOfMeasure ? ' (' + item.unitOfMeasure + ')' : '');
|
|
||||||
opt.dataset.qty = item.quantityOnHand;
|
|
||||||
opt.dataset.uom = item.unitOfMeasure || '';
|
|
||||||
sel.appendChild(opt);
|
|
||||||
});
|
|
||||||
|
|
||||||
sel.addEventListener('change', lmOnItemChange);
|
|
||||||
document.getElementById('lmQuantity').addEventListener('input', lmOnQtyInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
function lmOnItemChange() {
|
|
||||||
const sel = document.getElementById('lmInventoryItem');
|
|
||||||
const opt = sel.options[sel.selectedIndex];
|
|
||||||
const balDiv = document.getElementById('lmItemBalance');
|
|
||||||
if (sel.value && opt) {
|
|
||||||
const qty = parseFloat(opt.dataset.qty) || 0;
|
|
||||||
const uom = opt.dataset.uom;
|
|
||||||
balDiv.textContent = 'Current stock: ' + qty.toFixed(2) + (uom ? ' ' + uom : '');
|
|
||||||
balDiv.classList.remove('d-none');
|
|
||||||
} else {
|
|
||||||
balDiv.classList.add('d-none');
|
|
||||||
}
|
|
||||||
lmOnQtyInput();
|
lmOnQtyInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function lmComboOpen() {
|
||||||
|
const q = document.getElementById('lmItemSearch')?.value?.toLowerCase() || '';
|
||||||
|
lmComboRender(q);
|
||||||
|
lmComboShow();
|
||||||
|
}
|
||||||
|
|
||||||
|
function lmComboToggle() {
|
||||||
|
const dd = document.getElementById('lmItemDropdown');
|
||||||
|
if (!dd) return;
|
||||||
|
if (dd.style.display === 'none' || !dd.style.display) {
|
||||||
|
lmComboOpen();
|
||||||
|
document.getElementById('lmItemSearch')?.focus();
|
||||||
|
} else {
|
||||||
|
lmComboClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function lmMakeRow(it) {
|
||||||
|
const display = (it.manufacturer ? escLm(it.manufacturer) + ' – ' : '') +
|
||||||
|
escLm(it.name) +
|
||||||
|
(it.unitOfMeasure ? ' <span class="text-muted" style="font-size:.82rem;">(' + escLm(it.unitOfMeasure) + ')</span>' : '');
|
||||||
|
const label = (it.manufacturer ? it.manufacturer + ' - ' : '') +
|
||||||
|
it.name +
|
||||||
|
(it.unitOfMeasure ? ' (' + it.unitOfMeasure + ')' : '');
|
||||||
|
return `<div class="lm-item-opt" style="padding:.35rem .75rem;font-size:.875rem;cursor:pointer;"
|
||||||
|
data-id="${it.id}"
|
||||||
|
data-qty="${it.quantityOnHand}"
|
||||||
|
data-uom="${escLm(it.unitOfMeasure || '')}"
|
||||||
|
data-label="${escLm(label)}"
|
||||||
|
onmousedown="event.preventDefault(); lmComboSelect(this)"
|
||||||
|
onmouseenter="this.style.background='#f0f4ff'"
|
||||||
|
onmouseleave="this.classList.contains('lm-active') ? null : this.style.background=''">
|
||||||
|
${display}
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lmComboRender(query) {
|
||||||
|
const dd = document.getElementById('lmItemDropdown');
|
||||||
|
if (!dd) return;
|
||||||
|
const filtered = query
|
||||||
|
? _items.filter(it => it.name.toLowerCase().includes(query) ||
|
||||||
|
(it.manufacturer && it.manufacturer.toLowerCase().includes(query)) ||
|
||||||
|
(it.unitOfMeasure && it.unitOfMeasure.toLowerCase().includes(query)))
|
||||||
|
: _items;
|
||||||
|
if (filtered.length === 0) {
|
||||||
|
dd.innerHTML = '<div class="px-3 py-2 text-muted small">No items match.</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const jobItems = filtered.filter(it => _jobPowderIds.has(it.id));
|
||||||
|
const otherItems = filtered.filter(it => !_jobPowderIds.has(it.id));
|
||||||
|
|
||||||
|
let html = '';
|
||||||
|
if (jobItems.length > 0) {
|
||||||
|
html += '<div class="px-3 py-1 text-muted" style="font-size:.72rem;letter-spacing:.04em;text-transform:uppercase;background:#f8f9fa;border-bottom:1px solid #dee2e6;">This Job</div>';
|
||||||
|
html += jobItems.map(lmMakeRow).join('');
|
||||||
|
if (otherItems.length > 0) {
|
||||||
|
html += '<div style="height:1px;background:#dee2e6;margin:.25rem 0;"></div>';
|
||||||
|
html += '<div class="px-3 py-1 text-muted" style="font-size:.72rem;letter-spacing:.04em;text-transform:uppercase;background:#f8f9fa;border-bottom:1px solid #dee2e6;">All Inventory</div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html += otherItems.map(lmMakeRow).join('');
|
||||||
|
dd.innerHTML = html;
|
||||||
|
}
|
||||||
|
|
||||||
|
function lmComboShow() {
|
||||||
|
const dd = document.getElementById('lmItemDropdown');
|
||||||
|
const anchor = document.getElementById('lmItemSearch');
|
||||||
|
if (!dd || !anchor) return;
|
||||||
|
const rect = anchor.closest('.input-group').getBoundingClientRect();
|
||||||
|
dd.style.position = 'fixed';
|
||||||
|
dd.style.top = (rect.bottom + 2) + 'px';
|
||||||
|
dd.style.left = rect.left + 'px';
|
||||||
|
dd.style.width = rect.width + 'px';
|
||||||
|
dd.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function lmComboClose() {
|
||||||
|
const dd = document.getElementById('lmItemDropdown');
|
||||||
|
if (dd) dd.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
window.lmComboSelect = function (el) {
|
||||||
|
_selectedItemId = parseInt(el.dataset.id) || 0;
|
||||||
|
document.getElementById('lmItemSearch').value = el.dataset.label;
|
||||||
|
lmComboClose();
|
||||||
|
|
||||||
|
const qty = parseFloat(el.dataset.qty) || 0;
|
||||||
|
const uom = el.dataset.uom;
|
||||||
|
const balDiv = document.getElementById('lmItemBalance');
|
||||||
|
balDiv.textContent = 'Current stock: ' + qty.toFixed(2) + (uom ? ' ' + uom : '');
|
||||||
|
balDiv.classList.remove('d-none');
|
||||||
|
lmOnQtyInput();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.lmComboInput = lmComboInput;
|
||||||
|
window.lmComboOpen = lmComboOpen;
|
||||||
|
window.lmComboToggle = lmComboToggle;
|
||||||
|
|
||||||
|
window.lmComboKey = function (event) {
|
||||||
|
const dd = document.getElementById('lmItemDropdown');
|
||||||
|
if (!dd || dd.style.display === 'none') {
|
||||||
|
if (event.key === 'ArrowDown' || event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
lmComboOpen();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const opts = Array.from(dd.querySelectorAll('.lm-item-opt'));
|
||||||
|
let idx = opts.findIndex(o => o.classList.contains('lm-active'));
|
||||||
|
if (event.key === 'ArrowDown') {
|
||||||
|
event.preventDefault();
|
||||||
|
idx = Math.min(idx + 1, opts.length - 1);
|
||||||
|
opts.forEach(o => { o.classList.remove('lm-active'); o.style.background = ''; });
|
||||||
|
if (opts[idx]) { opts[idx].classList.add('lm-active'); opts[idx].style.background = '#e8eeff'; opts[idx].scrollIntoView({ block: 'nearest' }); }
|
||||||
|
} else if (event.key === 'ArrowUp') {
|
||||||
|
event.preventDefault();
|
||||||
|
idx = Math.max(idx - 1, 0);
|
||||||
|
opts.forEach(o => { o.classList.remove('lm-active'); o.style.background = ''; });
|
||||||
|
if (opts[idx]) { opts[idx].classList.add('lm-active'); opts[idx].style.background = '#e8eeff'; opts[idx].scrollIntoView({ block: 'nearest' }); }
|
||||||
|
} else if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
const active = dd.querySelector('.lm-active') || opts[0];
|
||||||
|
if (active) active.dispatchEvent(new MouseEvent('mousedown'));
|
||||||
|
} else if (event.key === 'Escape') {
|
||||||
|
lmComboClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function escLm(s) {
|
||||||
|
return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Quantity / label logic ────────────────────────────────────────────────
|
||||||
|
|
||||||
function lmOnQtyInput() {
|
function lmOnQtyInput() {
|
||||||
const method = document.querySelector('input[name="lmEntryMethod"]:checked')?.value;
|
const method = document.querySelector('input[name="lmEntryMethod"]:checked')?.value;
|
||||||
if (method !== 'remaining') {
|
if (method !== 'remaining') {
|
||||||
document.getElementById('lmComputedUsed').classList.add('d-none');
|
document.getElementById('lmComputedUsed').classList.add('d-none');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const sel = document.getElementById('lmInventoryItem');
|
if (!_selectedItemId) {
|
||||||
const opt = sel.options[sel.selectedIndex];
|
document.getElementById('lmComputedUsed').classList.add('d-none');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const item = _items.find(it => it.id === _selectedItemId);
|
||||||
|
const onHand = item ? (parseFloat(item.quantityOnHand) || 0) : 0;
|
||||||
const remaining = parseFloat(document.getElementById('lmQuantity').value) || 0;
|
const remaining = parseFloat(document.getElementById('lmQuantity').value) || 0;
|
||||||
const onHand = parseFloat(opt?.dataset.qty) || 0;
|
|
||||||
const used = onHand - remaining;
|
const used = onHand - remaining;
|
||||||
const computedDiv = document.getElementById('lmComputedUsed');
|
const computedDiv = document.getElementById('lmComputedUsed');
|
||||||
if (sel.value) {
|
computedDiv.textContent = 'Usage = ' + onHand.toFixed(2) + ' − ' + remaining.toFixed(2) + ' = ' + used.toFixed(2) + (item?.unitOfMeasure ? ' ' + item.unitOfMeasure : '');
|
||||||
computedDiv.textContent = 'Usage = ' + onHand.toFixed(2) + ' − ' + remaining.toFixed(2) + ' = ' + used.toFixed(2) + ' ' + (opt?.dataset.uom || '');
|
computedDiv.classList.remove('d-none');
|
||||||
computedDiv.classList.remove('d-none');
|
|
||||||
} else {
|
|
||||||
computedDiv.classList.add('d-none');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window.lmUpdateQuantityLabel = function () {
|
window.lmUpdateQuantityLabel = function () {
|
||||||
@@ -70,9 +181,11 @@
|
|||||||
lmOnQtyInput();
|
lmOnQtyInput();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── Modal open / save ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
window.openLogMaterialModal = function () {
|
window.openLogMaterialModal = function () {
|
||||||
// Reset form
|
_selectedItemId = 0;
|
||||||
document.getElementById('lmInventoryItem').value = '';
|
document.getElementById('lmItemSearch').value = '';
|
||||||
document.getElementById('lmItemBalance').classList.add('d-none');
|
document.getElementById('lmItemBalance').classList.add('d-none');
|
||||||
document.getElementById('lmQuantity').value = '';
|
document.getElementById('lmQuantity').value = '';
|
||||||
document.getElementById('lmComputedUsed').classList.add('d-none');
|
document.getElementById('lmComputedUsed').classList.add('d-none');
|
||||||
@@ -82,14 +195,12 @@
|
|||||||
document.getElementById('lmSaveBtn').disabled = false;
|
document.getElementById('lmSaveBtn').disabled = false;
|
||||||
document.getElementById('lmMethodUsed').checked = true;
|
document.getElementById('lmMethodUsed').checked = true;
|
||||||
window.lmUpdateQuantityLabel();
|
window.lmUpdateQuantityLabel();
|
||||||
|
lmComboClose();
|
||||||
if (_modal) _modal.show();
|
if (_modal) _modal.show();
|
||||||
};
|
};
|
||||||
|
|
||||||
window.lmSave = async function () {
|
window.lmSave = async function () {
|
||||||
const cfg = window.__logMaterial;
|
const cfg = window.__logMaterial;
|
||||||
const itemId = parseInt(document.getElementById('lmInventoryItem').value) || 0;
|
|
||||||
const qtyInput = parseFloat(document.getElementById('lmQuantity').value) || 0;
|
|
||||||
const method = document.querySelector('input[name="lmEntryMethod"]:checked')?.value;
|
|
||||||
const alertEl = document.getElementById('lmAlert');
|
const alertEl = document.getElementById('lmAlert');
|
||||||
|
|
||||||
function showError(msg) {
|
function showError(msg) {
|
||||||
@@ -98,13 +209,16 @@
|
|||||||
alertEl.classList.remove('d-none');
|
alertEl.classList.remove('d-none');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!itemId) { showError('Please select an inventory item.'); return; }
|
if (!_selectedItemId) { showError('Please select an inventory item.'); return; }
|
||||||
|
|
||||||
|
const qtyInput = parseFloat(document.getElementById('lmQuantity').value) || 0;
|
||||||
if (qtyInput <= 0) { showError('Please enter a quantity greater than zero.'); return; }
|
if (qtyInput <= 0) { showError('Please enter a quantity greater than zero.'); return; }
|
||||||
|
|
||||||
|
const method = document.querySelector('input[name="lmEntryMethod"]:checked')?.value;
|
||||||
let quantityUsed = qtyInput;
|
let quantityUsed = qtyInput;
|
||||||
if (method === 'remaining') {
|
if (method === 'remaining') {
|
||||||
const sel = document.getElementById('lmInventoryItem');
|
const item = _items.find(it => it.id === _selectedItemId);
|
||||||
const onHand = parseFloat(sel.options[sel.selectedIndex]?.dataset.qty) || 0;
|
const onHand = item ? (parseFloat(item.quantityOnHand) || 0) : 0;
|
||||||
quantityUsed = onHand - qtyInput;
|
quantityUsed = onHand - qtyInput;
|
||||||
if (quantityUsed <= 0) {
|
if (quantityUsed <= 0) {
|
||||||
showError('Remaining quantity cannot be equal to or greater than the current stock (' + onHand.toFixed(2) + ').');
|
showError('Remaining quantity cannot be equal to or greater than the current stock (' + onHand.toFixed(2) + ').');
|
||||||
@@ -125,7 +239,7 @@
|
|||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
jobId: cfg.jobId,
|
jobId: cfg.jobId,
|
||||||
inventoryItemId: itemId,
|
inventoryItemId: _selectedItemId,
|
||||||
quantityUsed: quantityUsed,
|
quantityUsed: quantityUsed,
|
||||||
transactionType: document.getElementById('lmTransactionType').value,
|
transactionType: document.getElementById('lmTransactionType').value,
|
||||||
notes: document.getElementById('lmNotes').value.trim() || null
|
notes: document.getElementById('lmNotes').value.trim() || null
|
||||||
@@ -134,7 +248,6 @@
|
|||||||
const data = await resp.json();
|
const data = await resp.json();
|
||||||
if (data.success) {
|
if (data.success) {
|
||||||
if (_modal) _modal.hide();
|
if (_modal) _modal.hide();
|
||||||
// Reload page so the materials table refreshes
|
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
showError(data.message || 'An error occurred.');
|
showError(data.message || 'An error occurred.');
|
||||||
@@ -146,5 +259,27 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── Init ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
const cfg = window.__logMaterial;
|
||||||
|
if (!cfg) return;
|
||||||
|
|
||||||
|
_items = cfg.inventoryItems || [];
|
||||||
|
_jobPowderIds = new Set(cfg.jobPowderIds || []);
|
||||||
|
_modal = new bootstrap.Modal(document.getElementById('logMaterialModal'));
|
||||||
|
|
||||||
|
document.getElementById('lmQuantity').addEventListener('input', lmOnQtyInput);
|
||||||
|
|
||||||
|
// Close dropdown when clicking outside
|
||||||
|
document.addEventListener('click', function (e) {
|
||||||
|
if (!e.target.closest('#lmItemSearch') &&
|
||||||
|
!e.target.closest('#lmItemDropdown') &&
|
||||||
|
!e.target.closest('#lmItemDropdownToggle')) {
|
||||||
|
lmComboClose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
document.addEventListener('DOMContentLoaded', init);
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user