Die Frage von old-smokey nach einer individuellen Filterung für den Newsfeed hat mich inspiriert, mich an den Code zu setzen und eine maßgeschneiderte Lösung zu entwickeln. Da Xobor eine solche Filterung serverseitig pro Nutzer nicht anbietet, habe ich ein clientseitiges JavaScript-Plugin geschrieben, das genau diese Lücke schließt – und zwar für alle Xobor-Generationen von V1 bis V6 inklusive des Business v4 Templates.
💡 Meine Idee & Die technischen Anpassungen (Fokus: Server-Schonung)
Bei der Entwicklung stand neben der Usability vor allem die Performance im Vordergrund. Deshalb habe ich an folgende Punkte gedacht:
* 0% Serverlast: Die gesamte Filterung und Speicherung läuft rein clientseitig (im Browser des jeweiligen Nutzers). Der Foren-Server wird mit keinem einzigen Byte zusätzlich belastet.
* Intelligenter Intervall-Filter: Da Xobor die Feeds asynchron via Ajax nachlädt, läuft im Hintergrund ein ressourcenschonender 3-Sekunden-Takt. Dieser prüft blitzschnell nur neu hinzugekommene Einträge. Das verbraucht weder spürbare CPU-Leistung noch Akku auf Mobilgeräten.
* Dynamische Text-Erkennung (ISO/UTF-8 sicher): Das Skript liest die Kategorienamen dynamisch über textContent.trim() aus. Es gibt keine hartcodierten Sonderzeichen im Code, was Zeichensatz-Konflikte in älteren Foren-Generationen komplett ausschließt.
* Dauerhafter Browserspeicher: Die ausgeblendeten Bereiche werden im localStorage des Nutzers abgelegt. Die Filterung bleibt auch nach Tagen und Browser-Neustarts aktiv, bis der User sie wieder umschaltet. Andere Forenmitglieder sehen davon absolut nichts.
* Design-Neutralität: Über currentColor und inherit passt sich der Button ([ FEED ON ] / [ MUTE ]) automatisch an euer v4- oder v6-Design (Farben, Schriftart, Abstände) an.
🛠️ Einbau-Anleitung für das Admin-Menü:
1. Gehe zu Plugins -> Plugin-Entwicklung. 2. Klicke auf "Neues Plugin erstellen" (Name z. B.: „Individueller Activity Feed Filter“). 3. Erstelle ein neues Template Element. 4. Wähle die Platzierung Untere Leiste / Header (bottom_header). 5. Kopiere den folgenden Code hinein, speichere ihn ab.
Habe es Enricos gegeben und er hat es installiert und ist soweit zufrieden.
Hoffe, dass die Idee und Inspiration sehr gut ankommt. Du kannst es ja in deinem Testforum testen und mir sagen, ob ich an alles gedacht habe oder ob ich noch etwas vergessen habe.
Betreff: Re: Activity Feed (Individueller Filter für jeden User - V1-V6)
Hallo Wolfgang,
vielen Dank für dein schnelles Feedback! Ich habe mir die Sache sofort angeschaut und den Grund gefunden, warum es bei dir noch nicht lief.
Hier ist die Erklärung dazu: Ich hatte das erste Skript vorab als Spezial-Anfertigung direkt für Luis Bereich angepasst, während Xobor noch mit den Serverfehlern nach dem Umzug gekämpft hat. In diesem fehlerhaften Zustand lief mein extra angefertigter Code bei Lui im Forum perfekt.
Über Nacht hat Xobor dann aber die Serverfehler komplett bereinigt! Der Newsfeed läuft jetzt wieder im sauberen Standard-Zustand.
Das bedeutet: Der Satzbau im Feed enthält (wie bei dir im Test) nur noch Foren- und Themennamen, aber nicht mehr den Namen der Kategorie. Meine Spezial-Anfertigung lief dadurch auf einem sauberen System ins Leere.
Ich habe den Code daher komplett bereinigt und von Grund auf neu geschrieben (Version 15.6):
Das neue Skript ist jetzt eine universelle, unzerstörbare Lösung für V4 und V6.
Es verlässt sich nicht mehr auf den reinen Text, sondern nutzt eine dreistufige ID- und Text-Matrix: Beim Laden scannt es die unsichtbare Foren-Struktur der Startseite und merkt sich, welche Foren-ID zu welcher Kategorie gehört.
Beim Klick auf [ MUTE ] werden sowohl die ID als auch der Name im localStorage gesichert.
Die Filter-Engine liest die echten Xobor-SEO-Links (t15f24528-testt.html) im Feed aus, zieht sich die Foren-ID heraus und blendet den Eintrag blitzschnell aus – völlig egal, wie der Text formatiert ist.
Ich habe dir im Anhang Bilder angehängt, die dir zeigen, wie das Interface live läuft.
Auch einen Screenshot meines fehlerfreien Konsolen-Logs (ohne jegliche JavaScript-Fehler) habe ich beigefügt!
Bild in mute:
mit mute geklickt
Bild mit feed on:
mit feed on geklickt
Bild mit konsole auszug:
mit konsole auszug
Hier ist der neue, saubere Code für das Plugin (Untere Leiste / Footer
if (mutedFeeds.includes(associatedCatId) || mutedFeeds.includes(forumId)) { shouldHide = true; } }
// 2. Check, ob der Text eines Links (z. B. Foren-Name oder Thema) auf der Mute-Liste steht mutedFeeds.forEach(mutedValue => { const strMuted = String(mutedValue).toLowerCase(); if (linkTextLower.includes(strMuted) || href.toLowerCase().includes(strMuted)) { shouldHide = true; } }); });
// 3. Voller Text-Match Fallback (Sichert ab, wenn Namen im Feed-Satz stehen) mutedFeeds.forEach(mutedValue => { const strMuted = String(mutedValue).toLowerCase(); if (textContentLower.includes(strMuted)) { shouldHide = true; } });
let catIdentifier = null; if (box.id && box.id.match(/\d+/)) { catIdentifier = box.id.match(/\d+/)[0]; } else { const idMatch = catLink.href.match(/cat=(\d+)/) || catLink.href.match(/fcategory=(\d+)/); if (idMatch) catIdentifier = idMatch[1]; }
const catName = catLink.textContent.trim(); if (!catIdentifier) catIdentifier = catName;
// Prüfen, ob ID oder Name gemuted ist const isMuted = mutedFeeds.includes(catIdentifier) || mutedFeeds.includes(catName);
const eye = document.createElement('span'); eye.className = isMuted ? 'feed-toggle-eye muted' : 'feed-toggle-eye'; eye.textContent = isMuted ? '[ MUTE ]' : '[ FEED ON ]'; eye.title = isMuted ? `Feed für ${catName} wieder aktivieren` : `Feed für ${catName} ausblenden`;
eye.addEventListener('click', function(e) { e.preventDefault(); e.stopPropagation(); let currentMuted = getMutedFeeds();
if (currentMuted.includes(catIdentifier) || currentMuted.includes(catName)) { // Entmuten: Entferne ID und Name aus der Liste currentMuted = currentMuted.filter(name => name !== catIdentifier && name !== catName); this.textContent = '[ FEED ON ]'; this.className = 'feed-toggle-eye'; } else { // Muten: Speicher ID UND Name für doppelten Schutz ab! if (catIdentifier) currentMuted.push(catIdentifier); if (catName) currentMuted.push(catName); this.textContent = '[ MUTE ]'; this.className = 'feed-toggle-eye muted'; }
Mit dieser bereinigten Version klappt die Filterung jetzt unzerstörbar bei jedem Klick, da das Skript auf die echten Xobor-Verknüpfungen zugreift.
Deine Idee, die Ausblendung direkt an das Einklappen der Titelleiste auf der Startseite zu koppeln, ist übrigens genial – das baue ich gerade als zweites, alternatives Modul parallel auf! Lass mich wissen, was du zu der neuen Version sagst.
RE: Betreff: Newsfeed an das Zuklappen der Kategorien
Hallo Wolfgang Ich habe mir deine geniale Idee sofort zu Herzen genommen, mich direkt an den Rechner gesetzt und den Code komplett neu geschrieben!
Die Idee, den Newsfeed an das Zuklappen der Kategorien über die Titelleiste zu koppeln, ist technisch absolut genial. Ich habe das Skript v16.5 jetzt genau so aufgebaut, dass es im Hintergrund die echten Xobor SEO-IDs der geschlossenen Boxen ausliest.
Ich habe das Ganze gerade bei mir auf le-dernier-du-clan-loreth.xobor.de auf Herz und Nieren getestet und es funktioniert einwandfrei!
Ein wichtiger technischer Hinweis zum Ablauf:
Wenn man eine Kategorie über die Titelleiste einklappt, speichert Xobor diesen Zustand im Browser. Wenn der User die Seite dann aktualisiert (neu lädt), liest mein Skript diesen Zustand sofort aus, gleicht die IDs im 2,5-Sekunden-AJAX-Takt ab und die Einträge aus der zugeklappten Kategorie sind komplett aus dem Activity Feed verschwunden!
Wenn man sie wieder aufklappt und aktualisiert, ist alles wieder da.
Meintest du das genau so vom Ablauf her? Probiere die neue Version 16.5 bitte mal in deinem Testforum aus, ich bin super gespannt auf dein Feedback!
// Zuordnungs-Map: Welches Forum (f) gehört zu welcher Kategorie (cat)? const forumToCategoryMap = {};
// 1. STRUCTURE SCANNER: Baut die Datenbank der Foren-Zugehörigkeiten live auf function scanForumStructure() { document.querySelectorAll('.box.cat, [id^="cat_"], .forum_table, table.table_forum').forEach(box => { let catId = null; if (box.id && box.id.match(/\d+/)) { catId = box.id.match(/\d+/)[0]; } else { const catLink = box.querySelector('a[href*="cat="], a[href*="fcategory="]'); if (catLink) { const match = catLink.href.match(/cat=(\d+)/) || catLink.href.match(/fcategory=(\d+)/); if (match) catId = match[1]; } } if (!catId) return;
// Alle Foren-Links innerhalb dieser Kategorie-Box finden und verknüpfen box.querySelectorAll('a[href*="f="], a[href*="f"]').forEach(forumLink => { const href = forumLink.getAttribute('href') || ''; const forumIdMatch = href.match(/f=(\d+)/) || href.match(/\/f(\d+)/) || href.match(/f(\d+)/); if (forumIdMatch) { forumToCategoryMap[forumIdMatch[1]] = catId; } }); }); }
// 2. LIVE FILTER ENGINE: Synchronisiert den Feed mit den eingeklappten Boxen function syncFeedWithCollapsedCategories() { const closedCategoryIds = [];
// Verstecken, wenn die dazugehörige Kategorie eingeklappt ist! if (associatedCatId && closedCategoryIds.includes(associatedCatId)) { shouldHide = true; } } });
Hallo Wolfgang, vielen Dank für dein tolles Feedback und die Blumen!
Ich muss aber ganz ehrlich sagen:
Ich bin bei Weitem noch kein Profi und lerne selbst jeden Tag dazu. Ich bin noch voll am Üben und Versuchen, aber ich bemühe mich einfach immer, coole Ideen und Inspirationen so gut es geht in Code umzusetzen.
Dass du meine Logik aus den Vorversionen aufgegriffen hast und den Code jetzt so stark optimieren konntest, freut mich riesig. Genau aus diesem Grund teile ich meine Ansätze so gerne – damit man voneinander lernt und am Ende etwas richtig Gutes für alle dabei herauskommt.
Deine Lösung für das Event-System ohne die Intervall-Zeitschleife ist echt klasse geworden! Ich werde mir deine Skripte jetzt in Ruhe anschauen und weiter damit üben. Vielen Dank für die tolle Zusammenarbeit und die Unterstützung bei diesem Projekt!