familytree

A self-hosted family tree builder.
Log | Files | Refs | README

commit 9272e3917019c24464776878c720a8107cd687fc
parent e88bfa7864ba208f2939e6b2bc9ddea7bec43def
Author: Julian Piribauer <julian.piribauer@gmail.com>
Date:   Sat,  9 May 2026 18:36:18 +0000

PDF: open as blob URL (no print dialog); fix connector proportions; 🌳 tab icon

- Replace window.print() with Blob URL opened in new tab — no print dialog
- dropY now 35% of the way between box bottom and nearest child, scales with GY
- Drop line starts from midY+5 so it visually connects to the partnership dot
- Add 🌳 emoji to browser tab title

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Diffstat:
Mstatic/app.js | 19++++++++++---------
Mstatic/index.html | 2+-
2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/static/app.js b/static/app.js @@ -640,14 +640,16 @@ function drawPrintEdges(g, pos, { partnerships, parentLinks }, NW, NH) { const children = parentLinks.filter(pl => pl.partnership_id === ps.id).map(pl => pl.child_id); if (children.length) { - const dropY = p1.y + NH + 30; const childXs = children.map(cid => pos[cid]?.x ?? mx); + const childYs = children.map(cid => pos[cid]?.y).filter(y => y !== undefined); + const nearestChildY = childYs.length ? Math.min(...childYs) : p1.y + NH * 2; + const dropY = p1.y + NH + Math.round((nearestChildY - p1.y - NH) * 0.35); if (children.length === 1 && Math.abs(childXs[0] - mx) > 1) { const cp = pos[children[0]]; if (cp) lineAttr(edgeG.append('path')) - .attr('d', `M${mx},${p1.y + NH} C${mx},${dropY + 60} ${cp.x},${cp.y - 60} ${cp.x},${cp.y}`); + .attr('d', `M${mx},${midY + 5} C${mx},${dropY + 50} ${cp.x},${cp.y - 50} ${cp.x},${cp.y}`); } else { - lineAttr(edgeG.append('line')).attr('x1', mx).attr('y1', p1.y + NH).attr('x2', mx).attr('y2', dropY); + lineAttr(edgeG.append('line')).attr('x1', mx).attr('y1', midY + 5).attr('x2', mx).attr('y2', dropY); if (children.length > 1) { lineAttr(edgeG.append('line')) .attr('x1', Math.min(mx, ...childXs)).attr('y1', dropY) @@ -773,12 +775,11 @@ function downloadPDF() { </body> </html>`; - const win = window.open('', '_blank'); - if (!win) { showError('Popup blocked — allow popups for this site.'); return; } - win.document.write(html); - win.document.close(); - win.focus(); - setTimeout(() => win.print(), 600); + const blob = new Blob([html], { type: 'text/html;charset=utf-8' }); + const url = URL.createObjectURL(blob); + const tab = window.open(url, '_blank'); + if (!tab) showError('Popup blocked — allow popups for this site.'); + setTimeout(() => URL.revokeObjectURL(url), 30000); } /* ── Detail panel ── */ diff --git a/static/index.html b/static/index.html @@ -7,7 +7,7 @@ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=EB+Garamond:ital,wght@0,400;0,600;1,400&display=swap" rel="stylesheet"> <link rel="stylesheet" href="/static/style.css"> - <title>Family Tree</title> + <title>🌳 Family Tree</title> </head> <body>