« Back to History
mesr_zari.php
|
20260722_120325.php
Initial Domain Snapshot
Copy Code
<?php /* mesr_zari_directweight.php - Zari / Metalic / Winding pages (direct weight input) - All rows use direct weight input (kg) instead of cone/roll calculations. - Uses mesr_matrix for denier/color lookups and add-lookup persistence. - AJAX endpoints kept: cone_lookup, bobin_lookup (unused now for weight), add_lookup, save. - Fixes: prevents accidental form submit when adding lookups or pressing Enter inside table inputs. */ error_reporting(E_ALL); ini_set('display_errors',1); require_once __DIR__ . '/modules/auth/page_acl.php'; $ctx = page_require_access('mesr_zari'); $u = $ctx['user'] ?? null; $company_id = (int)($ctx['company_id'] ?? 0); $pdo = $ctx['pdo'] ?? null; if (!$pdo) require_once __DIR__ . '/core/db.php'; /* ---------------- AJAX handlers ---------------- */ /* cone_lookup kept (may still be used elsewhere) */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'cone_lookup') { header('Content-Type: application/json; charset=utf-8'); $den = trim($_POST['denier'] ?? ''); $col = trim($_POST['color'] ?? ''); try { $q = $pdo->prepare("SELECT cone_weight FROM mesr_matrix WHERE company_id = :cid AND matrix_type = 'cone_weight' AND LOWER(TRIM(denier)) = LOWER(TRIM(:denier)) AND LOWER(TRIM(color)) = LOWER(TRIM(:color)) LIMIT 1"); $q->execute([':cid'=>$company_id, ':denier'=>$den, ':color'=>$col]); $r = $q->fetch(PDO::FETCH_ASSOC); if ($r && $r['cone_weight'] !== null) { echo json_encode(['success'=>true,'cone_weight'=> (float)$r['cone_weight']]); exit; } $q2 = $pdo->prepare("SELECT cone_weight FROM mesr_matrix WHERE company_id = :cid AND matrix_type = 'cone_weight' AND (denier IS NULL OR TRIM(denier) = '') AND LOWER(TRIM(color)) = LOWER(TRIM(:color)) LIMIT 1"); $q2->execute([':cid'=>$company_id, ':color'=>$col]); $r2 = $q2->fetch(PDO::FETCH_ASSOC); if ($r2 && $r2['cone_weight'] !== null) { echo json_encode(['success'=>true,'cone_weight'=> (float)$r2['cone_weight']]); exit; } } catch (Exception $e) { echo json_encode(['success'=>false,'msg'=>'error']); exit; } echo json_encode(['success'=>false,'msg'=>'not_found']); exit; } /* bobin_lookup kept (fallback if ever needed) */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'bobin_lookup') { header('Content-Type: application/json; charset=utf-8'); $den = trim($_POST['denier'] ?? ''); $col = trim($_POST['color'] ?? ''); try { $q = $pdo->prepare("SELECT bobin_weight_gm FROM mesr_matrix WHERE company_id = :cid AND matrix_type = 'bobin_weight' AND LOWER(TRIM(denier)) = LOWER(TRIM(:denier)) AND LOWER(TRIM(color)) = LOWER(TRIM(:color)) LIMIT 1"); $q->execute([':cid'=>$company_id, ':denier'=>$den, ':color'=>$col]); $r = $q->fetch(PDO::FETCH_ASSOC); if ($r && $r['bobin_weight_gm'] !== null) { echo json_encode(['success'=>true,'bobin_weight_gm'=> (float)$r['bobin_weight_gm']]); exit; } } catch (Exception $e) { echo json_encode(['success'=>false,'msg'=>'error']); exit; } echo json_encode(['success'=>false,'msg'=>'not_found']); exit; } /* add_lookup persists denier/color into mesr_matrix */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'add_lookup') { header('Content-Type: application/json; charset=utf-8'); $type = trim($_POST['type'] ?? ''); $value = trim($_POST['value'] ?? ''); if (!$type || !$value) { echo json_encode(['success'=>false,'msg'=>'missing']); exit; } try { if ($type === 'denier') { $ins = $pdo->prepare("INSERT INTO mesr_matrix (company_id, matrix_type, denier, created_by, created_at) VALUES (:cid,'denier',:val,:uid,NOW())"); $ins->execute([':cid'=>$company_id, ':val'=>$value, ':uid'=>$u['id'] ?? null]); echo json_encode(['success'=>true]); exit; } elseif ($type === 'color') { $ins = $pdo->prepare("INSERT INTO mesr_matrix (company_id, matrix_type, color, created_by, created_at) VALUES (:cid,'color',:val,:uid,NOW())"); $ins->execute([':cid'=>$company_id, ':val'=>$value, ':uid'=>$u['id'] ?? null]); echo json_encode(['success'=>true]); exit; } } catch (Exception $e) { echo json_encode(['success'=>false,'msg'=>'db']); exit; } echo json_encode(['success'=>false,'msg'=>'unknown']); exit; } /* Save final month entry */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'save') { $token = $_POST['csrf_token'] ?? ''; if (!$token || !hash_equals($_SESSION['csrf_token'] ?? '', $token)) { echo "<div style='color:red;padding:10px;'>CSRF token mismatch.</div>"; exit; } $month = trim($_POST['month'] ?? ''); $location = trim($_POST['location'] ?? ''); $remark = trim($_POST['remark'] ?? ''); $sections_json = $_POST['sections_json'] ?? '[]'; if (!$month || !$location) { echo "<div style='color:orange;padding:10px;'>Please provide month and location.</div>"; exit; } $stock_type = $location . ' Zari Machine'; try { $ins = $pdo->prepare("INSERT INTO month_end_stock_report (company_id, month, stock_type, yarns_json, remark, created_by, created_at) VALUES (:cid, :month, :st, :yj, :remark, :uid, NOW())"); $ins->execute([ ':cid'=>$company_id, ':month'=>$month, ':st'=>$stock_type, ':yj'=>$sections_json, ':remark'=>$remark, ':uid'=>$u['id'] ?? null ]); echo "<div style='color:green;padding:10px;'>Saved successfully.</div>"; } catch (PDOException $ex) { echo "<div style='color:red;padding:10px;'>DB error: ".htmlspecialchars($ex->getMessage())."</div>"; } exit; } /* ---------------- End AJAX ---------------- */ /* include header if available */ $header_paths = [ __DIR__ . '/erp/partials/header.php', __DIR__ . '/partials/header.php', __DIR__ . '/header.php' ]; foreach ($header_paths as $hp) { if (file_exists($hp)) { require_once $hp; break; } } /* CSRF token for the form */ $csrf = $_SESSION['csrf_token'] ?? bin2hex(random_bytes(16)); $_SESSION['csrf_token'] = $csrf; /* load deniers/colors from mesr_matrix */ $deniers = []; $colors = []; try { $p = $pdo->prepare("SELECT DISTINCT TRIM(denier) AS denier FROM mesr_matrix WHERE company_id = :cid AND denier IS NOT NULL AND TRIM(denier) <> '' ORDER BY denier"); $p->execute([':cid'=>$company_id]); $deniers = array_column($p->fetchAll(PDO::FETCH_ASSOC), 'denier'); $q = $pdo->prepare("SELECT DISTINCT TRIM(color) AS color FROM mesr_matrix WHERE company_id = :cid AND color IS NOT NULL AND TRIM(color) <> '' ORDER BY color"); $q->execute([':cid'=>$company_id]); $colors = array_column($q->fetchAll(PDO::FETCH_ASSOC), 'color'); } catch (Exception $e) {} /* ensure defaults */ if (empty($deniers)) $deniers = ['110 Lichi']; if (empty($colors)) $colors = ['Gold','Maroon','Red']; ?> <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>MESR - Zari / Metalic (Direct Weight)</title> <meta name="viewport" content="width=device-width,initial-scale=1"> <style> body{font-family:Arial,Helvetica,sans-serif;background:#fff;padding:18px;} .card{border:1px solid #ddd;border-radius:6px;padding:16px;max-width:1200px;margin:8px auto;} .form-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;} .form-group{display:flex;flex-direction:column;margin-bottom:8px;} label{font-weight:600;margin-bottom:6px;} input.form-control, select.form-control, textarea.form-control{padding:8px;border:1px solid #ccc;border-radius:4px;} .btn{display:inline-block;padding:8px 12px;border-radius:6px;border:0;cursor:pointer;background:#2d6cdf;color:#fff;} .small-btn{padding:6px 8px;font-size:12px;margin-left:6px;} .table{width:100%;border-collapse:collapse;margin-top:8px;} .table th,.table td{border:1px solid #eee;padding:8px;font-size:13px;text-align:left;} .section{border:1px dashed #ccc;padding:10px;margin:12px 0;border-radius:6px;background:#fbfbfb;} .total{font-weight:700;} </style> </head> <body> <div class="card"> <h3>Zari / Metalic / Winding Entry (Direct Weight)</h3> <form id="mainForm" method="post" action=""> <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>"> <input type="hidden" name="action" value="save"> <div class="form-grid"> <div class="form-group"><label for="month">Month</label><input id="month" name="month" type="month" class="form-control" required></div> <div class="form-group"><label for="location">Location</label> <select id="location" name="location" class="form-control" required> <option value="">-- Select --</option> <option value="ZARI MACHINE">ZARI MACHINE</option> <option value="MST1">MST1</option> <option value="MST2A">MST2A</option> <option value="MST2B">MST2B</option> </select> </div> <div class="form-group"><label for="remark">Remark</label><input id="remark" name="remark" class="form-control"></div> </div> <!-- Zari Kasab - In --> <div class="section"> <h4>Zari Kasab - Total In Machine</h4> <button type="button" id="add_zk_in" class="small-btn">+ Add Row</button> <table class="table" id="tbl_zk_in"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="3" style="text-align:right;">Total Kg</td><td id="total_zk_in" class="total">0</td><td></td></tr></tfoot></table> </div> <!-- Zari Kasab - Out --> <div class="section"> <h4>Zari Kasab - Total Out</h4> <button type="button" id="add_zk_out" class="small-btn">+ Add Row</button> <table class="table" id="tbl_zk_out"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="3" style="text-align:right;">Total Kg</td><td id="total_zk_out" class="total">0</td><td></td></tr></tfoot></table> </div> <!-- Metalic in Machine / Open / Closed --> <div class="section"> <h4>Metalic - Total In Machine</h4> <button type="button" id="add_m_in" class="small-btn">+ Add Row</button> <table class="table" id="tbl_m_in"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="3" style="text-align:right;">Total Kg</td><td id="total_m_in" class="total">0</td><td></td></tr></tfoot></table> </div> <div class="section"> <h4>Metalic - Total in Open Box</h4> <button type="button" id="add_m_open" class="small-btn">+ Add Row</button> <table class="table" id="tbl_m_open"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="3" style="text-align:right;">Total Kg</td><td id="total_m_open" class="total">0</td><td></td></tr></tfoot></table> </div> <div class="section"> <h4>Metalic - Total in Closed Box</h4> <button type="button" id="add_m_closed" class="small-btn">+ Add Row</button> <table class="table" id="tbl_m_closed"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Box/ID</th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="4" style="text-align:right;">Total Kg</td><td id="total_m_closed" class="total">0</td><td></td></tr></tfoot></table> </div> <!-- Yarn in Winding / Zari / Open / Closed --> <div class="section"> <h4>Yarn in Winding Machine</h4> <button type="button" id="add_winding" class="small-btn">+ Add Row</button> <table class="table" id="tbl_winding"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="3" style="text-align:right;">Total Kg</td><td id="total_winding" class="total">0</td><td></td></tr></tfoot></table> </div> <div class="section"> <h4>Yarn in Zari Machine</h4> <button type="button" id="add_y_zari" class="small-btn">+ Add Row</button> <table class="table" id="tbl_y_zari"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="3" style="text-align:right;">Total Kg</td><td id="total_y_zari" class="total">0</td><td></td></tr></tfoot></table> </div> <div class="section"> <h4>Yarn in Open Box</h4> <button type="button" id="add_y_open" class="small-btn">+ Add Row</button> <table class="table" id="tbl_y_open"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="3" style="text-align:right;">Total Kg</td><td id="total_y_open" class="total">0</td><td></td></tr></tfoot></table> </div> <div class="section"> <h4>Yarn in Closed Box</h4> <button type="button" id="add_y_closed" class="small-btn">+ Add Row</button> <table class="table" id="tbl_y_closed"><thead><tr><th>#</th><th>Denier <button class="small-btn denier-add">+Add</button></th><th>Color <button class="small-btn color-add">+Add</button></th><th>Box/ID</th><th>Weight (kg)</th><th>Action</th></tr></thead><tbody></tbody> <tfoot><tr><td colspan="4" style="text-align:right;">Total Kg</td><td id="total_y_closed" class="total">0</td><td></td></tr></tfoot></table> </div> <input type="hidden" name="sections_json" id="sections_json"> <div style="margin-top:12px;"><button type="submit" class="btn">SAVE</button></div> </form> </div> <script> const PRELOADED_DENIERS = <?= json_encode($deniers, JSON_UNESCAPED_UNICODE) ?>; const PRELOADED_COLORS = <?= json_encode($colors, JSON_UNESCAPED_UNICODE) ?>; function escapeHtml(s){ return (s===null||s===undefined)?'':String(s).replaceAll('&','&').replaceAll('<','<').replaceAll('>','>'); } function renumber(tbody){ Array.from(tbody.querySelectorAll('tr')).forEach((tr,i)=> tr.children[0].textContent = i+1); } /* computeRow: use direct weight input (item_direct_weight) or box weight for closed boxes */ function computeRow(tr, type){ const wcell = tr.querySelector('.item_weight'); if (!wcell) return; const direct = tr.querySelector('.item_direct_weight'); if (direct) { const v = parseFloat(direct.value || 0); wcell.textContent = isNaN(v) ? '0' : v.toFixed(3); recalcTotals(); return; } // closed box fallback uses item_box_weight if (type === 'm_closed' || type === 'y_closed') { const boxw = parseFloat(tr.querySelector('.item_box_weight')?.value || 0); wcell.textContent = boxw > 0 ? boxw.toFixed(3) : '0'; recalcTotals(); return; } wcell.textContent = '0'; recalcTotals(); } /* recalc totals */ function recalcTotals(){ function sum(sel){ let s=0; document.querySelectorAll(sel).forEach(el=>{ const v=parseFloat(el.textContent||0); if(!isNaN(v)) s+=v; }); return s.toFixed(3); } document.getElementById('total_zk_in').textContent = sum('#tbl_zk_in .item_weight'); document.getElementById('total_zk_out').textContent = sum('#tbl_zk_out .item_weight'); document.getElementById('total_m_in').textContent = sum('#tbl_m_in .item_weight'); document.getElementById('total_m_open').textContent = sum('#tbl_m_open .item_weight'); document.getElementById('total_m_closed').textContent = sum('#tbl_m_closed .item_weight'); document.getElementById('total_winding').textContent = sum('#tbl_winding .item_weight'); document.getElementById('total_y_zari').textContent = sum('#tbl_y_zari .item_weight'); document.getElementById('total_y_open').textContent = sum('#tbl_y_open .item_weight'); document.getElementById('total_y_closed').textContent = sum('#tbl_y_closed .item_weight'); } /* addRow helper */ function addRow(tid, colsHtml, type){ const tbody = document.querySelector('#'+tid+' tbody'); const tr = document.createElement('tr'); tr.innerHTML = '<td></td>' + colsHtml + '<td><button type="button" class="remove-row small-btn">X</button></td>'; tbody.appendChild(tr); renumber(tbody); tr.querySelectorAll('input,select').forEach(el=>{ el.addEventListener('input', ()=> computeRow(tr, type)); el.addEventListener('change', ()=> computeRow(tr, type)); }); tr.querySelector('.remove-row').addEventListener('click', ()=> { tr.remove(); renumber(tbody); recalcTotals(); }); computeRow(tr, type); return tr; } /* HTML helpers */ function denierSelectHtml(){ let s = '<select class="form-control item_denier"><option value=""></option>'; PRELOADED_DENIERS.forEach(d => s += '<option>'+escapeHtml(d)+'</option>'); s += '</select>'; return s; } function colorSelectHtml(){ let s = '<select class="form-control item_color"><option value=""></option>'; PRELOADED_COLORS.forEach(c=> s += '<option>'+escapeHtml(c)+'</option>'); s += '</select>'; return s; } /* add-row wiring (use direct weight input) */ document.getElementById('add_zk_in').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_zk_in', cols, 'zk_in'); }); document.getElementById('add_zk_out').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_zk_out', cols, 'zk_out'); }); document.getElementById('add_m_in').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_m_in', cols, 'm_in'); }); document.getElementById('add_m_open').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_m_open', cols, 'm_open'); }); document.getElementById('add_m_closed').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input class="form-control item_box" /></td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_m_closed', cols, 'm_closed'); }); document.getElementById('add_winding').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_winding', cols, 'winding'); }); document.getElementById('add_y_zari').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_y_zari', cols, 'y_zari'); }); document.getElementById('add_y_open').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_y_open', cols, 'y_open'); }); document.getElementById('add_y_closed').addEventListener('click', function(e){ e.preventDefault(); const cols = [ '<td>'+denierSelectHtml()+'</td>', '<td>'+colorSelectHtml()+'</td>', '<td><input class="form-control item_box" /></td>', '<td><input type="number" step="0.001" class="form-control item_direct_weight" value="0" min="0"></td>', '<td class="item_weight">0</td>' ].join(''); addRow('tbl_y_closed', cols, 'y_closed'); }); /* add-lookup delegate (denier/color) - with preventDefault & stopPropagation to avoid accidental submit */ document.body.addEventListener('click', function(e){ if (e.target.classList.contains('denier-add')) { e.preventDefault(); e.stopPropagation(); const val = prompt('Enter new denier (e.g. 110 Lichi)'); if (!val) return; if (!PRELOADED_DENIERS.includes(val)) PRELOADED_DENIERS.push(val); document.querySelectorAll('.item_denier').forEach(s=>{ const exists = Array.from(s.options).some(o=>o.value.trim().toLowerCase()===val.trim().toLowerCase()); if (!exists) { const o = document.createElement('option'); o.value = val; o.text = val; s.appendChild(o); } }); const fd = new FormData(); fd.append('action','add_lookup'); fd.append('type','denier'); fd.append('value',val); fetch('',{ method:'POST', body: fd }).then(r=>r.json()).then(j=>{ if(!j.success) console.warn('denier save failed', j); }).catch(()=>{}); } if (e.target.classList.contains('color-add')) { e.preventDefault(); e.stopPropagation(); const val = prompt('Enter new color (e.g. Gold)'); if (!val) return; if (!PRELOADED_COLORS.includes(val)) PRELOADED_COLORS.push(val); document.querySelectorAll('.item_color').forEach(s=>{ const exists = Array.from(s.options).some(o=>o.value.trim().toLowerCase()===val.trim().toLowerCase()); if (!exists) { const o = document.createElement('option'); o.value = val; o.text = val; s.appendChild(o); } }); const fd = new FormData(); fd.append('action','add_lookup'); fd.append('type','color'); fd.append('value',val); fetch('',{ method:'POST', body: fd }).then(r=>r.json()).then(j=>{ if(!j.success) console.warn('color save failed', j); }).catch(()=>{}); } }); /* Prevent native form submit via Enter when focus is inside any of our data tables */ document.getElementById('mainForm').addEventListener('keydown', function(ev){ if (ev.key !== 'Enter') return; const t = ev.target; if (!t) return; if (t.tagName === 'BUTTON' || t.type === 'submit') return; if (t.tagName === 'TEXTAREA') return; if (t.closest('table')) { ev.preventDefault(); ev.stopPropagation(); // let existing Enter navigation handle focus/new-row } }); /* Enter-key navigation and auto-add row */ document.addEventListener('keydown', function(e){ if (e.key !== 'Enter') return; const el = e.target; if (!el) return; if (!el.closest('table')) return; // We already prevented native submit at form level; continue with navigation e.preventDefault(); const row = el.closest('tr'); const inputs = Array.from(row.querySelectorAll('input, select')); const idx = inputs.indexOf(el); if (idx < 0) return; if (idx < inputs.length - 1) { inputs[idx+1].focus(); return; } const tbody = row.parentElement; const nextRow = row.nextElementSibling; if (nextRow) { const first = nextRow.querySelector('input,select'); if (first) first.focus(); return; } const tid = tbody.closest('table').id; if (tid === 'tbl_zk_in') document.getElementById('add_zk_in').click(); if (tid === 'tbl_zk_out') document.getElementById('add_zk_out').click(); if (tid === 'tbl_m_in') document.getElementById('add_m_in').click(); if (tid === 'tbl_m_open') document.getElementById('add_m_open').click(); if (tid === 'tbl_m_closed') document.getElementById('add_m_closed').click(); if (tid === 'tbl_winding') document.getElementById('add_winding').click(); if (tid === 'tbl_y_zari') document.getElementById('add_y_zari').click(); if (tid === 'tbl_y_open') document.getElementById('add_y_open').click(); if (tid === 'tbl_y_closed') document.getElementById('add_y_closed').click(); setTimeout(()=> { const newRow = tbody.lastElementChild; const first = newRow.querySelector('input,select'); if (first) first.focus(); }, 80); }); /* Save: collect direct weights and other fields into sections_json */ document.getElementById('mainForm').addEventListener('submit', function(e){ function collect(tblId, mapping){ const out = []; document.querySelectorAll('#'+tblId+' tbody tr').forEach(tr=>{ const obj = {}; mapping.forEach(m=>{ if (m === 'weight') { obj[m] = parseFloat(tr.querySelector('.item_weight')?.textContent || 0); return; } if (m === 'direct_weight') { obj['direct_weight'] = parseFloat(tr.querySelector('.item_direct_weight')?.value || 0); return; } const el = tr.querySelector('.item_' + m); obj[m] = el ? el.value : ''; }); out.push(obj); }); return out; } const data = { zari_kasab_in: collect('tbl_zk_in', ['denier','color','direct_weight','weight']), zari_kasab_out: collect('tbl_zk_out', ['denier','color','direct_weight','weight']), metalic_in_machine: collect('tbl_m_in', ['denier','color','direct_weight','weight']), metalic_open_box: collect('tbl_m_open', ['denier','color','direct_weight','weight']), metalic_closed_box: collect('tbl_m_closed', ['denier','color','box','direct_weight','weight']), winding: collect('tbl_winding', ['denier','color','direct_weight','weight']), yarn_zari: collect('tbl_y_zari', ['denier','color','direct_weight','weight']), yarn_open: collect('tbl_y_open', ['denier','color','direct_weight','weight']), yarn_closed: collect('tbl_y_closed', ['denier','color','box','direct_weight','weight']) }; document.getElementById('sections_json').value = JSON.stringify(data); // allow normal submit }); /* initialize one row in each table */ ['add_zk_in','add_zk_out','add_m_in','add_m_open','add_m_closed','add_winding','add_y_zari','add_y_open','add_y_closed'].forEach(id=>{ try { document.getElementById(id).click(); } catch(e) {} }); </script> </body> </html>