Stabilize tracker bar placement above Facebook action row
This commit is contained in:
@@ -368,6 +368,82 @@ function countActionRoleSignals(node) {
|
||||
return [hasLike, hasComment, hasShare].filter(Boolean).length;
|
||||
}
|
||||
|
||||
function hasCommentSortSignal(node) {
|
||||
if (!node || !node.querySelector) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Boolean(
|
||||
node.querySelector(
|
||||
'[aria-label*="relevantes zuerst" i], [aria-label*="most relevant" i], [aria-label*="neueste" i], [aria-label*="newest" i]'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function isActionRowShapeCandidate(postElement, candidate) {
|
||||
if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (candidate.closest('.fb-tracker-ui')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
hasCommentComposerSignal(candidate)
|
||||
|| hasCommentContentSignal(candidate)
|
||||
|| hasCommentSortSignal(candidate)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const buttonCount = candidate.querySelectorAll('[role="button"], button').length;
|
||||
if (buttonCount < 3 || buttonCount > 24) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isCompactActionBarCandidate(postElement, candidate) {
|
||||
if (!isActionRowShapeCandidate(postElement, candidate)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const actionRoleSignals = countActionRoleSignals(candidate);
|
||||
if (actionRoleSignals >= 2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return hasInteractionButtons(candidate);
|
||||
}
|
||||
|
||||
function normalizeActionBarCandidate(postElement, candidate) {
|
||||
if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let fallback = null;
|
||||
let current = candidate;
|
||||
for (let depth = 0; depth < 12 && current && current !== postElement; depth++) {
|
||||
if (isCompactActionBarCandidate(postElement, current)) {
|
||||
return current;
|
||||
}
|
||||
|
||||
if (!fallback && isActionRowShapeCandidate(postElement, current)) {
|
||||
fallback = current;
|
||||
}
|
||||
|
||||
current = current.parentElement;
|
||||
}
|
||||
|
||||
if (fallback) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return isReliableActionBarCandidate(postElement, candidate) ? candidate : null;
|
||||
}
|
||||
|
||||
function isReliableActionBarCandidate(postElement, candidate) {
|
||||
if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) {
|
||||
return false;
|
||||
@@ -377,7 +453,11 @@ function isReliableActionBarCandidate(postElement, candidate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasCommentComposerSignal(candidate)) {
|
||||
if (
|
||||
hasCommentComposerSignal(candidate)
|
||||
|| hasCommentContentSignal(candidate)
|
||||
|| hasCommentSortSignal(candidate)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -436,18 +516,20 @@ function resolveActionButtonBar(postElement, buttonBar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const dataRoleResolved = findActionBarByDataRoles(postElement);
|
||||
if (dataRoleResolved) {
|
||||
return dataRoleResolved;
|
||||
}
|
||||
const candidates = [
|
||||
findActionBarByDataRoles(postElement),
|
||||
buttonBar,
|
||||
findButtonBar(postElement)
|
||||
];
|
||||
|
||||
if (buttonBar && isReliableActionBarCandidate(postElement, buttonBar)) {
|
||||
return buttonBar;
|
||||
}
|
||||
|
||||
const resolved = findButtonBar(postElement);
|
||||
if (resolved && isReliableActionBarCandidate(postElement, resolved)) {
|
||||
return resolved;
|
||||
for (const candidate of candidates) {
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
const normalized = normalizeActionBarCandidate(postElement, candidate);
|
||||
if (normalized) {
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -661,6 +743,28 @@ function insertMarkerAfterAnchor(postElement, marker, anchor) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getNextNonTrackerSibling(node) {
|
||||
if (!node) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let current = node.nextElementSibling;
|
||||
while (current) {
|
||||
if (
|
||||
!current.classList
|
||||
|| (
|
||||
!current.classList.contains('fb-tracker-ui')
|
||||
&& !current.classList.contains('fb-tracker-insertion-anchor')
|
||||
)
|
||||
) {
|
||||
return current;
|
||||
}
|
||||
current = current.nextElementSibling;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum = '?') {
|
||||
if (!postElement || !marker) {
|
||||
return false;
|
||||
@@ -668,7 +772,6 @@ function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum
|
||||
|
||||
const resolvedButtonBar = resolveActionButtonBar(postElement, buttonBar);
|
||||
const actionAnchor = getDirectActionAnchorInPost(postElement, resolvedButtonBar);
|
||||
const commentBoundary = findCommentBoundaryAnchorInPost(postElement, actionAnchor);
|
||||
|
||||
if (actionAnchor && insertMarkerBeforeAnchor(postElement, marker, actionAnchor)) {
|
||||
setTrackerInsertionMarkerLocked(marker, true);
|
||||
@@ -682,28 +785,13 @@ function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum
|
||||
return true;
|
||||
}
|
||||
|
||||
const commentComposerAnchor = findCommentComposerAnchorInPost(postElement);
|
||||
if (commentComposerAnchor && insertMarkerBeforeAnchor(postElement, marker, commentComposerAnchor)) {
|
||||
setTrackerInsertionMarkerLocked(marker, true);
|
||||
console.log('[FB Tracker] Post #' + postNum + ' - Marker inserted before comment composer');
|
||||
return true;
|
||||
if (postElement.firstChild) {
|
||||
postElement.insertBefore(marker, postElement.firstChild);
|
||||
} else {
|
||||
postElement.appendChild(marker);
|
||||
}
|
||||
|
||||
if (commentBoundary && insertMarkerBeforeAnchor(postElement, marker, commentBoundary)) {
|
||||
setTrackerInsertionMarkerLocked(marker, true);
|
||||
console.log('[FB Tracker] Post #' + postNum + ' - Marker inserted before comment boundary');
|
||||
return true;
|
||||
}
|
||||
|
||||
if (buttonBar && buttonBar.parentElement && buttonBar.parentElement.parentElement && !postElement.contains(buttonBar.parentElement.parentElement)) {
|
||||
buttonBar.parentElement.parentElement.insertBefore(marker, buttonBar.parentElement.nextSibling);
|
||||
setTrackerInsertionMarkerLocked(marker, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
postElement.appendChild(marker);
|
||||
setTrackerInsertionMarkerLocked(marker, false);
|
||||
console.log('[FB Tracker] Post #' + postNum + ' - Marker fallback appended to post');
|
||||
console.log('[FB Tracker] Post #' + postNum + ' - Marker fallback prepended to post');
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -717,8 +805,21 @@ function isTrackerInsertionMarkerPlacementValid(postElement, marker, buttonBar)
|
||||
}
|
||||
|
||||
const actionAnchor = getDirectActionAnchorInPost(postElement, buttonBar);
|
||||
if (actionAnchor && isNodeAfter(marker, actionAnchor)) {
|
||||
return false;
|
||||
if (actionAnchor) {
|
||||
if (isNodeAfter(marker, actionAnchor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (actionAnchor.contains(marker) || marker.contains(actionAnchor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (marker.parentElement === actionAnchor.parentElement) {
|
||||
const nextSibling = getNextNonTrackerSibling(marker);
|
||||
if (nextSibling && nextSibling !== actionAnchor) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const commentBoundary = findCommentBoundaryAnchorInPost(postElement);
|
||||
|
||||
Reference in New Issue
Block a user