Löscht datumslose Anzeigen. Filtert Profis. Button Pille. Farbe strikt #6a47b5. Anti-Flicker Logic.
当前为
// ==UserScript==
// @name Kleinanzeigen_01_Navigation Upgrade
// @namespace http://tampermonkey.net/
// @version 1.6
// @description Löscht datumslose Anzeigen. Filtert Profis. Button Pille. Farbe strikt #6a47b5. Anti-Flicker Logic.
// @author moritz & Gemini
// @icon https://www.google.com/s2/favicons?sz=64&domain=kleinanzeigen.de
// @match https://www.kleinanzeigen.de/*
// @run-at document-start
// @license MIT
// @grant none
// ==/UserScript==
(function() {
'use strict';
// =================================================================
// KONFIGURATION (DAS GESETZ)
// =================================================================
const CONFIG = {
btnHeight: '36px',
btnWidth: '190px',
colorHex: '#6a47b5', // Die einzige Farbe
colorRgb: '106, 71, 181', // RGB Werte für Transparenz
ghostOpacity: '0.2' // 20% Opazität
};
// =================================================================
// TEIL 0: Gedächtnis
// =================================================================
const storageKey = 'ka_show_pros_state';
const savedState = localStorage.getItem(storageKey) === 'true';
if (savedState) {
(document.body || document.documentElement).classList.add('ka-show-pro');
}
// =================================================================
// TEIL 1: CSS (Struktur V1.0 + Strict Colors)
// =================================================================
const cssStyles = `
/* 1. Globale Banner & Platzhalter weg */
.j-liberty-wrapper, #brws_banner-supersize, #btf-billboard,
#viewad-sidebar-banner, .site-base--left-banner, .site-base--right-banner {
display: none !important;
}
/* 2. PRO-Anzeigen ausblenden (Standard) */
li.ad-listitem.ka-pro-hidden {
display: none !important;
}
/* 3. Ghost-Mode Styles */
body.ka-show-pro li.ad-listitem.ka-pro-hidden {
display: list-item !important;
border: none !important;
margin-bottom: 10px !important;
padding: 0 !important;
}
/* Artikel: Farbe #6a47b5, Hintergrund 20% Opazität */
body.ka-show-pro li.ad-listitem.ka-pro-hidden article.aditem {
opacity: 1 !important;
background-color: rgba(${CONFIG.colorRgb}, ${CONFIG.ghostOpacity}) !important;
border: 1px solid ${CONFIG.colorHex} !important;
box-shadow: none !important;
border-radius: 4px !important;
}
/* Dashboard Container */
#ka-dashboard-container {
margin: 0 0 15px 0;
background: #fff;
border: 1px solid #d5d5d5;
padding: 12px 20px;
display: flex;
align-items: center;
justify-content: space-between;
font-family: "Martel Sans", sans-serif;
border-radius: 4px;
}
#ka-dashboard-text {
font-size: 14px;
color: #333;
font-weight: bold;
display: flex;
align-items: center;
gap: 5px;
}
/* Fake PRO Badge - Farbe #6a47b5 */
.ka-dashboard-badge {
background-color: ${CONFIG.colorHex};
color: #fff;
padding: 2px 6px;
font-size: 11px;
font-weight: bold;
border-radius: 3px;
line-height: 1;
display: inline-block;
}
/* BUTTON - Farbe #6a47b5 */
#ka-dashboard-btn {
background-color: ${CONFIG.colorHex} !important;
color: #ffffff !important;
border: none;
height: ${CONFIG.btnHeight};
width: ${CONFIG.btnWidth};
padding: 0;
font-size: 14px;
font-weight: bold;
/* Radius = Exakt die Höhe (Pille) */
border-radius: ${CONFIG.btnHeight} !important;
cursor: pointer;
display: flex !important;
align-items: center;
justify-content: center;
transition: filter 0.2s;
}
/* Hover: Gleiche Farbe, per Filter abgedunkelt */
#ka-dashboard-btn:hover {
background-color: ${CONFIG.colorHex} !important;
filter: brightness(0.85);
}
`;
const styleElement = document.createElement('style');
styleElement.type = 'text/css';
styleElement.appendChild(document.createTextNode(cssStyles));
(document.head || document.documentElement).appendChild(styleElement);
// =================================================================
// TEIL 2: Logik (Anti-Flicker)
// =================================================================
let validAdsCount = 0;
let proAdsCount = 0;
let isProcessing = false;
function cleanUp() {
if (isProcessing) return;
isProcessing = true;
const listItems = document.querySelectorAll('li.ad-listitem');
const resultList = document.getElementById('srchrslt-adtable');
let currentValid = 0;
let currentPro = 0;
// Array zum Sammeln der Profi-Zeilen für spätere Sortierung
const proRows = [];
listItems.forEach(li => {
// Platzhalter weg
if (li.querySelector('div[id^="srpb-result-list"]') || li.querySelector('.liberty-hide-unfilled')) {
li.remove();
return;
}
const ad = li.querySelector('article.aditem');
if (!ad) return;
// HARD DELETE (Kein Datum oder TOP)
const dateBox = ad.querySelector('.aditem-main--top--right');
const hasDate = dateBox && dateBox.innerText.trim().length > 0;
const isTopBadge = ad.querySelector('.aditem-image--badges--badge-topad') !== null;
const isTopClass = ad.classList.contains('is-topad');
if (!hasDate || isTopBadge || isTopClass) {
li.remove();
return;
}
// SOFT FILTER (Profis)
const isProBadge = ad.querySelector('.badge-hint-pro-small-srp') !== null;
const isProLink = ad.querySelector('a[href^="/pro/"]') !== null;
if (isProBadge || isProLink) {
li.classList.add('ka-pro-hidden');
currentPro++;
proRows.push(li); // In Liste sammeln, NICHT hier bewegen
} else {
li.classList.remove('ka-pro-hidden');
}
currentValid++;
});
// SORTIER-LOGIK MIT BREMSE (Verhindert Flackern)
if (resultList && proRows.length > 0) {
// Prüfung: Sind die Profis schon ganz oben?
let alreadySorted = true;
const children = resultList.children;
for (let i = 0; i < proRows.length; i++) {
if (children[i] !== proRows[i]) {
alreadySorted = false;
break;
}
}
// Nur bewegen, wenn noch nicht sortiert
if (!alreadySorted) {
const fragment = document.createDocumentFragment();
proRows.forEach(row => fragment.appendChild(row));
resultList.prepend(fragment);
}
}
if (currentValid !== validAdsCount || currentPro !== proAdsCount) {
validAdsCount = currentValid;
proAdsCount = currentPro;
updateDashboard();
}
setTimeout(() => { isProcessing = false; }, 50);
}
// =================================================================
// TEIL 3: Dashboard
// =================================================================
function initDashboard() {
const targetHeader = document.querySelector('.srp-header');
if (!targetHeader) return;
if (!document.getElementById('ka-dashboard-container')) {
const dashboard = document.createElement('div');
dashboard.id = 'ka-dashboard-container';
dashboard.innerHTML = `
<span id="ka-dashboard-text">...</span>
<button id="ka-dashboard-btn">Filter umschalten</button>
`;
targetHeader.parentNode.insertBefore(dashboard, targetHeader.nextSibling);
document.getElementById('ka-dashboard-btn').addEventListener('click', () => {
const isActive = document.body.classList.toggle('ka-show-pro');
localStorage.setItem(storageKey, isActive);
updateDashboard();
});
}
updateDashboard();
}
function updateDashboard() {
const textSpan = document.getElementById('ka-dashboard-text');
const btn = document.getElementById('ka-dashboard-btn');
if (!textSpan) return;
const isShowingPro = document.body.classList.contains('ka-show-pro');
const proBadgeHtml = `<span class="ka-dashboard-badge">PRO</span>`;
btn.style.display = 'flex';
if (isShowingPro) {
textSpan.innerHTML = `${validAdsCount} Anzeigen davon ${proAdsCount} ${proBadgeHtml}`;
btn.textContent = "Profis ausblenden";
} else {
if (proAdsCount > 0) {
textSpan.innerHTML = `${validAdsCount} Anzeigen davon ${proAdsCount} ${proBadgeHtml} ausgeblendet`;
btn.textContent = "Profis anzeigen";
} else {
textSpan.textContent = `${validAdsCount} Anzeigen (Keine Profis gefunden)`;
btn.textContent = "Profis anzeigen";
}
}
}
window.addEventListener('DOMContentLoaded', () => {
const observer = new MutationObserver(() => {
requestAnimationFrame(() => {
cleanUp();
initDashboard();
});
});
observer.observe(document.body, { childList: true, subtree: true });
});
// =================================================================
// TEIL 4: Navigation
// =================================================================
document.addEventListener('keydown', function(e) {
if (['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)) return;
if (e.key === 'ArrowLeft' || e.key === 'a') clickNav('.pagination-prev');
else if (e.key === 'ArrowRight' || e.key === 'd') clickNav('.pagination-next');
});
function clickNav(selector) {
const el = document.querySelector(selector);
if (el) {
if (el.href) el.click();
else if (el.getAttribute('data-url')) window.location.href = el.getAttribute('data-url');
}
}
if (window.location.href === 'https://www.kleinanzeigen.de/') {
const int = setInterval(() => {
const btn = document.querySelector('.button-secondary.j-feed-show-more');
if (btn) btn.click();
}, 1000);
setTimeout(() => clearInterval(int), 5000);
}
})();