Highlights your interesting notifications, with an option to hide the unimportant ones.
当前为
// ==UserScript==
// @name Facebook Notifications Highlighter
// @namespace http://www.JamesKoss.com/
// @version 2.1.0
// @description Highlights your interesting notifications, with an option to hide the unimportant ones.
// @author James Koss
// @match https://www.facebook.com/*
// @supportURL https://greasyfork.org/en/scripts/27189-facebook-your-notifications-highlighter/feedback
// ==/UserScript==
(function() {
'use strict';
var first = true; // First notifications popup loading.
var hidden = false; // Non-highlighted notifications are hidden.
var updater = null; // Timed updating.
var fbNotificationsFlyout = null;
var ulElement = null;
var firstNotification = null;
var lastNotification = null;
// Wait for page to load.
window.addEventListener('load', function() {
startScript();
}, false);
function startScript() {
fbNotificationsFlyout = document.getElementById('fbNotificationsFlyout');
// Listen to a click on the notifications button on FB.
var fbNotificationsJewel = document.getElementById("fbNotificationsJewel");
fbNotificationsJewel.addEventListener("click", onclickJewel);
// Auto updater.
updater = setInterval(updateView, 500);
}
// Clicking the notifications button on FB.
function onclickJewel(e) {
if (e.which === 1) {
updateNotifications();
}
}
// Check if notifications need updating while displayed.
function updateView() {
// Notifications must be visible and ready.
if (fbNotificationsFlyout.offsetParent === null) return;
if (ulElement === null) return;
// Request more notifications.
if (hidden === true) {
// Scrollbar hidden.
var sbh = fbNotificationsFlyout.querySelector('div.uiScrollableAreaGripper.hidden_elem');
// Or scrolled to bottom.
var wrap = fbNotificationsFlyout.querySelector('div.uiScrollableAreaWrap');
var bottom = wrap.offsetHeight + wrap.scrollTop >= wrap.scrollHeight - 10;
// And loading jewel must exist, otherwise finished all loadings.
var jewel = fbNotificationsFlyout.querySelector('div.uiScrollableAreaContent span.jewelLoading');
if ((sbh || bottom) && jewel) {
// Fake a scroll event for loader.
var e = new Event('scroll');
fbNotificationsFlyout.querySelector('div.uiScrollableArea').dispatchEvent(e);
}
}
var curFirstNotification = ulElement.firstChild;
var curLastNotification = ulElement.lastChild;
// Update view, if new notifications, or loaded old ones.
if (curLastNotification !== lastNotification ||
curFirstNotification !== firstNotification) {
// Update globals.
firstNotification = curFirstNotification;
lastNotification = curLastNotification;
updateNotifications();
updateVisibility();
}
}
// After clicking the notification, remove highlight color and eventListener.
function removeHighlight(e) {
e.currentTarget.removeEventListener("click", removeHighlight);
// Remove script styling.
e.currentTarget.style.backgroundColor = "";
if (e.currentTarget.paramA !== null) {
e.currentTarget.paramA.style.backgroundColor = "";
}
}
// Update notifications visibility.
function updateVisibility(req) {
// Select all relevant notifications.
var notifications = ulElement.querySelectorAll('li:not([data-highlighted]), li[data-highlightedreact]');
for (var i=0; i < notifications.length; i++) {
var cur = notifications[i];
var displayMode = null;
if (hidden === true)
displayMode = 'none';
cur.style.display = displayMode;
}
}
// Update relevant notifications with highlight.
function updateNotifications() {
if (ulElement === null) {
ulElement = fbNotificationsFlyout.querySelector('ul');
}
// Delay until notifications elements are available.
if (ulElement === null) {
setTimeout(function(){ updateNotifications(); }, 500);
return;
}
// On first viewing.
if (first === true) {
first = false;
// Hide/Show option.
var headerActions = fbNotificationsFlyout.querySelector('div.uiHeaderActions');
var toggleOption = document.createElement("a");
toggleOption.style = "font-weight: bold;";
toggleOption.title = "Hide unimportant notifications.";
toggleOption.innerHTML = 'Hide Unimportant';
toggleOption.onclick = function(e) {
e.stopPropagation();
e.preventDefault();
if (hidden === true) {
hidden = false;
toggleOption.title = "Hide unimportant notifications.";
toggleOption.innerHTML = 'Hide Unimportant';
} else {
hidden = true;
toggleOption.title = "Show unimportant notifications.";
toggleOption.innerHTML = 'Show Unimportant';
}
updateVisibility();
};
var spacer = document.createElement("span");
spacer.setAttribute("role", "presentation");
spacer.setAttribute("aria-hidden", "true");
spacer.innerHTML = ' · ';
headerActions.insertBefore(toggleOption, headerActions.firstChild);
headerActions.insertBefore(spacer, toggleOption.nextSibling);
}
// Only check new notifications.
var notificationsNew = ulElement.querySelectorAll('li.jewelItemNew:not([data-highlighted])');
for (var i = 0; i < notificationsNew.length; i++) {
var current = notificationsNew[i];
var notificationParent = current.querySelector('div[class="_4l_v"]');
var notificationYour = notificationParent.querySelectorAll('span');
// match 1 for interest highlight, 2 for "Like" highlight.
var match = false;
for (var j=0; j < notificationYour.length; j++) {
var cur = notificationYour[j];
var t = cur.textContent;
// Relevant text inside notification element.
if (t.indexOf("replied to your") !== -1 ||
t.indexOf("commented on your") !== -1 ||
t.indexOf("shared your") !== -1 ||
t.indexOf("mentioned you") !== -1 ||
t.indexOf("tagged you") !== -1 ||
t.indexOf("you're tagged in") !== -1 ||
t.indexOf("made you") !== -1 ||
t.indexOf("also replied") !== -1 ||
(t.indexOf("replied to") !== -1 && t.indexOf("on your") !== -1) ||
t.indexOf("also commented on his post") !== -1 ||
t.indexOf("also commented on her post") !== -1 ||
t.indexOf("also commented on their post") !== -1) {
match = 1;
break;
} else if (t.indexOf("likes your") !== -1 ||
t.indexOf("like your") !== -1 ||
t.indexOf("liked your") !== -1 ||
t.indexOf("reacted to") !== -1) {
match = 2;
break;
} else if (t.indexOf("approved your") !== -1 ||
t.indexOf("changed the name of the") !== -1 ||
t.indexOf("changed the type of the") !== -1) {
match = 3;
break;
} else if (t.indexOf("needs review") !== -1 ||
t.indexOf("your Timeline") !== -1 ||
t.indexOf("flagged as possible spam") !== -1 ||
t.indexOf("added a photo of you") !== -1 ||
t.indexOf("invited you to join") !== -1) {
match = 4;
break;
}
}
// No match.
if (match === false) {
continue;
}
// Remember highlighted element.
current.dataset.highlighted = "1";
// Select color by matching value.
var color;
switch(match) {
case 1:
color = "#c3d4ef"; // darker blue
break;
case 2:
color = "#faedf8"; // light pink
current.dataset.highlightedreact = "1";
break;
case 3:
color = "#d7f4d7"; // light green
break;
case 4:
color = "#dec3ef"; // darker purple
break;
}
// Update the li & a elements backgrounds.
current.style.backgroundColor = color;
var a = current.querySelector('a[class="_33e _1_0e"]');
if (a !== null) {
a.style.backgroundColor = color;
}
// Pass to object, for highlight removal after click.
current.paramA = a;
current.addEventListener("click", removeHighlight);
}
}
})();