diff --git a/crates/pdftract-cli/src/inspect/frontend/app.js b/crates/pdftract-cli/src/inspect/frontend/app.js index e28b8a4..51b817f 100644 --- a/crates/pdftract-cli/src/inspect/frontend/app.js +++ b/crates/pdftract-cli/src/inspect/frontend/app.js @@ -354,29 +354,67 @@ function loadFragment(){ function setupTooltips(svg){ const tooltip=document.getElementById('tooltip'); + const OFFSET=8; + svg.addEventListener('mouseover',e=>{ const target=e.target.closest('[data-text], [data-kind]'); if(!target)return; let content=''; if(target.dataset.spanIndex!==undefined){ - content=`Text: ${target.dataset.text}\nFont: ${target.dataset.font}\nSize: ${target.dataset.size}pt\nConfidence: ${target.dataset.confidence||'N/A'}\nSpan index: ${target.dataset.spanIndex}` + const lines=[]; + if(target.dataset.text)lines.push(`Text: ${target.dataset.text}`); + if(target.dataset.font){ + const size=target.dataset.size?` ${target.dataset.size}pt`:''; + lines.push(`Font: ${target.dataset.font}${size}`); + } + if(target.dataset.confidence&&target.dataset.confidence!==''){ + lines.push(`Confidence: ${target.dataset.confidence}`); + } + if(target.dataset.bbox)lines.push(`Bbox: ${target.dataset.bbox}`); + if(target.dataset.blockRef)lines.push(`Block: ${target.dataset.blockRef}`); + if(target.dataset.mcid)lines.push(`MCID: ${target.dataset.mcid}`); + if(target.dataset.readingIdx)lines.push(`Reading idx: ${target.dataset.readingIdx}`); + content=lines.join('\n'); }else if(target.dataset.blockIndex!==undefined){ content=`Block index: ${target.dataset.blockIndex}\nKind: ${target.dataset.kind}\nText: ${target.dataset.text}\nLevel: ${target.dataset.level||'N/A'}\nTable index: ${target.dataset.tableIndex||'N/A'}` } - tooltip.hidden=false; - tooltip.textContent=content; - tooltip.style.left=e.pageX+10+'px'; - tooltip.style.top=e.pageY+10+'px' + if(content){ + tooltip.textContent=content; + tooltip.hidden=false; + positionTooltip(e.pageX,e.pageY); + } }); + svg.addEventListener('mouseout',e=>{ if(e.target.closest('[data-text], [data-kind]'))tooltip.hidden=true }); + svg.addEventListener('mousemove',e=>{ - if(!tooltip.hidden){ - tooltip.style.left=e.pageX+10+'px'; - tooltip.style.top=e.pageY+10+'px' + if(!tooltip.hidden)positionTooltip(e.pageX,e.pageY) + }); + + function positionTooltip(x,y){ + const tooltipRect=tooltip.getBoundingClientRect(); + const viewportWidth=window.innerWidth; + const viewportHeight=window.innerHeight; + + let left=x+OFFSET; + let top=y+OFFSET; + + if(left+tooltipRect.width>viewportWidth){ + left=x-tooltipRect.width-OFFSET; } - }) + + if(top+tooltipRect.height>viewportHeight){ + top=y-tooltipRect.height-OFFSET; + } + + left=Math.max(OFFSET,Math.min(left,viewportWidth-tooltipRect.width-OFFSET)); + top=Math.max(OFFSET,Math.min(top,viewportHeight-tooltipRect.height-OFFSET)); + + tooltip.style.left=left+'px'; + tooltip.style.top=top+'px' + } } document.addEventListener('DOMContentLoaded',init); diff --git a/crates/pdftract-cli/src/inspect/frontend/style.css b/crates/pdftract-cli/src/inspect/frontend/style.css index eab11a6..58357d8 100644 --- a/crates/pdftract-cli/src/inspect/frontend/style.css +++ b/crates/pdftract-cli/src/inspect/frontend/style.css @@ -27,7 +27,7 @@ body{font-family:system-ui,-apple-system,sans-serif;font-size:14px;line-height:1 .panel-header{padding:12px;border-bottom:1px solid #ddd;font-weight:600;background:#f9f9f9} .json-tree{flex:1;overflow:auto;padding:12px;font-size:12px;font-family:ui-monospace,monospace;white-space:pre-wrap;word-break:break-all} .loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:16px;color:#666} -.tooltip{position:absolute;background:#333;color:#fff;padding:6px 10px;border-radius:4px;font-size:12px;pointer-events:none;z-index:1000;max-width:300px;white-space:pre-wrap;word-break:break-word} +.tooltip{position:absolute;background:rgba(255,255,255,.95);border:1px solid #ccc;padding:6px 10px;font-family:ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,monospace;font-size:12px;pointer-events:none;z-index:1000;max-width:400px;white-space:pre;line-height:1.4} .layer-spans,.layer-blocks,.layer-columns,.layer-reading-order,.layer-confidence-heatmap,.layer-ocr,.layer-mcid,.layer-anchors,.layer-diff{display:none} html[data-layers~="spans"] .layer-spans,html[data-layers~="blocks"] .layer-blocks,html[data-layers~="columns"] .layer-columns,html[data-layers~="reading-order"] .layer-reading-order,html[data-layers~="confidence-heatmap"] .layer-confidence-heatmap,html[data-layers~="ocr"] .layer-ocr,html[data-layers~="mcid"] .layer-mcid,html[data-layers~="anchors"] .layer-anchors,html[data-layers~="diff"] .layer-diff{display:block} .tooltip-key{color:#8f8}