/* מחשבון מעשר · tovtorah.org הערות בסגנון בלוק בלבד. הערת שורה תישבר כשוורדפרס מכווץ את הסקריפט לשורה אחת. */ (function(){ var W = document.getElementById('ttmWrap'); if(!W || W.getAttribute('data-ttm-ready') === '1'){ return; } W.setAttribute('data-ttm-ready','1'); var LS_KEY = 'tt_maaser_ledger_v1'; var DONATE_BASE = '/donate/'; /* חלוקת היתרה בין תחומי הסיוע. חמשת התחומים הם אלה שהאתר מפרסם ב-/donate/ וב-/transparency/, ותו לא. בחירת תחום מותרת ומוצהרת באתר; בחירת אדם מזוהה אינה קיימת כאן ולא תהיה. */ var SPLIT_SRC = 'calc-split'; var splitLeft = 0; var basisTouched = false; /* הופעל 2026-08-06: נבחרה עמותה 580770147 עם ניהול תקין וסעיף 46 בתוקף. */ var DONATE_ENABLED = true; var state = { rate:0.10, mode:'salary', basis:'net', src:'bonus', amount:0, base:0 }; /* ---------- עזרי מספרים ---------- */ function num(id){ var el = document.getElementById(id); if(!el){ return 0; } var v = String(el.value || '').replace(/[^0-9.\-]/g,''); var n = parseFloat(v); if(isNaN(n) || n < 0){ return 0; } return n; } function ils(n){ var r = Math.round(n || 0); return '₪' + r.toLocaleString('en-US'); } function today(){ var d = new Date(); var p = function(x){ return (x < 10 ? '0' : '') + x; }; return p(d.getDate()) + '/' + p(d.getMonth()+1) + '/' + d.getFullYear(); } /* ---------- בורר צ'יפים ---------- */ function wireChips(containerId, attr, onPick){ var box = document.getElementById(containerId); if(!box){ return; } box.addEventListener('click', function(e){ var btn = e.target.closest('.ttm-chip'); if(!btn || !box.contains(btn)){ return; } var all = box.querySelectorAll('.ttm-chip'); for(var i=0;i' + ils(lines[i][1]) + ''; } html += '
  • הבסיס לחישוב' + ils(base) + '
  • '; html += '
  • ' + (state.rate === 0.20 ? 'חומש, חמישית' : 'מעשר, עשירית') + '' + Math.round(state.rate*100) + '%
  • '; ul.innerHTML = html; } var out = document.getElementById('ttmOut'); if(out){ out.textContent = ils(amount); } var lbl = document.getElementById('ttmResultLabel'); if(lbl){ lbl.textContent = state.rate === 0.20 ? 'החומש להפרשה' : 'המעשר להפרשה'; } var a = document.getElementById('ttmDonate'); if(a){ var r = Math.round(amount); a.setAttribute('data-amount', String(r)); if(DONATE_ENABLED){ a.setAttribute('href', DONATE_BASE + (r > 0 ? '?amount=' + r + '&purpose=maaser&src=calc' : '?purpose=maaser&src=calc')); } else { a.hidden = true; } } var bn2 = document.getElementById('ttmBasisNote'); if(bn2){ var hint = ''; if(state.mode === 'salary'){ if(Math.round(amount) === 0){ var gg = num('ttmSalGross'), nn = num('ttmSalNet'); if(state.basis === 'gross'){ if(gg === 0){ if(nn > 0){ hint = ' בחרתם להפריש מהברוטו, ולכן צריך למלא את שכר הברוטו.'; } } } else { if(nn === 0){ if(gg > 0){ hint = ' בחרתם להפריש מהנטו, ולכן צריך למלא את שכר הנטו. אפשר גם לבחור "מהברוטו".'; } } } } } bn2.textContent = (BASIS_NOTE[state.basis] || '') + hint; } var sv = document.getElementById('ttmSave'); if(sv){ sv.disabled = (Math.round(amount) <= 0); } } /* ---------- יתרה ---------- */ function load(){ try{ var raw = window.localStorage.getItem(LS_KEY); if(!raw){ return []; } var arr = JSON.parse(raw); return Object.prototype.toString.call(arr) === '[object Array]' ? arr : []; }catch(e){ return []; } } function save(rows){ try{ window.localStorage.setItem(LS_KEY, JSON.stringify(rows)); }catch(e){} } function modeLabel(){ if(state.mode === 'salary'){ return 'משכורת'; } if(state.mode === 'business'){ return 'עצמאי או עסק'; } var m = { bonus:'בונוס או מענק', gift:'מתנה', inherit:'ירושה', win:'זכייה', sale:'מכירת נכס' }; return m[state.src] || 'הכנסה חד פעמית'; } function render(){ var rows = load(); var ledger = document.getElementById('ttmLedger'); var tbody = document.getElementById('ttmRows'); if(!ledger || !tbody){ return; } ledger.hidden = (rows.length === 0); var owed = 0, paid = 0, html = ''; for(var i=0;i' + (r.date || '') + '' + '' + String(r.label || '').replace(/' + '' + (r.owed ? ils(r.owed) : '') + '' + '' + (r.paid ? ils(r.paid) : '') + '' + '' + ''; } if(!html){ html = 'אין רשומות עדיין'; } tbody.innerHTML = html; var left = owed - paid; if(left < 0){ left = 0; } var a = document.getElementById('ttmTotOwed'); var b = document.getElementById('ttmTotPaid'); var c = document.getElementById('ttmTotLeft'); if(a){ a.textContent = ils(owed); } if(b){ b.textContent = ils(paid); } if(c){ c.textContent = ils(left); } splitLeft = left; paintSplit(); } /* ---------- בסיס ההפרשה עוקב אחרי מה שמילאו ---------- */ /* הבעיה: ברירת המחדל היא "מהנטו", והשדה הראשון בטופס הוא "שכר ברוטו". מי שמילא את השדה הראשון בלבד ראה ₪0 והסיק שהמחשבון שבור. הפתרון: הבסיס עוקב אחרי השדה שמולא בפועל, והצ'יפ זז מול העיניים — עד לרגע שבו המשתמש בוחר בסיס בעצמו, ומאז הבחירה שלו קובעת. */ function setBasisUI(v){ var box = document.getElementById('ttmBasis'); if(!box){ return; } var all = box.querySelectorAll('.ttm-chip'), i, on; for(i=0;i 0){ setBasisUI('net'); return; } if(g > 0){ setBasisUI('gross'); } } /* ---------- חלוקת היתרה ---------- */ /* סכום בתוך משפט עברי חייב bdi מבודד, אחרת ה-₪ נודד לצד השני של המספר. ils() לבדו מחזיר טקסט, ולכן הוא בטוח ל-innerHTML. */ function amt(n){ return '' + ils(n) + ''; } function splitInputs(){ return W.querySelectorAll('.ttm-cause-in'); } function splitLines(){ var a = splitInputs(), out = [], i, v; for(i=0;i 0)){ box.hidden = true; return; } box.hidden = false; var lines = splitLines(), tot = 0, i; for(i=0;i splitLeft){ note.innerHTML = 'שיבצתם ' + amt(tot - splitLeft) + ' מעבר ליתרה. גם זה בסדר גמור.'; } else { note.textContent = 'כל היתרה משובצת.'; } } var go = document.getElementById('ttmSplitGo'); if(go){ if(tot > 0){ go.innerHTML = 'לתרום ' + amt(tot); go.setAttribute('href', splitHref(tot, lines)); } else { go.innerHTML = 'לתרום את היתרה, ' + amt(splitLeft); go.setAttribute('href', splitHref(splitLeft, [])); } } } function splitEven(){ var a = splitInputs(), n = a.length, i; if(!(splitLeft > 0)){ return; } if(n === 0){ return; } var each = Math.floor(splitLeft / n); var rest = splitLeft - (each * n); for(i=0;i= 0 && idx < rows.length){ rows.splice(idx,1); save(rows); render(); } }); } var clearBtn = document.getElementById('ttmClear'); if(clearBtn){ clearBtn.addEventListener('click', function(){ if(!window.confirm('לאפס את כל רשומות היתרה? הפעולה אינה הפיכה.')){ return; } save([]); render(); }); } var expBtn = document.getElementById('ttmExport'); if(expBtn){ expBtn.addEventListener('click', function(){ var rows = load(); var csv = 'תאריך,פירוט,הפרשה,ניתן\n'; for(var i=0;i