tangled
alpha
login
or
join now
margin.at
/
margin
86
fork
atom
Write on the margins of the internet. Powered by the AT Protocol.
margin.at
extension
web
atproto
comments
86
fork
atom
overview
issues
4
pulls
1
pipelines
remove text selection popup
scanash.com
1 month ago
50899d3a
33bf7042
+2
-124
1 changed file
expand all
collapse all
unified
split
extension
content
content.js
+2
-124
extension/content/content.js
···
2
let sidebarHost = null;
3
let sidebarShadow = null;
4
let popoverEl = null;
5
-
let selectionPopupEl = null;
6
7
let activeItems = [];
8
let currentSelection = null;
···
470
471
document.addEventListener("mousemove", handleMouseMove);
472
document.addEventListener("click", handleDocumentClick, true);
473
-
document.addEventListener("mouseup", handleTextSelection);
474
-
}
475
-
476
-
function handleTextSelection(e) {
477
-
if (e.target.closest && e.target.closest("#margin-overlay-host")) return;
478
-
479
-
const selection = window.getSelection();
480
-
const selectedText = selection?.toString().trim();
481
-
if (!selectedText || selectedText.length < 3) {
482
-
hideSelectionPopup();
483
-
return;
484
-
}
485
-
486
-
const anchorNode = selection.anchorNode;
487
-
if (anchorNode) {
488
-
const parent = anchorNode.parentElement;
489
-
if (
490
-
parent &&
491
-
(parent.tagName === "INPUT" ||
492
-
parent.tagName === "TEXTAREA" ||
493
-
parent.isContentEditable)
494
-
) {
495
-
return;
496
-
}
497
-
}
498
-
499
-
currentSelection = {
500
-
text: selectedText,
501
-
selector: { type: "TextQuoteSelector", exact: selectedText },
502
-
};
503
-
504
-
showSelectionPopup(e.clientX, e.clientY);
505
-
}
506
-
507
-
function showSelectionPopup(x, y) {
508
-
hideSelectionPopup();
509
-
if (!sidebarShadow) return;
510
-
511
-
const container = sidebarShadow.getElementById("margin-overlay-container");
512
-
if (!container) return;
513
-
514
-
selectionPopupEl = document.createElement("div");
515
-
selectionPopupEl.className = "margin-selection-popup";
516
-
517
-
const popupWidth = 180;
518
-
const viewportWidth = window.innerWidth;
519
-
let left = x + 5;
520
-
if (left + popupWidth > viewportWidth) {
521
-
left = viewportWidth - popupWidth - 10;
522
-
}
523
-
524
-
selectionPopupEl.style.left = `${left}px`;
525
-
selectionPopupEl.style.top = `${y + 10}px`;
526
-
527
-
selectionPopupEl.innerHTML = `
528
-
<button class="selection-btn btn-annotate">
529
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
530
-
<path d="M12 20h9M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
531
-
</svg>
532
-
Annotate
533
-
</button>
534
-
<button class="selection-btn btn-highlight">
535
-
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
536
-
<path d="M9 11l3 3L22 4"/>
537
-
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/>
538
-
</svg>
539
-
Highlight
540
-
</button>
541
-
`;
542
-
543
-
selectionPopupEl
544
-
.querySelector(".btn-annotate")
545
-
.addEventListener("click", (e) => {
546
-
e.stopPropagation();
547
-
hideSelectionPopup();
548
-
showInlineComposeModal();
549
-
});
550
-
551
-
selectionPopupEl
552
-
.querySelector(".btn-highlight")
553
-
.addEventListener("click", async (e) => {
554
-
e.stopPropagation();
555
-
hideSelectionPopup();
556
-
557
-
chrome.runtime.sendMessage(
558
-
{
559
-
type: "CREATE_HIGHLIGHT",
560
-
data: {
561
-
url: window.location.href,
562
-
title: document.title,
563
-
selector: currentSelection.selector,
564
-
color: "#fcd34d",
565
-
},
566
-
},
567
-
(res) => {
568
-
if (res && res.success) {
569
-
fetchAnnotations();
570
-
}
571
-
},
572
-
);
573
-
});
574
-
575
-
container.appendChild(selectionPopupEl);
576
-
577
-
setTimeout(() => {
578
-
document.addEventListener("mousedown", closeSelectionPopupOutside, {
579
-
once: true,
580
-
});
581
-
}, 100);
582
-
}
583
-
584
-
function hideSelectionPopup() {
585
-
if (selectionPopupEl) {
586
-
selectionPopupEl.remove();
587
-
selectionPopupEl = null;
588
-
}
589
-
}
590
-
591
-
function closeSelectionPopupOutside(e) {
592
-
if (selectionPopupEl && !selectionPopupEl.contains(e.target)) {
593
-
hideSelectionPopup();
594
-
}
595
}
596
597
function showInlineComposeModal() {
···
762
const firstRect = firstRange.getClientRects()[0];
763
const totalWidth =
764
Math.min(uniqueAuthors.length, maxShow + (overflow > 0 ? 1 : 0)) *
765
-
18 +
766
8;
767
const leftPos = firstRect.left - totalWidth;
768
const topPos = firstRect.top + firstRect.height / 2 - 12;
···
2
let sidebarHost = null;
3
let sidebarShadow = null;
4
let popoverEl = null;
5
+
6
7
let activeItems = [];
8
let currentSelection = null;
···
470
471
document.addEventListener("mousemove", handleMouseMove);
472
document.addEventListener("click", handleDocumentClick, true);
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
473
}
474
475
function showInlineComposeModal() {
···
640
const firstRect = firstRange.getClientRects()[0];
641
const totalWidth =
642
Math.min(uniqueAuthors.length, maxShow + (overflow > 0 ? 1 : 0)) *
643
+
18 +
644
8;
645
const leftPos = firstRect.left - totalWidth;
646
const topPos = firstRect.top + firstRect.height / 2 - 12;