L&R Photo Analysis

No form selected

'); w.document.close(); }catch(e){} // v255 PDF-only reliability: pricing enrichment must never leave the already-open // Safari print tab parked on the placeholder. Give enrichment a bounded window, // then render the current completed results exactly as they exist. await Promise.race([ Promise.allSettled(patientTargets.map(t=>Promise.resolve().then(()=>ensureAllPricing(t)))), new Promise(resolve=>setTimeout(resolve,3000)) ]); const c=document.createElement('div'); c.className='patient-export'; patientTargets.forEach(t=>c.appendChild(t.cloneNode(true))); resolvePhotoHeadNeckFinalState(c); await Promise.race([Promise.resolve().then(()=>ensureHeadNeckPhotoExportPricing(c)),new Promise(resolve=>setTimeout(resolve,3000))]).catch(()=>{}); // v320 PRINT/PDF: enrich Fusion OTS-trial cards with the same inline billing used by Copy Results. await Promise.race([ Promise.resolve().then(()=>ensureFusionTrialInlinePricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); await Promise.race([ Promise.resolve().then(()=>ensureMcpExportPricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); await Promise.race([ Promise.resolve().then(()=>ensureWristExportPricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); await Promise.race([ Promise.resolve().then(()=>ensureGloveExportPricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); await Promise.race([ Promise.resolve().then(()=>ensureBraExportPricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); await Promise.race([ Promise.resolve().then(()=>ensureKneeToThighExportPricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); // ReadyWrap Toe Photo: mirror the locked Manual Entry selected-color final state. cleanPhotoRwToeSelectedColor(c); resolvePhotoRwToeFinalState(c); cleanPhotoRwToeSelectedColor(c); // ReadyWrap Toe Photo PRINT/PDF ONLY: place the side label inside the final // colored result card, at its top-left, matching the locked Manual Entry print layout. c.querySelectorAll('[data-photo-rwtoe-side],[data-photo-rwtoe-trial-color-group]').forEach(group=>{ const heading=group.querySelector(':scope > .fusion-screen-side-heading'); const card=group.querySelector(':scope > .refblock'); if(!heading||!card)return; const side=String(heading.textContent||'').trim().toUpperCase(); if(!/^(LEFT|RIGHT)$/.test(side))return; const h=document.createElement('div'); h.className='rwtoe-print-side-heading'; h.textContent=side; card.insertBefore(h,card.firstChild); heading.remove(); }); // EXO Toe Cap Photo PRINT/PDF ONLY: use the exact ReadyWrap Toe final-card architecture. cleanPhotoExotoeSelectedColor(c); c.querySelectorAll('[data-photo-exotoe-side],.exotoe-trial-inline-group').forEach(group=>{ const heading=group.querySelector(':scope > .exotoe-screen-side-heading'); const card=group.querySelector(':scope > .refblock'); if(!heading||!card||!/Exo(?:Soft|Strong) Toe Cap/i.test(String(card.textContent||'')))return; const side=String(group.dataset.photoExotoeSide||heading.textContent||'').trim().toUpperCase(); if(!/^(LEFT|RIGHT)$/.test(side))return; card.querySelectorAll(':scope > .rwtoe-print-side-heading').forEach(n=>n.remove()); const h=document.createElement('div'); h.className='rwtoe-print-side-heading'; h.textContent=side; card.insertBefore(h,card.firstChild); heading.remove(); }); // Foot CT Photo: use the same final-state export sequence already proven by // Foot CT Manual/Copy — selected color becomes structural, then the completed // OTS Trial replaces the underlying Custom decision-support card. cleanPhotoFootctSelectedColor(c); resolvePhotoFootctFinalState(c); // v325 PRINT/PDF ONLY: make the selected Photo Analysis Fusion color structural // before final-state cleanup hoists the authoritative trial cards out of their // color-selection container. This is the same proven selected-color cleanup used by Copy Results. cleanPhotoThighSelectedColor(c); resolvePhotoThighFinalState(c); movePhotoReadyWrapSideInsideFinalCard(c,{groupSelector:'[data-photo-thigh-side],[data-photo-thigh-trial-color-group]',dataKey:'photoThighSide',productName:'ReadyWrap Thigh'}); cleanPhotoExobkSelectedColor(c); resolvePhotoExobkFinalState(c); cleanPhotoExobkSelectedColor(c); cleanPhotoExothighSelectedColor(c); resolvePhotoExothighFinalState(c); cleanPhotoExothighSelectedColor(c); // ExoStrong Thigh High PHOTO PRINT/PDF ONLY: mirror the proven Below Knee final-card structure. // Remove any legacy side prefix already fused into the product name, then place one standalone side heading. c.querySelectorAll('[data-photo-exothigh-side],[data-photo-exothigh-trial-color-group]').forEach(group=>{ const heading=group.querySelector(':scope > .fusion-screen-side-heading'); const card=group.querySelector(':scope > .refblock'); if(!card||!/ExoStrong Thigh High/i.test(String(card.textContent||'')))return; const side=String(group.dataset.photoExothighSide||heading?.textContent||'').trim().toUpperCase(); if(!/^(LEFT|RIGHT)$/.test(side))return; const name=card.querySelector('.result-product-name'); if(name)name.textContent=String(name.textContent||'').replace(/^(LEFT|RIGHT)\s*[—-]?\s*/i,'').trim(); card.querySelectorAll(':scope > .exothigh-print-side-heading').forEach(n=>n.remove()); const h=document.createElement('div'); h.className='exothigh-print-side-heading'; h.textContent=side; h.style.fontWeight='900';h.style.fontSize='20px';h.style.lineHeight='1.2';h.style.margin='0 0 10px';h.style.display='block'; card.insertBefore(h,card.firstChild); if(heading)heading.remove(); }); cleanPhotoArmSelectedColor(c); cleanPhotoExotoeSelectedColor(c); resolvePhotoArmFinalState(c); cleanPhotoArmSelectedColor(c); preparePhotoArmExportSideLabels(c); cleanPhotoExotoeSelectedColor(c); resolvePhotoMcpFinalState(c); cleanPhotoMcpFinalExport(c); resolvePhotoWristFinalState(c); cleanPhotoWristFinalExport(c); // v447 Glove uses the same final-state export sequence as Wrist/MCP. resolvePhotoGloveFinalState(c); // v452 Bra mirrors the locked Glove final-state PRINT/PDF architecture: // once an OTS Trial REF exists, hoist only the completed generated result // and remove the underlying Custom/comparison workflow from the export. resolvePhotoBraFinalState(c); await Promise.race([ Promise.resolve().then(()=>ensureAllPricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); await Promise.race([ Promise.resolve().then(()=>ensureGloveExportPricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); await Promise.race([ Promise.resolve().then(()=>ensureBraExportPricing(c)), new Promise(resolve=>setTimeout(resolve,3000)) ]).catch(()=>{}); await Promise.race([Promise.resolve().then(()=>refreshFullLegPhotoPricing(c)),new Promise(resolve=>setTimeout(resolve,3000))]).catch(()=>{}); cleanPhotoGloveFinalExport(c); preparePhotoGloveExportSideLabels(c); cleanPhotoBraFinalExport(c); resolvePhotoBelowKneeFinalState(c); cleanPhotoBelowKneeFinalExport(c); cleanPhotoFusionSelectedColor(c); resolvePhotoFusionFinalState(c); cleanPhotoFusionFinalExport(c); preparePhotoCalfExportSideLabels(c); resolvePhotoCalfFinalState(c); cleanPhotoCalfFinalExport(c); preparePhotoFullLegExportSideLabels(c); resolvePhotoFullLegFinalState(c); cleanPhotoFullLegFinalExport(c); resolvePhotoKneeToThighFinalState(c); cleanPhotoKneeToThighFinalExport(c); cleanPhotoGauntletSelectedColor(c); resolvePhotoGauntletFinalState(c); cleanPhotoGauntletSelectedColor(c); cleanPhotoFusionSelectedColor(c); cleanKneeTrialExport(c); resolveKneeFinalState(c); // v522 PRINT/PDF ONLY — migrate the proven Fusion Photo Analysis side structure // into detached Manual Fusion final results. Side identity comes from the existing // data-fusion-choice-side carried by the authoritative result card; no sizing/REF data changes. c.querySelectorAll('.fusion-color-choice,[data-fusion-trial-color-choice]').forEach(n=>n.remove()); ['Left','Right'].forEach(side=>{ const sideUpper=side.toUpperCase(); const candidates=[...c.querySelectorAll('.refblock[data-fusion-choice-side="'+side+'"]')] .filter(card=>/ReadyWrap Fusion Kit/i.test(String(card.textContent||'')) && /REF\s*#?\s*\d{6}/i.test(String(card.textContent||''))); if(!candidates.length)return; candidates.forEach(card=>{ const name=card.querySelector('.result-product-name'); if(name && !/^(LEFT|RIGHT)\s*[—-]/i.test(String(name.textContent||'').trim())) name.textContent=sideUpper+' — '+String(name.textContent||'').trim(); }); const already=candidates[0].closest('.manual-fusion-side-group,.photo-fusion-side-group,.fusion-print-side-group,.fusion-trial-inline-group[data-fusion-side]'); if(already){ if(!already.querySelector(':scope > .fusion-screen-side-heading')){ const heading=document.createElement('div'); heading.className='fusion-screen-side-heading'; heading.textContent=sideUpper; already.insertBefore(heading,already.firstChild); } already.classList.add(side.toLowerCase()); return; } const wrap=document.createElement('div'); wrap.className='fusion-print-side-group '+side.toLowerCase(); wrap.setAttribute('data-fusion-side',sideUpper); const heading=document.createElement('div'); heading.className='fusion-screen-side-heading'; heading.textContent=sideUpper; wrap.appendChild(heading); candidates[0].before(wrap); candidates.forEach(card=>wrap.appendChild(card)); }); // v259 PRINT/PDF ONLY: refResultBlock() emits the primary Black REF as two sibling // .black-ref nodes ("Black —" + "REF 123456"). The print CSS makes every // .black-ref display:block, which splits only those primary cards across two lines. // Trial/right cards already emit one .black-ref node. Merge the split siblings in // the actual print clone before print CSS is applied so both structures are identical. c.querySelectorAll('.black-ref').forEach(label=>{ if(!/^Black\s*[—-]\s*$/i.test(String(label.textContent||'').trim())) return; const ref=label.nextElementSibling; if(!ref || !ref.classList.contains('black-ref') || !/^REF\s*#?\s*\d{6}(?:\s*\(pair\))?$/i.test(String(ref.textContent||'').trim())) return; const merged=document.createElement('strong'); merged.className='black-ref'; merged.textContent='Black — '+String(ref.textContent||'').trim(); label.replaceWith(merged); ref.remove(); }); // Print/PDF export: concise patient result layout. Keep a completed OTS Trial summary, not the comparison matrix. simplifyExportComparisons(c); c.querySelectorAll('.result-actions,.pricing-billing-btn,.fl-compare-btn,.fl-hide,button').forEach(n=>n.remove()); c.querySelectorAll('.pricing-billing-output').forEach(n=>n.style.display='block'); c.querySelectorAll('[hidden],.hidden').forEach(n=>n.remove()); // Export-only parity: use the same complete side card for Photo Analysis and Manual Entry. const printBlocks=[...c.querySelectorAll('.refblock,.manual-component')]; printBlocks.forEach(block=>{ const t=String(block.textContent||'').trim(); const isRight=/^RIGHT\b/i.test(t)||block.classList.contains('right'); const isLeft=/^LEFT\b/i.test(t)||block.classList.contains('left'); block.classList.toggle('export-right',isRight); block.classList.toggle('export-left',!isRight&&isLeft); block.innerHTML=block.innerHTML.replace(/\b(Beige)(\s*[—-]\s*REF\s*#?\s*\d{6})/gi,'$1$2'); }); const css=`body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Arial,sans-serif;margin:18px;color:#111;background:#fff;font-size:15px}.patient-export,.result,.resultbox,#refStatus{max-width:760px;margin:auto}.refblock,.manual-component{break-inside:avoid;page-break-inside:avoid;margin:0 0 16px;padding:16px;border-radius:14px;background:#dfeaff;line-height:1.45}.refblock.right,.right,.export-right{background:#e0f2e4!important}.export-left{background:#dfeaff!important}.manual-fusion-side-group,.fusion-print-side-group,.fusion-trial-inline-group[data-photo-footct-trial-color-group],.fusion-trial-inline-group[data-photo-exobk-trial-color-group],.fusion-trial-inline-group[data-photo-exothigh-trial-color-group],.photo-fusion-side-group,.photo-arm-side-group,.arm-trial-inline-group,.photo-mcp-side-group,.mcp-trial-inline-group,.photo-wrist-side-group,.wrist-trial-inline-group,.photo-glove-side-group,.glove-trial-inline-group,.photo-bra-result-group,.bra-photo-trial-inline-group,.photo-gauntlet-side-group,.gauntlet-trial-inline-group,.bk-trial-inline-group,.photo-bk-side-group,.ktt-trial-inline-group,.photo-ktt-side-group,.manual-fusion-side-group{break-inside:avoid;page-break-inside:avoid;margin:0 0 16px;padding:16px;border-radius:14px;background:#dfeaff;line-height:1.45}.manual-fusion-side-group.right,.fusion-print-side-group.right,.fusion-trial-inline-group.right[data-photo-footct-trial-color-group],.fusion-trial-inline-group.right[data-photo-exobk-trial-color-group],.fusion-trial-inline-group.right[data-photo-exothigh-trial-color-group],.photo-fusion-side-group.right,.photo-arm-side-group.right,.arm-trial-inline-group.right,.photo-mcp-side-group.right,.mcp-trial-inline-group.right,.photo-wrist-side-group.right,.wrist-trial-inline-group.right,.photo-glove-side-group.right,.glove-trial-inline-group.right,.photo-gauntlet-side-group.right,.gauntlet-trial-inline-group.right,.bk-trial-inline-group.right,.photo-bk-side-group.right,.manual-fusion-side-group.right{background:#e0f2e4!important}.manual-fusion-side-group>.fusion-screen-side-heading,.fusion-print-side-group>.fusion-screen-side-heading,.fusion-trial-inline-group[data-photo-footct-trial-color-group]>.fusion-screen-side-heading,.fusion-trial-inline-group[data-photo-exobk-trial-color-group]>.fusion-screen-side-heading,.fusion-trial-inline-group[data-photo-exothigh-trial-color-group]>.fusion-screen-side-heading,.photo-fusion-side-group>.fusion-screen-side-heading,.photo-arm-side-group>.arm-screen-side-heading,.arm-trial-inline-group>.arm-screen-side-heading,.photo-mcp-side-group>.mcp-screen-side-heading,.mcp-trial-inline-group>.mcp-screen-side-heading,.photo-wrist-side-group>.mcp-screen-side-heading,.wrist-trial-inline-group>.mcp-screen-side-heading,.photo-glove-side-group>.mcp-screen-side-heading,.glove-trial-inline-group>.mcp-screen-side-heading,.photo-gauntlet-side-group>.gauntlet-screen-side-heading,.gauntlet-trial-inline-group>.gauntlet-screen-side-heading,.bk-trial-inline-group>.bk-screen-side-heading,.photo-bk-side-group>.bk-screen-side-heading,.ktt-trial-inline-group>.ktt-screen-side-heading,.photo-ktt-side-group>.ktt-screen-side-heading,.manual-fusion-side-group>.fusion-screen-side-heading{font-weight:900;font-size:20px;line-height:1.2;margin:0 0 10px}.manual-fusion-side-group>.refblock,.fusion-print-side-group>.refblock,.fusion-trial-inline-group[data-photo-footct-trial-color-group]>.refblock,.fusion-trial-inline-group[data-photo-exobk-trial-color-group]>.refblock,.fusion-trial-inline-group[data-photo-exothigh-trial-color-group]>.refblock,.photo-fusion-side-group>.refblock,.photo-arm-side-group>.refblock,.arm-trial-inline-group>.refblock,.photo-mcp-side-group>.refblock,.mcp-trial-inline-group>.refblock,.photo-wrist-side-group>.refblock,.wrist-trial-inline-group>.refblock,.photo-glove-side-group>.refblock,.glove-trial-inline-group>.refblock,.photo-bra-result-group>.refblock,.bra-photo-trial-inline-group>.refblock,.photo-gauntlet-side-group>.refblock,.gauntlet-trial-inline-group>.refblock,.bk-trial-inline-group>.refblock,.photo-bk-side-group>.refblock,.ktt-trial-inline-group>.refblock,.photo-ktt-side-group>.refblock,.manual-fusion-side-group>.refblock{background:transparent!important;border-radius:0!important;padding:8px 0 12px!important;margin:0!important}.manual-fusion-side-group>.refblock+.refblock,.fusion-print-side-group>.refblock+.refblock{border-top:1px solid rgba(80,100,130,.18);padding-top:14px!important;margin-top:2px!important}.export-left :is(h1,h2,h3,h4,.result-product-name,.side-title){color:#244a86}.export-right :is(h1,h2,h3,h4,.result-product-name,.side-title){color:#2d6b3a}.export-trial-summary{margin:10px 0 12px;padding:12px;border:1px solid #d8dee6;border-radius:10px;background:#fff;line-height:1.45;break-inside:avoid;page-break-inside:avoid}.export-beige,.beige-ref{display:block!important;color:#96652f!important;font-weight:800}.black-ref{display:block!important;color:#000!important;font-weight:800}.pricing-billing-wrap{border-top:1px solid #d8dee6;margin-top:12px;padding-top:10px}.pricing-billing-card{break-inside:avoid;margin-top:8px;padding:10px;border:1px solid #d8dee6;border-radius:8px;background:#f8fafc;line-height:1.4}.rwtoe-print-side-heading{font-weight:900;font-size:20px;line-height:1.2;margin:0 0 10px;color:#111!important}.result-product-name,strong{font-weight:800}@page{margin:.42in}`; const returnBar=''; const navCss='.print-return{max-width:760px;margin:0 auto 18px}.print-return button{width:auto;margin:0;padding:10px 14px;border:1px solid #aeb6c2;border-radius:9px;background:#fff;color:#111;font:700 15px -apple-system,BlinkMacSystemFont,\"Segoe UI\",Arial,sans-serif}@media print{.print-return{display:none!important}}'; w.document.open();w.document.write('L&R REF Generator Results'+returnBar+c.outerHTML+' ');w.document.close(); // Give Mobile Safari two paint frames after the final document replaces the // placeholder, then invoke print. This prevents the first print snapshot from // capturing the transient blank document while leaving export content unchanged. w.requestAnimationFrame(()=>w.requestAnimationFrame(()=>setTimeout(()=>{if(!w.closed){w.focus();w.print();}},150))); } function activePatientTargets(){ const all=[]; const manual=document.getElementById('refStatus'); if(manual && /REF\s*#?\s*\d{6}/i.test(String(manual.textContent||''))) all.push(manual); document.querySelectorAll('.result').forEach(el=>{ if(el.querySelector('.refblock') && /REF\s*#?\s*\d{6}/i.test(String(el.textContent||''))) all.push(el); }); return all.filter(el=>{ const card=el.closest('.card'); return !card || !card.classList.contains('hidden'); }); } function addPatientActions(){ const targets=activePatientTargets(); const last=targets[targets.length-1]; const rows=[...document.querySelectorAll('.result-actions.patient-actions')]; if(!last){ rows.forEach(r=>r.remove()); return; } if(rows.length===1 && rows[0].parentElement===last) return; rows.forEach(r=>r.remove()); const row=document.createElement('div');row.className='result-actions patient-actions'; const label=document.createElement('div');label.className='patient-actions-label';label.textContent='Patient Results'; const buttons=document.createElement('div');buttons.className='patient-actions-buttons'; const copy=document.createElement('button');copy.type='button';copy.className='result-action-btn';copy.textContent='Copy Results';copy.onclick=()=>copyText(last,copy); const pdf=document.createElement('button');pdf.type='button';pdf.className='result-action-btn secondary';pdf.textContent='Print / Save PDF';pdf.onclick=()=>printTarget(last); buttons.append(copy,pdf);row.append(label,buttons);last.appendChild(row); } function enhance(){ addPatientActions(); } const style=document.createElement('style');style.textContent=`.result-actions{margin:20px 0 4px;padding:18px 14px 4px;border-top:1px solid #d8dee6;text-align:center}.patient-actions-label{font-size:13px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;color:#6b7280;margin-bottom:11px}.patient-actions-buttons{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}.result-action-btn{width:auto!important;margin:0!important;padding:10px 14px!important;border-radius:9px!important;font-size:14px!important;font-weight:800!important;background:#2457a7!important;color:#fff!important;border:1px solid #2457a7!important}.result-action-btn.secondary{background:#fff!important;color:#111!important;border-color:#aeb6c2!important}.result-action-btn.copying{background:#8a8a8a!important;border-color:#8a8a8a!important;opacity:1!important}`;document.head.appendChild(style); let q=false;new MutationObserver(()=>{if(q)return;q=true;requestAnimationFrame(()=>{q=false;enhance()})}).observe(document.body,{childList:true,subtree:true,characterData:true});enhance(); })();