Skip to content

Instantly share code, notes, and snippets.

@dertuxmalwieder
Last active February 6, 2023 01:38
Show Gist options
  • Save dertuxmalwieder/5ad281037ed627de23f88f79629913cb to your computer and use it in GitHub Desktop.
Save dertuxmalwieder/5ad281037ed627de23f88f79629913cb to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Whisky.de-Forum ++
// @author WithKeys
// @namespace tuxproject.de
// @description Zusätzliche Funktionen für das Whisky.de-Forum.
// @include /www.whisky.de\/forum\/.*/
// @include /www.whisky.de\/tfg\/forum.html$/
// @exclude /\.(jpe?g|png|gif)$/
// @require https://raw.githubusercontent.com/franciscop/umbrella/master/umbrella.min.js
// @version 5.4
// @license CDDL-1.1; https://spdx.org/licenses/CDDL-1.1.html#licenseText
// @downloadURL https://gist.github.com/dertuxmalwieder/5ad281037ed627de23f88f79629913cb/raw/WDE++.user.js
// @grant GM.addStyle
// @grant GM.getValue
// @grant GM.setValue
// @grant GM.info
// @run-at document-idle
// ==/UserScript==
// -------- WDE++-Button:
u("#header .navigation-realms ul").append('<li class="wde"><a href="#" onclick="return false;" id="wdeplus_btn"><span>WDE++</span></a></li>');
// -------- Einstellungsdialog:
// Der Einstellungsdialog ist inzwischen so groß geworden, dass wir ihn auf mobilen
// (kleinen) Geräten nicht mehr vernünftig anzeigen können. Nutzer solcher Geräte
// sollten WDE++ aber natürlich trotzdem vernünftig nutzen können.
// Lösung: Wir brauchen einen zweiten, kleineren Einstellungsdialog, der nur die
// wesentlichen Optionen anzeigt - Kopfbereich und Seitenleisten und ähnliche UI-
// Spielereien sind hier nicht so entscheidend und können bei den Standardwerten
// belassen werden.
// Ein Gerät gilt als Mobilgerät, falls das bevorzugte Eingabegerät über Elementen
// schweben kann. Das können Mäuse ganz gut und Finger eher nicht. Bonusproblem:
// Tablets haben meist keine Maus, aber sind groß genug, um den Einstellungsdialog
// vernünftig anzuzeigen. Smartphones aber nicht. Wir brauchen also zusätzlich eine
// Erkennung der Bildschirmgröße. Außerdem gehen wir davon aus, dass im Querformat
// alles akzeptabel aussieht, weil wir ein bisschen naiv sind. ;-)
const isSmallMobileDevice = window.matchMedia("(max-width: 1024px) and (orientation: portrait) and (any-hover: none)").matches;
const dialogHtml = isSmallMobileDevice ? '\
<div id="wdeplusSettingsCtr" class="wdeSmall"> \
<form> \
<div class="wdeplusHdr wdeSmall">WDE++ - mobile Version</div> \
\
<input type="checkbox" name="wdeChkConvertWID" id="wdeChkConvertWID" /> \
<label for="wdeChkConvertWID">WIDs als Links darstellen</label> \
\
<div style="margin-left:16px"> \
Anzeigestil: \
\
<input type="radio" name="wdeRdConvertWIDStyle" value="1" id="wdeRdConvertWIDStyle1" /> \
<label for="wdeRdConvertWIDStyle1" title="Zeigt [WB] an.">[WB]</label> \
\
<input type="radio" name="wdeRdConvertWIDStyle" value="2" id="wdeRdConvertWIDStyle2" /> \
<label for="wdeRdConvertWIDStyle2" title="Zeigt [Whisky-ID] an.">[123456]</label> \
\
<input type="radio" name="wdeRdConvertWIDStyle" value="3" id="wdeRdConvertWIDStyle3" /> \
<label for="wdeRdConvertWIDStyle3" title="Zeigt [WB: Whisky-ID] an.">[WB: 123456]</label> \
</div> \
\
<br /> \
\
<input type="checkbox" name="wdeChkUncropQuotes" id="wdeChkUncropQuotes" /> \
<label for="wdeChkUncropQuotes">Zitate kompakter anzeigen</label> \
\
<br /> \
\
<input type="checkbox" style="display:none" name="wdeChkDontCollapseSignatures" id="wdeChkDontCollapseSignatures" /> \
\
<input type="checkbox" name="wdeChkHideCounter" id="wdeChkHideCounter" /> \
<label for="wdeChkHideCounter">Beitragszähler ausblenden</label> \
\
<input type="checkbox" style="display:none" name="wdeChkPinHeader" id="wdeChkPinHeader" /> \
<input type="checkbox" style="display:none" name="wdeChkLeftSidebar" id="wdeChkLeftSidebar" /> \
<input type="checkbox" style="display:none" name="wdeChkRightSidebar" id="wdeChkRightSidebar" /> \
\
<br /><br /> \
\
<input type="text" name="wdeThreadIgnoreList" id="wdeThreadIgnoreList" placeholder="Die hier eingetragenen Themen werden ausgeblendet." /> \
<label for="wdeThreadIgnoreList">Zu ignorierende Themen (IDs oder Titel, mit Semikolon getrennt)<br /><span class="wdeplusHint"><b>Achtung:</b> Unter "Neueste Beiträge" funktionieren nur die Titel!</span></label> \
\
<br /><br /> \
\
<input type="text" name="wdeUserIgnoreList" id="wdeUserIgnoreList" placeholder="Die hier eingetragenen Benutzer werden ausgeblendet." /> \
<label for="wdeUserIgnoreList">Zu ignorierende Benutzer (mit Semikolon getrennt)</label><br /> \
<input type="checkbox" name="wdeUserIgnoreCompletely" id="wdeUserIgnoreCompletely" /> \
<label for="wdeUserIgnoreCompletely">Beiträge komplett entfernen</label> \
\
<br /><br /> \
\
<button id="wdeSaveBtn" type="button">speichern und neu laden</button> \
<button id="wdeCloseBtn" type="button">abbrechen und schließen</button> \
</form> \
</div> \
'
:
'\
<div id="wdeplusSettingsCtr"> \
<form> \
<div class="wdeplusHdr">WDE++: Einstellungen fürs Whiskyforum</div> \
\
<input type="checkbox" name="wdeChkConvertWID" id="wdeChkConvertWID" /> \
<label for="wdeChkConvertWID" title="Wandelt &quot;WID: ...&quot; automatisch in Links zum Whisky um.">WIDs als Links darstellen</label> \
\
<br /> \
\
<div style="margin-left:16px"> \
Anzeigestil: \
\
<input type="radio" name="wdeRdConvertWIDStyle" value="1" id="wdeRdConvertWIDStyle1" /> \
<label for="wdeRdConvertWIDStyle1" title="Zeigt [WB] an.">[WB]</label> \
\
<input type="radio" name="wdeRdConvertWIDStyle" value="2" id="wdeRdConvertWIDStyle2" /> \
<label for="wdeRdConvertWIDStyle2" title="Zeigt [Whisky-ID] an.">[123456]</label> \
\
<input type="radio" name="wdeRdConvertWIDStyle" value="3" id="wdeRdConvertWIDStyle3" /> \
<label for="wdeRdConvertWIDStyle3" title="Zeigt [WB: Whisky-ID] an.">[WB: 123456]</label> \
</div> \
\
<br /> \
\
<input type="checkbox" name="wdeChkUncropQuotes" id="wdeChkUncropQuotes" /> \
<label for="wdeChkUncropQuotes" title="Entfernt verschachtelte Zitate und klappt Zitate immer aus.">Zitate kompakter anzeigen</label> \
\
<br /> \
\
<input type="checkbox" name="wdeChkDontCollapseSignatures" id="wdeChkDontCollapseSignatures" /> \
<label for="wdeChkDontCollapseSignatures" title="Deaktiviert das automatische Einklappen von Signaturen.">Signaturen immer komplett anzeigen</label> \
\
<br /> \
\
<input type="checkbox" name="wdeChkHideCounter" id="wdeChkHideCounter" /> \
<label for="wdeChkHideCounter" title="Entfernt den Beitragszähler unter Benutzernamen.">Beitragszähler ausblenden</label> \
\
<br /> \
\
<input type="checkbox" name="wdeChkPinHeader" id="wdeChkPinHeader" /> \
<label for="wdeChkPinHeader" title="Hält den Kopfbereich immer im sichtbaren Bereich.">Kopfbereich anheften</label> \
\
<br /> \
\
<input type="checkbox" name="wdeChkLeftSidebar" id="wdeChkLeftSidebar" /> \
<label for="wdeChkLeftSidebar" title="Hinweis: Alle Elemente in der linken Leiste werden gelöscht!">Linke Seitenleiste ausblenden</label> \
\
<br /> \
\
<input type="checkbox" name="wdeChkRightSidebar" id="wdeChkRightSidebar" /> \
<label for="wdeChkRightSidebar">Rechte Seitenleiste ausblenden</label> \
\
<br /><br /> \
\
<input type="text" name="wdeThreadIgnoreList" id="wdeThreadIgnoreList" placeholder="Die hier eingetragenen Themen werden ausgeblendet." /> \
<label for="wdeThreadIgnoreList" title="Die hier eingetragenen Themen werden ausgeblendet.">Zu ignorierende Themen (IDs oder Titel, mit Semikolon getrennt)<br /><span class="wdeplusHint"><b>Achtung:</b> Unter "Neueste Beiträge" funktionieren nur die Titel!</span></label> \
\
<br /><br /> \
\
<input type="text" name="wdeUserIgnoreList" id="wdeUserIgnoreList" placeholder="Die hier eingetragenen Benutzer werden ausgeblendet." /> \
<label for="wdeUserIgnoreList" title="Die hier eingetragenen Benutzer werden ausgeblendet.">Zu ignorierende Benutzer (mit Semikolon getrennt)</label><br /> \
<input type="checkbox" name="wdeUserIgnoreCompletely" id="wdeUserIgnoreCompletely" /> \
<label for="wdeUserIgnoreCompletely" title="An = Beiträge werden entfernt, aus = Beiträge werden durch Platzhalter ersetzt.">Beiträge komplett entfernen</label> \
\
<br /><br /> \
\
<button id="wdeSaveBtn" type="button">speichern und neu laden</button> \
<button id="wdeCloseBtn" type="button" title="Tastenkürzel: &lt;Esc&gt;">abbrechen und schließen</button> \
</form> \
</div> \
';
u("body").append(dialogHtml);
u("#wdeplus_btn").on("click", function() {
u("#wdeplusSettingsCtr").addClass("visible");
}, false);
u("#wdeCloseBtn").on("click", function() {
u("#wdeplusSettingsCtr").removeClass("visible");
}, false);
u("#wdeChkConvertWID").on("click", function() {
document.getElementById("wdeRdConvertWIDStyle1").disabled = !u(this).is(":checked");
document.getElementById("wdeRdConvertWIDStyle2").disabled = !u(this).is(":checked");
document.getElementById("wdeRdConvertWIDStyle3").disabled = !u(this).is(":checked");
});
u("#wdeSaveBtn").on("click", function () {
// Speichern:
GM.setValue("convertWIDs", cbToBit("#wdeChkConvertWID"));
GM.setValue("pinHeader", cbToBit("#wdeChkPinHeader"));
GM.setValue("disableLeftSidebar", cbToBit("#wdeChkLeftSidebar"));
GM.setValue("disableRightSidebar", cbToBit("#wdeChkRightSidebar"));
GM.setValue("uncropQuotes", cbToBit("#wdeChkUncropQuotes"));
GM.setValue("dontCollapseSignatures", cbToBit("#wdeChkDontCollapseSignatures"));
GM.setValue("hideCounter", cbToBit("#wdeChkHideCounter"));
GM.setValue("userIgnoreList", document.getElementById("wdeUserIgnoreList").value);
GM.setValue("userIgnoreCompletely", cbToBit("#wdeUserIgnoreCompletely"));
GM.setValue("threadIgnoreList", document.getElementById("wdeThreadIgnoreList").value);
if (cbToBit("#wdeRdConvertWIDStyle1")) GM.setValue("convertWIDStyle", 1);
else if (cbToBit("#wdeRdConvertWIDStyle2")) GM.setValue("convertWIDStyle", 2);
else GM.setValue("convertWIDStyle", 3);
window.location.reload(true);
}, false);
// Versionsnummer im Einstellungsfenster anzeigen:
u(".wdeplusHdr").html(u(".wdeplusHdr").html() + " [Version " + GM.info.script.version + "]");
// -------- Variablen (werden in den Einstellungen gesetzt):
let ConvertWIDs = await GM.getValue('convertWIDs', 0);
let ConvertWIDStyle = await GM.getValue('convertWIDStyle', 3);
let PinHeader = await GM.getValue('pinHeader', 0);
let DisableLeftSidebar = await GM.getValue('disableLeftSidebar', 0);
let DisableRightSidebar = await GM.getValue('disableRightSidebar', 1);
let UncropQuotes = await GM.getValue('uncropQuotes', 1);
let DontCollapseSignatures = await GM.getValue('dontCollapseSignatures', 0);
let HideCounter = await GM.getValue('hideCounter', 0);
let UserIgnoreList = await GM.getValue('userIgnoreList', '');
let UserIgnoreDelete = await GM.getValue('userIgnoreCompletely', 0);
let ThreadIgnoreList = await GM.getValue('threadIgnoreList', '');
// Dialogelemente vorbelegen:
if (ConvertWIDs == 1) { u("#wdeChkConvertWID").attr("checked", true); }
u("#wdeRdConvertWIDStyle" + ConvertWIDStyle).attr("checked", true);
if (PinHeader == 1) { u("#wdeChkPinHeader").attr("checked", true); }
if (DisableLeftSidebar == 1) { u("#wdeChkLeftSidebar").attr("checked", true); }
if (DisableRightSidebar == 1) { u("#wdeChkRightSidebar").attr("checked", true); }
if (UncropQuotes == 1) { u("#wdeChkUncropQuotes").attr("checked", true); }
if (DontCollapseSignatures == 1) { u("#wdeChkDontCollapseSignatures").attr("checked", true); }
if (HideCounter == 1) { u("#wdeChkHideCounter").attr("checked", true); }
if (UserIgnoreDelete == 1) { u("#wdeUserIgnoreCompletely").attr("checked", true); }
document.getElementById("wdeUserIgnoreList").value = UserIgnoreList;
document.getElementById("wdeThreadIgnoreList").value = ThreadIgnoreList;
document.getElementById("wdeRdConvertWIDStyle1").disabled = ConvertWIDs != 1;
document.getElementById("wdeRdConvertWIDStyle2").disabled = ConvertWIDs != 1;
document.getElementById("wdeRdConvertWIDStyle3").disabled = ConvertWIDs != 1;
// -------- Trigger für das Einstellungsmenü:
function cbToBit(node) {
// Checkboxselector rein, 1 oder 0 raus.
return u(node).is(":checked") ? 1 : 0;
}
document.addEventListener('keyup', function (event) {
// Einstellungen per <Esc> schließen:
if (event.defaultPrevented || !u("#wdeplusSettingsCtr").hasClass("visible")) {
return;
}
let key = event.key || event.keyCode;
if (key === 'Escape' || key === 'Esc' || key === 27) {
u("#wdeplusSettingsCtr").removeClass("visible");
}
});
// -------- Größenvariablen für Elemente, die wir später vielleicht
// entfernen, aber ihre Breite danach noch brauchen:
let sidebar_links = u("#sidebar-left").size().width;
let sidebar_rechts = u("#sidebar-right").size().width;
// -------- Tu' Dinge auf der Seite:
// Selektor für ganze Seite:
const pagewrapper = u(".page-content");
const wdeObserver = new MutationObserver(function(mutations) {
// Wegen des blöden :-) AJAX-Krempels müssen wir aktiv gucken,
// ob sich die Seite ändert, und ggf. reagieren.
mutations.forEach(function(mutation) {
if (mutation.type == "childList" && mutation.addedNodes != null) {
// Beiträge wurden nachgeladen:
processPage();
}
});
});
const obsConfig = {
attributes: true,
childList: true,
characterData: true,
subtree: true
};
wdeObserver.observe(document.getElementById("content"), obsConfig);
function addWDEPlusSmileys() {
// Affen- und Schulternzuckemoji einfügbar machen:
const affensmiley = "<li class=\"wdePlusSmiley\" aria-label='<img class=\"emoji\" src=\"https://i.imgur.com/TenuIIZ.png\" title=\"Affe. (WDE++-Extra)\" alt=\"Affe. (WDE++-Extra)\" height=\"20\" />'><a href=\"#\" data-value='<img class=\"emoji\" src=\"https://i.imgur.com/TenuIIZ.png\" title=\"Affe. (WDE++-Extra)\" alt=\"Affe. (WDE++-Extra)\" height=\"20\" />'><img class=\"emoji\" src=\"https://i.imgur.com/TenuIIZ.png\" title=\"Affe. (WDE++-Extra)\" alt=\"Affe. (WDE++-Extra)\" height=\"20\" /></a></li>";
const schulternzuck = "<li class=\"wdePlusSmiley\" aria-label='<img class=\"emoji\" src=\"https://i.imgur.com/89q8r3X.png\" title=\"Schulternzuck. (WDE++-Extra)\" alt=\"Schulternzuck. (WDE++-Extra)\" height=\"20\" />'><a href=\"#\" data-value='<img class=\"emoji\" src=\"https://i.imgur.com/89q8r3X.png\" title=\"Schulternzuck. (WDE++-Extra)\" alt=\"Schulternzuck. (WDE++-Extra)\" height=\"20\" />'><img class=\"emoji\" src=\"https://i.imgur.com/89q8r3X.png\" title=\"Schulternzuck. (WDE++-Extra)\" alt=\"Schulternzuck. (WDE++-Extra)\" height=\"20\" /></a></li>";
u("ul.dropdown-smileys:not(.wdeProcessed)").each(function(node, i) {
u(node).append(affensmiley);
u(node).append(schulternzuck);
u(node).addClass("wdeProcessed");
});
}
function addThreadIgnoreMenu(force) {
// Fügt Menüpunkte zum Ignorieren/Entignorieren von Threads dem Zahnradmenü hinzu.
const menuUl = u("#Item_0.PageTitle .header-options .Options .OptionsMenu ul.Flyout");
if (menuUl != null && (force || !u(".page-content").hasClass("wdeplusprocd"))) {
// Diese Funktion ist rekursiv. Beim initialen Aufruf sollte "force" auf "false" stehen,
// denn sonst wird sie in Endlosschleife aufgerufen und das ist nicht gut.
// Ist der Thread bereits ignoriert?
const numericThreadId = u("#Form_DiscussionID") != null ? u("#Form_DiscussionID").attr("value") : "0";
const threadTitle = u("#Item_0.PageTitle h1").html();
const ignoreThreadListArray = ThreadIgnoreList.split(";").map(s => s.trim());
if (ignoreThreadListArray.length > 0) {
const isIgnore = ignoreThreadListArray.includes(numericThreadId) || ignoreThreadListArray.includes(threadTitle);
const ignoreMenu = '<li id="ThreadIgnoreMenu" data-threadtitle="'+ threadTitle +'" data-threadid="' + numericThreadId + '"><a href="#" onclick="return false;">' + (isIgnore ? "Entignorieren" : "Ignorieren") + '</a></li>';
// Einmal reicht:
if (u("#ThreadIgnoreMenu") != null) u("#ThreadIgnoreMenu").remove();
menuUl.append(ignoreMenu);
u("#ThreadIgnoreMenu").on("click", function() {
// (Ent-)Ignorieren:
const isIgnoreNum = ignoreThreadListArray.includes(u(this).attr("data-threadid"));
const isIgnoreTxt = ignoreThreadListArray.includes(u(this).attr("data-threadtitle"));
if (isIgnoreNum) {
let index = ignoreThreadListArray.indexOf(u(this).attr("data-threadid"));
if (index > -1) ignoreThreadListArray.splice(index, 1);
}
if (isIgnoreTxt) {
let index = ignoreThreadListArray.indexOf(u(this).attr("data-threadtitle"));
if (index > -1) ignoreThreadListArray.splice(index, 1);
}
if (!isIgnoreNum && !isIgnoreTxt) {
// Ist nicht ignoriert. Ignorieren.
// (Titel, falls ohne ";", sonst ID.)
ignoreThreadListArray.push(u(this).attr("data-threadtitle").includes(";") ? u(this).attr("data-threadid") : u(this).attr("data-threadtitle"));
}
ThreadIgnoreList = ignoreThreadListArray.join(";");
GM.setValue("threadIgnoreList", ThreadIgnoreList);
// UI aktualisieren:
document.getElementById("wdeThreadIgnoreList").value = ThreadIgnoreList;
// (Ent-)Ignorieren-Menü neu aufbauen:
addThreadIgnoreMenu(true);
});
}
}
}
function outputWIDStyle() {
// Gibt den Ausgabetext für die Regexersetzung von WIDs zurück.
let ersetzen = '';
switch (ConvertWIDStyle) {
case 1:
// Nur "[WB]":
ersetzen = "[WB]";
break;
case 2:
// Nur "[(WID)]":
ersetzen = "[$3]";
break;
case 3:
// "[WB: (WID)]":
ersetzen = "[WB: $3]";
break;
}
return ersetzen;
}
function processPage() {
// Hinweis: Firefox kann kein negatives Lookbehind und wird sich beklagen, wenn man es versucht.
// Wir müssen hier daher die einfachere Variante nehmen. Da die Forensoftware manchmal &nbsp;
// und/oder irgendwelche HTML-Tags einfügt, müssen wir das natürlich auch entfernen.
const widregex = /WB?ID([:\s]|(&nbsp;|<\S*?>|<span (?:data-sheets-formula-bar-text-)?style="[^"]*">))+(\d+)(?:<\/span>)?/g;
// Selektor für Themenliste (Forum):
const threadListNormal = u("ul.DataList.Discussions div li.ItemDiscussion");
// Selektor für Themenliste (Neueste Beiträge):
const threadListRecent = u("div.vanilla-latest-comments ul.DataList.MessageList li.Item");
// Selektor für Beitragsinhalte:
const allPostTexts = u(".MessageList .Item .clearfix .right-block .Item-BodyWrap .Item-Body");
allPostTexts.each(function(node, i) {
if (u(node).hasClass("wdeplusprocd")) {
// Bereits verarbeitet.
return;
}
const beitragsDiv = u(node).parent().parent().parent();
// Beiträge ignorierter Benutzer ausblenden:
const ignoreUserListArray = UserIgnoreList.split(";").map(s => s.trim());
const postUser = u(beitragsDiv).find("a.Username").html();
if (ignoreUserListArray.length > 0 && ignoreUserListArray.includes(postUser)) {
// Dieser Beitrag kann weg.
if (UserIgnoreDelete) {
u(beitragsDiv).parent().remove();
}
else {
u(beitragsDiv).replace("<div>Ignorierter Beitrag von " + postUser + ".</div>");
}
}
else if (postUser == "WithKeys") {
u(beitragsDiv).find("span.RoleTitle").html("Mäzen");
}
// WIDs konvertieren:
if (ConvertWIDs) {
// Alle Links zu WIDs, die die Forensoftware bereits eingebaut hat, wieder entfernen:
const allLinksInNode = u(node).find("a");
allLinksInNode.each(function(anchor, i) {
const href = u(anchor).attr("href");
const innerText = u(anchor).html();
if (href != null && href.match(/:WID:/) != null) {
u(anchor).replace(innerText);
}
});
const origHtml = u(node).html();
const ersetzen = outputWIDStyle();
const newHtml = origHtml.replace(widregex, '<a href="https://www.whiskybase.com/whiskies/whisky/$3" target="_blank" title="Whisky $3 in der Base">' + ersetzen + '</a>');
u(node).html(newHtml);
}
u(node).addClass("wdeplusprocd");
});
// Selektor für PN-Inhalte:
const allPMTexts = u(".MessageList .Item .ConversationMessage .Message .Wysiwyg-Content");
allPMTexts.each(function(node, i) {
if (u(node).hasClass("wdeplusprocd")) {
// Bereits verarbeitet.
return;
}
// WIDs konvertieren:
if (ConvertWIDs) {
// Alle Links zu WIDs, die die Forensoftware bereits eingebaut hat, wieder entfernen:
const allLinksInNode = u(node).find("a");
allLinksInNode.each(function(anchor, i) {
const href = u(anchor).attr("href");
const innerText = u(anchor).html();
if (href != null && href.match(/:WID:/) != null) {
u(anchor).replace(innerText);
}
});
const origHtml = u(node).html();
const ersetzen = outputWIDStyle();
const newHtml = origHtml.replace(widregex, '<a href="https://www.whiskybase.com/whiskies/whisky/$3" target="_blank" title="Whisky $3 in der Base">' + ersetzen + '</a>');
u(node).html(newHtml);
}
u(node).addClass("wdeplusprocd");
});
// Ignorierte Themen ausblenden:
const ignoreThreadListArray = ThreadIgnoreList.split(";").map(s => s.trim());
if (ignoreThreadListArray.length > 0) {
if (threadListNormal != null) {
// Themenliste. Hier können IDs und Titel entfernt werden.
threadListNormal.each(function(node, i) {
// Nummerische IDs:
const discussionId = u(node).attr("id");
const numericalId = discussionId.replace("Discussion_", "");
if (ignoreThreadListArray.includes(numericalId)) {
// Gefunden. Ganzen Eintrag entfernen.
u(node).remove();
return;
}
// Titel:
const titel = u(node).find("div.Title a").html();
if (ignoreThreadListArray.includes(titel)) {
// Gefunden. Ganzen Eintrag entfernen.
u(node).remove();
return;
}
});
}
if (threadListRecent != null) {
// Beitragsliste. Hier funktionieren nur Titel.
threadListRecent.each(function(node, i) {
const titel = u(node).find(".MItem b a").html();
if (ignoreThreadListArray.includes(titel)) {
// Gefunden. Ganzen Eintrag entfernen.
u(node).remove();
return;
}
});
}
}
if (UncropQuotes == 1) {
// "cropped" aus Zitaten entfernen (nervt nur unnötig):
u("blockquote").removeClass("cropped");
// Zitate in Zitaten entfernen (braucht keiner):
u("blockquote div blockquote").remove();
}
else {
// Bugfix: Dieses Script macht Ausklappen von Zitaten kaputt.
u("blockquote").on("click", function(e) {
e.preventDefault();
u(this).removeClass("cropped");
});
}
if (HideCounter == 1) {
// Beitragszähler ausblenden:
u("span.AuthorInfo span.PostCount").remove();
// Federn usw. auch:
u("span.AuthorInfo span.Rank:not(.TasteRatingIcon)").remove();
}
// Extrasmileys einfügen. Das muss auch beim Hinzufügen neuer Nodes passieren, weil das
// Editierfenster von Beiträgen in diesen immer inline aufgeht. Blöd!
addWDEPlusSmileys();
// Ignoriermenü einfügen.
addThreadIgnoreMenu(false);
// Signatureinklappung reparieren:
if (DontCollapseSignatures == 1) {
u(".UserSignature").removeClass("UserSignatureCollapsed");
u(".userSignatureExpandCollapseButtons").remove();
}
else {
u(".userSignatureExpandButton, .userSignatureCollapseButton").each(function(node, i) {
if (u(node).hasClass("wdeplusprocd")) {
// Bereits verarbeitet.
return;
}
u(node).off("click").on("click", function() {
let thisSignature = u(this).parent().parent().find(".UserSignature");
// Funktionsweise des Ein- und Ausklappens wiederherstellen:
u(thisSignature).toggleClass("UserSignatureCollapsed");
// Beschriftung reparieren:
u(node).html(u(thisSignature).hasClass("UserSignatureCollapsed") ? "Signatur ausklappen" : "Signatur einklappen");
});
// Rechtschreibung der Umschaltschaltfläche verbessern:
u(node).html("Signatur ausklappen");
u(node).addClass("wdeplusprocd");
});
}
if (!u(pagewrapper).hasClass("wdeplusprocd")) {
// Die Seite wurde noch nicht angepasst.
// Dumme Reklame wegmachen:
u("#banners-top").remove();
if (PinHeader == 1) {
// Kopfzeile anheften:
u(".container-fluid").attr("style", "position: fixed; z-index: 100; background-color: antiquewhite;");
// Bei angehefteter Kopfzeile würden Popups verdeckt. Korrigieren:
u(".Popup").attr("style", "z-index: 200;");
// Seitenauswahl und Foreninhalt müssen weiter unten beginnen:
u("#Body").attr("style", "margin-top: 170px");
if (u(".datamints-infinite-scroll-pagination") != null) {
// "Unendliches" Scrollen ist aktiv. Da ohnehin angeheftet, können wir hier weniger
// "Platz" oben annehmen:
u(".datamints-infinite-scroll-pagination").attr("style", "margin-top: 110px");
}
// Hochscrollen, da die Seite in schlechten Browsern (Firefox) jetzt
// automatisch runtergescrollt wurde, falls wir uns in einer Forenliste
// (/forum/categories/) befinden:
if (window.location.pathname.includes("/forum/categories/")) {
window.scrollTo(0, 0);
}
}
// Seitenleisten sind nur auf dem Desktop relevant.
if (!isSmallMobileDevice) {
// Seitenleiste(n) ausblenden:
if (DisableLeftSidebar == 1 && u("#sidebar-left") != null) {
u("#sidebar-left").remove();
}
if (DisableRightSidebar == 1 && u("#sidebar-right") != null) {
u("#sidebar-right").remove();
}
// Breite anpassen, falls Seitenleiste(n) ausgeblendet:
if (DisableRightSidebar == 1 || DisableLeftSidebar == 1) {
wdeResize();
}
}
// Als "verarbeitet" kennzeichnen:
u(pagewrapper).addClass("wdeplusprocd");
}
}
// Falls "Infinite Scroll" deaktiviert ist, greift der MutationObserver nicht.
// Initial muss processPage() daher wenigstens einmal aufgerufen werden.
processPage();
// -------- Beim Größenändern des Fensters Elemente anpassen:
function wdeResize() {
// Beim Größenändern werden auch Seitenleisten u.U. unterschiedlich breit:
if (u("#sidebar-left").length > 0) {
sidebar_links = window.matchMedia("(max-width: 800px)").matches ? 0 : u("#sidebar-left").size().width;
}
if (u("#sidebar-right").length > 0) {
sidebar_rechts = window.matchMedia("(max-width: 800px)").matches ? 0 : u("#sidebar-right").size().width;
}
let breiteMitte = u("#Body .wrapper").size().width - sidebar_links - sidebar_rechts;
// Anpassen der Breite an die Existenz der Seitenleisten:
if (DisableLeftSidebar == 1 && u("#sidebar-left").length == 0) {
// Linke Seitenleiste weg - Mitte verbreitern:
breiteMitte += sidebar_links;
}
if (DisableRightSidebar == 1 && u("#sidebar-right").length == 0) {
// Rechte Seitenleiste weg - Mitte verbreitern:
breiteMitte += sidebar_rechts;
}
u(pagewrapper).attr("style", "width:" + breiteMitte + "px");
// Auch das "antworten"-Element darf breiter sein:
const antwortenForm = u(".MessageForm.fixed").first();
if (antwortenForm != null) {
let antwortenStyle = "";
if (DisableLeftSidebar == 0) {
antwortenStyle += "margin-left:0px;";
antwortenStyle += "left:" + sidebar_links + "px;";
}
antwortenStyle += "max-width:" + breiteMitte + "px;";
antwortenStyle += "width:" + breiteMitte + "px;";
u(antwortenForm).attr("style", antwortenStyle);
}
}
if (!isSmallMobileDevice && (DisableRightSidebar == 1 || DisableLeftSidebar == 1)) {
// Eine Größenänderung ist nur bei Seitenleistenausblendung sinnvoll.
window.addEventListener("resize", wdeResize);
}
// -------- CSS:
GM.addStyle(" \
.navigation-realms > ul > li.wde > a:before { \
/* Stern fürs Einstellungsmenü */ \
content: '\\f19a'; \
} \
\
.MessageList.Comments .Pocket { \
/* Keine Reklame zwischen den Beiträgen */ \
display: none; \
} \
\
#wdeplusSettingsCtr { \
position: fixed; \
padding: 2em; \
background: #FFF2E1; \
border: 3px double black; \
border-radius: 1ex; \
z-index: 999; \
width: 614px; \
height: 600px; \
} \
\
#wdeplusSettingsCtr.wdeSmall { \
padding: 12px; \
width: 100%; \
height: auto; \
top: 100px; \
left: 0px; \
} \
\
#wdeplusSettingsCtr:not(.wdeSmall) { \
/* Zentrieren, wenn Bildschirm groß genug: */ \
top: 50%; \
left: 50%; \
margin-top: -262px; \
margin-left: -307px; \
} \
\
#wdeplusSettingsCtr:not(.visible) { \
/* Der Dialog ist immer da, nur manchmal versteckt. */ \
display: none; \
} \
\
#wdeplusSettingsCtr form label { \
font-weight: normal; \
padding-top: 4px; \
} \
\
#wdeplusSettingsCtr form button { \
border: 1px solid black; \
} \
\
#wdeSaveBtn { \
background-color: lightgreen; \
} \
\
#wdeCloseBtn { \
background-color: #fcaca4; \
} \
\
.wdeplusHdr { \
font-size: 18px; \
font-weight: bold; \
margin-bottom: 18px; \
} \
\
.wdeplusHdr.wdeSmall { \
margin-bottom: 8px; \
} \
\
.wdeplusHint { \
font-size: 12px; \
margin-top: 20px; \
} \
\
.FormWrapper-Condensed { \
/* Antworten-Formular mit sichtbarem Rand. \
Sieht sonst scheiße aus. */ \
border: 1px solid #CF4D3B; \
} \
\
div.consent { \
/* Cookiezustimmungsnervbalken wegmachen. \
Achtung: Euer Browser sollte natürlich trotzdem so \
eingestellt sein, dass er nicht alle Werbecookies \
ungefragt übernimmt. (Viele moderne Browser sind das \
sowieso, geprüft in Safari und Vivaldi.) */ \
display: none; \
} \
\
@media (max-width: 799px) { \
/* Korrektur: Mit dem zusätzlichen Button ist die Buttonleiste \
oben auf kleinen Bildschirmen zu breit. Mach'se schmaler. */ \
.navigation-realms > ul > li.current { \
width: 20%; \
} \
\
/* Auch die Buttonbeschriftung stört da eher. */ \
.navigation-realms > ul > li.current > a > span { \
display: none; \
} \
} \
");
if (PinHeader == 1) {
// Bei angehefteter Kopfzeile verschwinden sonst die Dialoge.
GM.addStyle(".modal { padding-top: 170px; }");
}
Version 1.0 2020-02-11
* Erste Version.
Version 1.1 2020-02-11
* Die Änderung der Fenstergröße wird jetzt behandelt.
* Das Ausklappen von Zitaten ging nicht mehr.
* Option eingebaut, um Zitate automatisch auszuklappen.
* Zitate in Zitaten werden jetzt auf Wunsch automatisch entfernt.
* Das manuelle Ausklappen geht wieder.
* Der WID-Umwandler funktioniert jetzt auch bei falscher Syntax etwas weniger schlecht.
Version 1.2 2020-02-11
* Weitere Hilfetexte im Einstellungsdialog eingefügt.
* Blacklist für Threads eingefügt: Versteckt Themen anhand ihrer IDs.
* Vergessenen Debuglogeintrag entfernt.
Version 1.3 2020-02-11
* Größenänderungen werden nur noch bei ausgeblendeten Seitenleisten vorgenommen.
Version 1.4 2020-02-12
* Fehlerkorrektur für Firefox: Der reguläre Ausdruck für WIDs wurde vereinfacht.
Version 1.5 2020-02-13
* Das Script läuft jetzt auch im "Treffpunkt".
* WDE++ kann sich bei Updates jetzt selbst aktualisieren.
* Unter "Neueste Beiträge" funktionierte das Ignorieren von Thread-IDs nicht.
* Alternativ können jetzt auch Threadtitel angegeben werden.
* Wenn ID und Titel desselben Threads angegeben werden, funktioniert es trotzdem.
* Verschönerung: Das Antworten-Formular hat nur noch in seiner Aufpoppvariante einen Rahmen.
Version 1.6 2020-02-13
*** Testupdate für die automatische Aktualisierung, nicht separat veröffentlicht.
* Verschiedene Verbesserungen am Design des Einstellungsdialogs.
Version 1.7 2020-02-14
* Verbesserungen für die WID-Erkennung.
* Automatisch eingefügte "denied:"-Links werden jetzt zuerst entfernt.
* Manchmal gab es &nbsp; in einer WID. Das wird jetzt korrekt weggefiltert.
* JPG, PNG und GIF werden nicht mehr fälschlich als Seite des Forums behandelt.
Version 1.8 2020-02-25
*** Nicht separat veröffentlicht.
* Verlinkte WIDs werden jetzt auch als Nummer angezeigt.
* Code ein wenig aufgeräumt.
Version 1.9 2020-02-26
* Der Anzeigestil von WIDs kann jetzt geändert werden.
* Mit Zahl, ohne Zahl oder nur die Zahl.
* Der Kopfbereich des Forums kann jetzt angeheftet werden.
* Der Einstellungsdialog wurde etwas farbenfroher gestaltet.
* Mehr reguläre Ausdrücke für weniger include-Regeln.
Version 2.0 2020-02-26
* Der Einstellungsdialog wird jetzt in der Mitte des Bildschirms geöffnet.
Version 2.1 2020-02-27
* Eventuell war der blöde Reklamebanner oben im Weg. Er wird jetzt ausgeblendet, sofern
die Kopfzeile angeheftet wird.
Version 2.2 2020-03-03
*** Nicht separat veröffentlicht.
* Manchmal hat die Forensoftware HTML-Tags in WIDs reingemacht. Diese werden jetzt gefunden
und gelöscht.
Version 2.3 2020-03-31
* WIDs in Dateinamen sollten jetzt kein Problem mehr darstellen.
* WB-Links jetzt mit "www".
Version 2.4 2020-04-09
*** Nicht separat veröffentlicht.
* Das Antworten-Formular wurde manchmal nicht richtig angezeigt. Jetzt vielleicht doch.
Version 2.5 2020-04-14
* Fehlerbehebungen für Firefox bei angeheftetem Kopfbereich:
* Firefox hat immer runtergescrollt. Es wird jetzt automatisch wieder hochgescrollt.
* Anpassung der Navigation bei ausgewähltem "unendlichem" Scrollen.
Version 2.6 2020-06-17
* Das Hochscrollen (siehe Version 2.5) passiert jetzt nur noch in der Themenliste.
* Bei angeheftetem Kopfbereich wurden Popups verdeckt. Korrigiert.
* Der Einstellungsdialog kann jetzt mit "<Esc>" geschlossen werden.
Version 2.7 2020-06-19
*** Nicht separat veröffentlicht.
* Der Einstellungsdialog zeigt jetzt auch die Versionsnummer des Scripts an.
Version 2.8 2020-06-24
*** Das Veröffentlichen separater ZIP-Dateien wurde eingestellt. Es wird jetzt
nur noch die Installation über die Scriptdatei von GitHub unterstützt!
* Das Öffnen des Einstellungsdialogs springt nicht mehr auf der Seite umher.
* Der Einstellungsknopf benutzt jetzt das "Dauertiefpreis"- anstelle des Info-Symbols.
Version 2.9 2020-11-02
* Reguläre Ausdrücke vereinfacht: Das Script wird nur noch auf der www-Subdomain
aktiviert.
* Zwischen Beiträgen tauchte manchmal ein Werbebanner auf. Der sollte jetzt nicht
mehr da sein.
Version 3.0 2020-11-09
* Lizenzheader eingefügt (weil ich's kann).
* Layout der Buttonleiste auf kleinen Bildschirmen verbessert.
* Smartphonenutzer haben jetzt einen neuen, kleineren Einstellungsdialog.
* Der Einstellungsdialog wird erst freigegeben, wenn die Seite geladen ist. Das
sollte das "Flackern" beim Aufruf beheben.
* Bugfix: Breitenberechnung auf Smartphones deaktiviert.
Version 3.1 2020-11-09
* Firefox ignorierte das "load"-Event manchmal. WDE++ wird daher nun per run-at-
Direktive nach dem Laden der Seite ausgeführt.
Version 3.2 2021-01-16
* Die WID-Stilauswahl wird jetzt ausgegraut, wenn die Umwandlung nicht gewünscht
ist.
Version 3.3 2021-01-20
* Code besser dokumentiert sowie im Forum angekündigtes Easter Egg platziert.
Version 3.4 2021-01-26
* Die Ermittlung der WID-Anzeige wurde in eine eigene Funktion ausgelagert.
* WIDs werden jetzt auch in privaten Nachrichten umgewandelt.
Version 3.5 2021-01-27
* Easter Egg wieder entfernt.
* Es gab eine unnötige Logmeldung beim Größeändern des Browserfensters. Jetzt
gibt es sie nicht mehr.
Version 3.6 2021-01-29
* Die Ignorierlisten werden jetzt getrim()t, Leerzeichen vor/nach den trennenden
Semikola sollten somit weniger Probleme bereiten.
Version 3.7 2021-01-31
* Die WID-Stileinstellungen sind jetzt auch auf mobilen Geräten sichtbar.
Version 3.8 2021-02-03
* Fehler im regulären Ausdruck behoben: Das Wort WID konnte dazu führen, dass
ganze Absätze ersetzt (visuell gelöscht) wurden, wenn nach ihm eine neue Zeile
begonnen wurde.
* Die Reklame am oberen Bildrand sieht jetzt auch mit angeheftetem Kopfbereich
nicht mehr blöd aus, denn sie wird dann entfernt.
Version 3.9 2021-02-10
* WIDs konnten noch nicht erkannte span-Tags enthalten. Korrigiert.
Version 4.0 2021-03-13
* Es sind nun ein Affen- und ein Schulternzuck-Emoji als Bilder einfügbar.
Damit ist es theoretisch auch möglich, künftig beliebige Emojis hinzuzufügen,
sofern diese als Bilddateien online vorliegen.
Version 4.1 2021-03-26
* Der Cookiebanner am unteren Bildrand wird automatisch weggemacht.
Version 4.2 2021-04-26
* WID-Links funktionieren jetzt auch mit dem Präfix "WBID".
Version 4.3 2021-04-29
* Code für die Ermittlung zu ignorierender Beiträge etwas vereinfacht.
* Es wurde eine Änderung an angezeigten Benutzertiteln vorgenommen.
Version 4.4 2021-05-04
* Der Code für die Smartphoneerkennung war zwar funktional, aber nicht
ganz logisch. Korrigiert.
Version 4.5 2021-06-15
* Die Änderung der Fenstergröße (horizontal und/oder vertikal) konnte
zu Darstellungsfehlern des "Antworten"-Formulars führen. Korrigiert.
* Ignorieren und Entignorieren von Threads ist jetzt über das Zahnrad-
menü oben rechts möglich.
Version 4.6 2021-06-16
* Der Werbebanner oben wird jetzt auch ohne angehefteten Kopfbereich
entfernt.
* Eine Änderung am Forendesign hat WDE++ außer Gefecht gesetzt. Das
Gefecht wurde wieder aufgenommen.
* Die Suchleiste in der Seitenleiste existiert nicht mehr. Der Code,
um sie zu verschieben, wurde daher entfernt.
* Die Änderung der Fenstergröße (horizontal und/oder vertikal) konnte
immer noch zu Darstellungsfehlern führen. Korrigiert.
Version 4.7 2021-06-27
* Beiträge ignorierter Benutzer können jetzt auch vollständig entfernt
werden.
Version 4.8 2021-09-03
* Der Beitragszähler kann jetzt ausgeblendet werden.
Version 4.9 2021-10-28
* Umstellung auf GM.*-APIs: Greasemonkey sollte jetzt zusätzlich zu den
bisher unterstützten Erweiterungen Tampermonkey und Violentmonkey
funktionieren.
Version 5.0 2021-11-24
* Der kaputte Signatureinklapper vom Forum wurde erst mal rausoperiert.
Version 5.1 2021-11-26
* Lizenz von CDDL 1.0 auf CDDL 1.1 umgestellt (vermeidet Unklarheiten in
der EU).
* Der kaputte Signatureinklapper vom Forum wurde repariert.
Version 5.2 2021-11-30
* Der Signatureinklapper ist jetzt abschaltbar.
Version 5.3 2021-02-12
* Anpassungen an die neue Version von Whisky.woff2.
Version 5.4 2023-02-06
* Anpassungen an die neue Version von Whisky.woff2.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment