1/** 2 * News marquee: keep BlazorFastMarquee EnableDrag for sideways scrubbing, 3 * and open card links on tap (movement under threshold) via a sync window.open 4 * so popup blockers don't fire (Blazor @onclick / JS interop would). 5 */ 6export function Component(dotnetContext, itemRef) { 7 const DRAG_THRESHOLD_PX = 8; 8 9 let startX = 0; 10 let startY = 0; 11 let startHref = null; 12 let hasMoved = false; 13 let openedOnPointerUp = false; 14 // Survives until the synthetic click after pointerup â hasMoved is cleared earlier. 15 let suppressNextClick = false; 16 17 const findNewsLink = (eventTarget, clientX, clientY) => { 18 const fromTarget = 19 eventTarget instanceof Element 20 ? eventTarget.closest("a[data-news-link]") 21 : null; 22 if (fromTarget) { 23 return fromTarget; 24 } 25 26 const under = document.elementFromPoint(clientX, clientY); 27 return under instanceof Element ? under.closest("a[data-news-link]") : null; 28 }; 29 30 const onPointerDown = (e) => { 31 if (e.pointerType === "mouse" && e.button !== 0) { 32 return; 33 } 34 35 const link = findNewsLink(e.target, e.clientX, e.clientY); 36 if (!link) { 37 startHref = null; 38 return; 39 } 40 41 startHref = link.href; 42 startX = e.clientX; 43 startY = e.clientY; 44 hasMoved = false; 45 openedOnPointerUp = false; 46 suppressNextClick = false; 47 }; 48 49 const onPointerMove = (e) => { 50 if (!startHref || hasMoved) { 51 return; 52 } 53 54 const dx = Math.abs(e.clientX - startX); 55 const dy = Math.abs(e.clientY - startY); 56 if (dx > DRAG_THRESHOLD_PX || dy > DRAG_THRESHOLD_PX) { 57 hasMoved = true; 58 } 59 }; 60 61 const onPointerUp = (e) => { 62 if (!startHref) { 63 return; 64 } 65 66 const href = startHref; 67 const dragged = hasMoved; 68 startHref = null; 69 hasMoved = false; 70 71 if (dragged) { 72 // Click fires after pointerup with hasMoved already cleared â block it. 73 suppressNextClick = true; 74 return; 75 } 76 77 if (!href) { 78 return; 79 } 80 81 openedOnPointerUp = true; 82 window.open(href, "_blank", "noopener,noreferrer"); 83 }; 84 85 const onPointerCancel = () => { 86 startHref = null; 87 hasMoved = false; 88 openedOnPointerUp = false; 89 suppressNextClick = false; 90 }; 91 92 // Prevent native <a> navigation (and double-open) after we handled tap on pointerup, 93 // or after a drag scrub. Marquee may also suppress click; this is belt-and-suspenders. 94 const onClick = (e) => { 95 const link = findNewsLink(e.target, e.clientX, e.clientY); 96 if (!link) { 97 openedOnPointerUp = false; 98 suppressNextClick = false; 99 return; 100 } 101 102 e.preventDefault(); 103 e.stopPropagation(); 104 105 if (openedOnPointerUp || suppressNextClick) { 106 openedOnPointerUp = false; 107 suppressNextClick = false; 108 return; 109 } 110 111 // Keyboard / fallback activation when pointerup path didn't run 112 if (link.href) { 113 window.open(link.href, "_blank", "noopener,noreferrer"); 114 } 115 116 openedOnPointerUp = false; 117 suppressNextClick = false; 118 }; 119 120 itemRef.addEventListener("pointerdown", onPointerDown, true); 121 itemRef.addEventListener("pointermove", onPointerMove, true); 122 itemRef.addEventListener("pointerup", onPointerUp, true); 123 itemRef.addEventListener("pointercancel", onPointerCancel, true); 124 itemRef.addEventListener("click", onClick, true); 125 126 return { 127 dispose() { 128 itemRef.removeEventListener("pointerdown", onPointerDown, true); 129 itemRef.removeEventListener("pointermove", onPointerMove, true); 130 itemRef.removeEventListener("pointerup", onPointerUp, true); 131 itemRef.removeEventListener("pointercancel", onPointerCancel, true); 132 itemRef.removeEventListener("click", onClick, true); 133 }, 134 }; 135}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.