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;
|
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) {
|
function isReliableActionBarCandidate(postElement, candidate) {
|
||||||
if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) {
|
if (!postElement || !candidate || !candidate.isConnected || !postElement.contains(candidate)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -377,7 +453,11 @@ function isReliableActionBarCandidate(postElement, candidate) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCommentComposerSignal(candidate)) {
|
if (
|
||||||
|
hasCommentComposerSignal(candidate)
|
||||||
|
|| hasCommentContentSignal(candidate)
|
||||||
|
|| hasCommentSortSignal(candidate)
|
||||||
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,18 +516,20 @@ function resolveActionButtonBar(postElement, buttonBar) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dataRoleResolved = findActionBarByDataRoles(postElement);
|
const candidates = [
|
||||||
if (dataRoleResolved) {
|
findActionBarByDataRoles(postElement),
|
||||||
return dataRoleResolved;
|
buttonBar,
|
||||||
}
|
findButtonBar(postElement)
|
||||||
|
];
|
||||||
|
|
||||||
if (buttonBar && isReliableActionBarCandidate(postElement, buttonBar)) {
|
for (const candidate of candidates) {
|
||||||
return buttonBar;
|
if (!candidate) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
const resolved = findButtonBar(postElement);
|
const normalized = normalizeActionBarCandidate(postElement, candidate);
|
||||||
if (resolved && isReliableActionBarCandidate(postElement, resolved)) {
|
if (normalized) {
|
||||||
return resolved;
|
return normalized;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -661,6 +743,28 @@ function insertMarkerAfterAnchor(postElement, marker, anchor) {
|
|||||||
return true;
|
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 = '?') {
|
function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum = '?') {
|
||||||
if (!postElement || !marker) {
|
if (!postElement || !marker) {
|
||||||
return false;
|
return false;
|
||||||
@@ -668,7 +772,6 @@ function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum
|
|||||||
|
|
||||||
const resolvedButtonBar = resolveActionButtonBar(postElement, buttonBar);
|
const resolvedButtonBar = resolveActionButtonBar(postElement, buttonBar);
|
||||||
const actionAnchor = getDirectActionAnchorInPost(postElement, resolvedButtonBar);
|
const actionAnchor = getDirectActionAnchorInPost(postElement, resolvedButtonBar);
|
||||||
const commentBoundary = findCommentBoundaryAnchorInPost(postElement, actionAnchor);
|
|
||||||
|
|
||||||
if (actionAnchor && insertMarkerBeforeAnchor(postElement, marker, actionAnchor)) {
|
if (actionAnchor && insertMarkerBeforeAnchor(postElement, marker, actionAnchor)) {
|
||||||
setTrackerInsertionMarkerLocked(marker, true);
|
setTrackerInsertionMarkerLocked(marker, true);
|
||||||
@@ -682,28 +785,13 @@ function positionTrackerInsertionMarker(postElement, marker, buttonBar, postNum
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const commentComposerAnchor = findCommentComposerAnchorInPost(postElement);
|
if (postElement.firstChild) {
|
||||||
if (commentComposerAnchor && insertMarkerBeforeAnchor(postElement, marker, commentComposerAnchor)) {
|
postElement.insertBefore(marker, postElement.firstChild);
|
||||||
setTrackerInsertionMarkerLocked(marker, true);
|
} else {
|
||||||
console.log('[FB Tracker] Post #' + postNum + ' - Marker inserted before comment composer');
|
postElement.appendChild(marker);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,8 +805,21 @@ function isTrackerInsertionMarkerPlacementValid(postElement, marker, buttonBar)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const actionAnchor = getDirectActionAnchorInPost(postElement, buttonBar);
|
const actionAnchor = getDirectActionAnchorInPost(postElement, buttonBar);
|
||||||
if (actionAnchor && isNodeAfter(marker, actionAnchor)) {
|
if (actionAnchor) {
|
||||||
return false;
|
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);
|
const commentBoundary = findCommentBoundaryAnchorInPost(postElement);
|
||||||
|
|||||||
Reference in New Issue
Block a user