Place tracker below sort row to avoid dropdown overlap
This commit is contained in:
@@ -299,6 +299,80 @@ function getDirectActionAnchorInPost(postElement, buttonBar) {
|
|||||||
return getTrackerInsertionAnchorInPost(postElement, buttonBar);
|
return getTrackerInsertionAnchorInPost(postElement, buttonBar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isNodeAfter(node, referenceNode) {
|
||||||
|
if (!node || !referenceNode || node === referenceNode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return Boolean(referenceNode.compareDocumentPosition(node) & Node.DOCUMENT_POSITION_FOLLOWING);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTopLevelAnchorWithinPost(postElement, element) {
|
||||||
|
if (!postElement || !element || !postElement.contains(element)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let anchor = element;
|
||||||
|
while (anchor.parentElement && anchor.parentElement !== postElement) {
|
||||||
|
anchor = anchor.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return anchor && anchor.parentElement === postElement ? anchor : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function findCommentSortAnchorInPost(postElement, actionAnchor = null) {
|
||||||
|
if (!postElement) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const keywords = ['relevantes zuerst', 'most relevant', 'neueste', 'newest'];
|
||||||
|
const selectorCandidates = postElement.querySelectorAll([
|
||||||
|
'[aria-label*="relevantes zuerst" i]',
|
||||||
|
'[aria-label*="most relevant" i]',
|
||||||
|
'[aria-label*="neueste" i]',
|
||||||
|
'[aria-label*="newest" i]'
|
||||||
|
].join(', '));
|
||||||
|
|
||||||
|
const candidates = new Set(selectorCandidates);
|
||||||
|
postElement.querySelectorAll('[role="button"], button').forEach((node) => {
|
||||||
|
const text = (node.textContent || '').trim().toLowerCase();
|
||||||
|
if (text && text.length <= 80 && keywords.some((keyword) => text.includes(keyword))) {
|
||||||
|
candidates.add(node);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const anchors = [];
|
||||||
|
candidates.forEach((candidate) => {
|
||||||
|
if (!candidate || !isElementVisible(candidate) || candidate.closest('.fb-tracker-ui')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let anchor = getTopLevelAnchorWithinPost(postElement, candidate) || candidate;
|
||||||
|
if (anchor === actionAnchor) {
|
||||||
|
anchor = candidate;
|
||||||
|
}
|
||||||
|
if (!anchor || !anchor.parentElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (actionAnchor && anchor !== actionAnchor && !isNodeAfter(anchor, actionAnchor)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors.push(anchor);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!anchors.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
anchors.sort((a, b) => {
|
||||||
|
if (a === b) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1;
|
||||||
|
});
|
||||||
|
return anchors[0];
|
||||||
|
}
|
||||||
|
|
||||||
const AI_CREDENTIAL_CACHE_TTL = 60 * 1000; // 1 minute cache
|
const AI_CREDENTIAL_CACHE_TTL = 60 * 1000; // 1 minute cache
|
||||||
const aiCredentialCache = {
|
const aiCredentialCache = {
|
||||||
data: null,
|
data: null,
|
||||||
@@ -3233,8 +3307,6 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
row-gap: 6px;
|
row-gap: 6px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
position: relative;
|
|
||||||
z-index: 2;
|
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
`;
|
`;
|
||||||
@@ -3848,11 +3920,18 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
}
|
}
|
||||||
|
|
||||||
const directActionAnchor = getDirectActionAnchorInPost(postElement, buttonBar);
|
const directActionAnchor = getDirectActionAnchorInPost(postElement, buttonBar);
|
||||||
|
const inPostActionAnchor = getTopLevelAnchorWithinPost(postElement, directActionAnchor) || directActionAnchor;
|
||||||
|
const commentSortAnchor = findCommentSortAnchorInPost(postElement, inPostActionAnchor);
|
||||||
|
const preferredAnchor = commentSortAnchor || inPostActionAnchor;
|
||||||
|
|
||||||
// Strategy 1: Insert directly below the actions row
|
// Strategy 1: Insert below actions; if present, place below the sort row
|
||||||
if (!inserted && directActionAnchor && directActionAnchor.parentElement) {
|
if (!inserted && preferredAnchor && preferredAnchor.parentElement) {
|
||||||
directActionAnchor.parentElement.insertBefore(container, directActionAnchor.nextSibling);
|
preferredAnchor.parentElement.insertBefore(container, preferredAnchor.nextSibling);
|
||||||
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted directly below actions. ID: #' + container.id);
|
if (commentSortAnchor) {
|
||||||
|
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted below comment sort row. ID: #' + container.id);
|
||||||
|
} else {
|
||||||
|
console.log('[FB Tracker] Post #' + postNum + ' - UI inserted directly below actions. ID: #' + container.id);
|
||||||
|
}
|
||||||
inserted = true;
|
inserted = true;
|
||||||
}
|
}
|
||||||
// Strategy 2: Insert directly after the detected button bar if still inside the post container
|
// Strategy 2: Insert directly after the detected button bar if still inside the post container
|
||||||
@@ -3900,8 +3979,11 @@ async function createTrackerUI(postElement, buttonBar, postNum = '?', options =
|
|||||||
observer.disconnect();
|
observer.disconnect();
|
||||||
// Try to re-insert
|
// Try to re-insert
|
||||||
const currentDirectActionAnchor = getDirectActionAnchorInPost(postElement, buttonBar);
|
const currentDirectActionAnchor = getDirectActionAnchorInPost(postElement, buttonBar);
|
||||||
if (currentDirectActionAnchor && currentDirectActionAnchor.parentElement) {
|
const currentInPostActionAnchor = getTopLevelAnchorWithinPost(postElement, currentDirectActionAnchor) || currentDirectActionAnchor;
|
||||||
currentDirectActionAnchor.parentElement.insertBefore(container, currentDirectActionAnchor.nextSibling);
|
const currentCommentSortAnchor = findCommentSortAnchorInPost(postElement, currentInPostActionAnchor);
|
||||||
|
const currentPreferredAnchor = currentCommentSortAnchor || currentInPostActionAnchor;
|
||||||
|
if (currentPreferredAnchor && currentPreferredAnchor.parentElement) {
|
||||||
|
currentPreferredAnchor.parentElement.insertBefore(container, currentPreferredAnchor.nextSibling);
|
||||||
} else if (buttonBar && buttonBar.parentElement && postElement.contains(buttonBar.parentElement)) {
|
} else if (buttonBar && buttonBar.parentElement && postElement.contains(buttonBar.parentElement)) {
|
||||||
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
|
buttonBar.parentElement.insertBefore(container, buttonBar.nextSibling);
|
||||||
} else if (buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement && !postElement.contains(buttonBar.parentElement.parentElement)) {
|
} else if (buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement && !postElement.contains(buttonBar.parentElement.parentElement)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user