// ==UserScript== // @name Jasbee Gebäude-Prozentanzeige // @namespace http://tampermonkey.net/ // @version 3.2 // @description Erlaubt das Scannen aller Gebäude im Hintergrund per Klick auf city.php (Mit optischen CSS-Fixes) // @author Daniel + Gemini // @match https://www.jasbee.de/module/* // @grant none // ==/UserScript== (function() { 'use strict'; // Liste der erlaubten Dateinamen const allowedPages = [ 'city.php', 'lager.php', 'baumarkt.php', 'sportsbar.php', 'aliengeb.php', 'sauna.php', 'haus.php', 'fussball.php', 'schwimmhalle.php', 'fabrik.php', 'fitness.php', 'bazar.php' ]; const currentPath = window.location.pathname; const currentPage = currentPath.substring(currentPath.lastIndexOf('/') + 1).toLowerCase(); if (!allowedPages.includes(currentPage)) { return; } // 1. Popup-Element erstellen und stylen const popup = document.createElement('div'); popup.id = 'gebaeude-prozent-popup'; popup.style.position = 'fixed'; popup.style.top = '10px'; popup.style.right = '10px'; popup.style.backgroundColor = 'rgba(20, 20, 20, 0.95)'; popup.style.color = '#fff'; popup.style.padding = '15px'; popup.style.borderRadius = '8px'; popup.style.boxShadow = '0 4px 15px rgba(0,0,0,0.6)'; popup.style.zIndex = '2147483647'; popup.style.fontFamily = 'Segoe UI, Arial, sans-serif'; popup.style.fontSize = '13px'; popup.style.maxHeight = '400px'; popup.style.overflowY = 'auto'; popup.style.minWidth = '290px'; popup.style.border = '1px solid #444'; popup.style.userSelect = 'none'; popup.innerHTML = ` `; document.body.appendChild(popup); // Scan-Button nur auf city.php einblenden const scanBtn = document.getElementById('scan-jasbee-buildings'); if (currentPage === 'city.php') { scanBtn.style.display = 'inline-block'; } // Drag-and-Drop Steuerung const header = document.getElementById('popup-header'); let isDragging = false; let currentX, currentY, initialX, initialY; let xOffset = 0, yOffset = 0; const savedPos = localStorage.getItem('jasbee_popup_pos'); if (savedPos) { const pos = JSON.parse(savedPos); popup.style.transform = `translate3d(${pos.x}px, ${pos.y}px, 0)`; xOffset = pos.x; yOffset = pos.y; } header.addEventListener('mousedown', (e) => { if (e.target === header) { initialX = e.clientX - xOffset; initialY = e.clientY - yOffset; isDragging = true; } }); document.addEventListener('mousemove', (e) => { if (isDragging) { e.preventDefault(); currentX = e.clientX - initialX; currentY = e.clientY - initialY; xOffset = currentX; yOffset = currentY; popup.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`; } }); document.addEventListener('mouseup', () => { if (isDragging) { isDragging = false; localStorage.setItem('jasbee_popup_pos', JSON.stringify({x: currentX, y: currentY})); } }); document.getElementById('clear-jasbee-data').addEventListener('click', () => { if (confirm('Möchtest du alle gespeicherten Zustandswerte löschen?')) { localStorage.removeItem('jasbee_building_data'); updateBuildingStatus(); } }); scanBtn.addEventListener('click', startBackgroundScan); function getStoredData() { const data = localStorage.getItem('jasbee_building_data'); return data ? JSON.parse(data) : {}; } function saveStoredData(data) { localStorage.setItem('jasbee_building_data', JSON.stringify(data)); } // Hintergrund-Scanner Funktion function startBackgroundScan() { const links = Array.from(document.querySelectorAll('a[href]')); const targets = []; links.forEach(link => { const href = link.getAttribute('href'); allowedPages.forEach(page => { if (page !== 'city.php' && href.includes(page) && !targets.includes(href)) { targets.push(href); } }); }); if (targets.length === 0) { alert('Keine Gebäude-Links auf der Seite gefunden!'); return; } scanBtn.disabled = true; scanBtn.style.background = '#555'; let index = 0; const iframe = document.createElement('iframe'); iframe.style.display = 'none'; document.body.appendChild(iframe); function loadNext() { if (index >= targets.length) { document.body.removeChild(iframe); scanBtn.disabled = false; scanBtn.style.background = '#ff9800'; scanBtn.innerText = 'Alle scannen'; updateBuildingStatus(); return; } scanBtn.innerText = `Scan ${index + 1}/${targets.length}`; iframe.src = targets[index]; index++; } iframe.addEventListener('load', () => { try { const doc = iframe.contentDocument || iframe.contentWindow.document; let buildingName = ''; const breadcrumbItems = doc.querySelectorAll('.breadcrumb li'); if (breadcrumbItems.length > 0) { buildingName = breadcrumbItems[breadcrumbItems.length - 1].textContent.trim().replace(/[\t\r\n]/g, ''); } const percentElements = doc.querySelectorAll('.pie-number'); let stateValue = ''; for (let el of percentElements) { const txt = el.textContent.trim(); if (txt.includes('%')) { const parentCard = el.closest('.card'); if (parentCard) { const cardHeader = parentCard.querySelector('h3'); if (cardHeader && cardHeader.textContent.trim() === 'Gebäudezustand') { stateValue = txt; break; } } } } if (buildingName && stateValue) { let currentStorage = getStoredData(); // Wir speichern Zustand und die genaue URL als Objekt ab currentStorage[buildingName] = { value: stateValue, url: iframe.src }; saveStoredData(currentStorage); updateBuildingStatus(); } } catch (e) { console.error("Fehler beim Auslesen des Iframes:", e); } setTimeout(loadNext, 500); }); loadNext(); } // Hauptfunktion zur Anzeige function updateBuildingStatus() { const contentDiv = document.getElementById('popup-content'); let currentStorage = getStoredData(); let hasNewData = false; let buildingName = ''; const breadcrumbItems = document.querySelectorAll('.breadcrumb li'); if (breadcrumbItems.length > 0) { buildingName = breadcrumbItems[breadcrumbItems.length - 1].textContent.trim().replace(/[\t\r\n]/g, ''); } const percentElements = document.querySelectorAll('.pie-number'); if (buildingName && buildingName.toLowerCase() !== 'city' && percentElements.length > 0) { let stateValue = ''; for (let el of percentElements) { const txt = el.textContent.trim(); if (txt.includes('%')) { const parentCard = el.closest('.card'); if (parentCard) { const cardHeader = parentCard.querySelector('h3'); if (cardHeader && cardHeader.textContent.trim() === 'Gebäudezustand') { stateValue = txt; break; } } } } if (stateValue) { // Abwärtskompatibilität prüfen (falls alte Datenstruktur ohne .value existiert) const oldVal = (typeof currentStorage[buildingName] === 'object') ? currentStorage[buildingName].value : currentStorage[buildingName]; if (oldVal !== stateValue) { currentStorage[buildingName] = { value: stateValue, url: window.location.href }; hasNewData = true; } } } if (hasNewData) { saveStoredData(currentStorage); } let buildingList = []; for (let name in currentStorage) { const entry = currentStorage[name]; // Abwärtskompatibler Check für die Datenstruktur const val = (typeof entry === 'object') ? entry.value : entry; const url = (typeof entry === 'object') ? entry.url : ''; buildingList.push({ name: name, value: val, url: url, numeric: parseFloat(val) || 0 }); } if (buildingList.length === 0) { contentDiv.innerHTML = 'Noch keine Zustände erfasst. Klicke auf "Alle scannen" oder besuche deine Gebäude.'; } else { buildingList.sort((a, b) => a.numeric - b.numeric); let html = ''; buildingList.forEach(item => { let color = '#4caf50'; if (item.numeric < 50) color = '#f44336'; else if (item.numeric < 90) color = '#ffeb3b'; const isCurrent = (item.name === buildingName) ? 'background-color: rgba(255,255,255,0.08); font-style: italic;' : ''; // Falls eine URL vorhanden ist, betten wir den Namen in einen Link ein const nameDisplay = item.url ? `${item.name}` : item.name; html += ``; }); html += '
${nameDisplay} ${item.value}
'; contentDiv.innerHTML = html; } } updateBuildingStatus(); })();