| <!doctype html> |
| <title>Navigating to a text fragment anchor</title> |
| <script> |
| function isInView(element) { |
| let rect = element.getBoundingClientRect(); |
| return rect.top >= 0 && rect.top <= window.innerHeight; |
| } |
| |
| function checkScroll() { |
| let bc = new BroadcastChannel('scroll-to-text-fragment'); |
| |
| let position = 'unknown'; |
| if (window.scrollY == 0) |
| position = 'top'; |
| else if (isInView(document.getElementById('element'))) |
| position = 'element'; |
| else if (isInView(document.getElementById('text'))) |
| position = 'text'; |
| else if (isInView(document.getElementById('more-text'))) |
| position = 'more-text'; |
| else if (isInView(document.getElementById('cross-node-context'))) |
| position = 'cross-node-context'; |
| else if (isInView(document.getElementById('text-directive-parameters'))) |
| position = 'text-directive-parameters'; |
| |
| bc.postMessage({ scrollPosition: position, href: window.location.href }); |
| bc.close(); |
| window.close(); |
| } |
| </script> |
| <style> |
| body { |
| height: 6200px; |
| } |
| #element { |
| position: absolute; |
| top: 2000px; |
| } |
| #text { |
| position: absolute; |
| top: 3000px; |
| } |
| #more-text { |
| position: absolute; |
| top: 4000px; |
| } |
| #cross-node-context { |
| position: absolute; |
| top: 5000px; |
| } |
| #text-directive-parameters { |
| position: absolute; |
| top: 6000px; |
| } |
| </style> |
| <body onload="window.requestAnimationFrame(checkScroll)"> |
| <div id="element">Element</div> |
| <p id="text">This is a test page !$'()*+./:;=?@_~ &,- ♥</p> |
| <p id="more-text">More test page text</p> |
| <div id="cross-node-context"> |
| <div> |
| <p>prefix</p> |
| <p>test page</p> |
| </div> |
| <div><p>suffix</p></div> |
| </div> |
| <p id="text-directive-parameters">this,is,test,page</p> |
| </body> |