您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
WME PTSM für Deutschland Österreich Schweiz
// ==UserScript== // @name WME Permalink to several Maps DACH // @description WME PTSM für Deutschland Österreich Schweiz // @namespace https://greasyfork.org/de/users/863740-horst-wittlich // @version 2025.06.07 // @match https://*.waze.com/editor* // @match https://*.waze.com/*/editor* // @match https://beta.waze.com/editor* // @match https://beta.waze.com/*/editor* // @icon https://i.ibb.co/ckSvk59/waze-icon.png // @grant none // @license MIT // ==/UserScript== /* global OpenLayers, W, proj4 */ var ptsmVersion = '2025.06.07'; var ptsmInitialized = false; var ptsmUpdateKey = 'wme-ptsm-update-shown-' + ptsmVersion; function showUpdatePopup() { try { // Prüfen ob Update-Info bereits angezeigt wurde if (localStorage.getItem(ptsmUpdateKey) === 'true') { return; } } catch (e) { // Falls localStorage nicht verfügbar, trotzdem anzeigen } // Popup erstellen var overlay = document.createElement('div'); overlay.style.cssText = ` position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); z-index: 999999; display: flex; align-items: center; justify-content: center; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; `; var popup = document.createElement('div'); popup.style.cssText = ` background: white; border-radius: 12px; padding: 24px; max-width: 400px; margin: 20px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); text-align: center; position: relative; `; popup.innerHTML = ` <div style="font-size: 24px; margin-bottom: 16px;">🎉 PTSM DACH Update! 🗺️</div> <div style="font-size: 18px; font-weight: bold; color: #007bff; margin-bottom: 16px;"> Version ${ptsmVersion} </div> <div style="text-align: left; margin-bottom: 20px; line-height: 1.6;"> <div style="font-size: 16px; font-weight: bold; margin-bottom: 12px; color: #333;"> ✨ Was ist neu: </div> <div style="margin-bottom: 8px;"> 🔧 <strong>ADAC Zoom level ist nun feiner. Es werden mehr abstufungen vom WME berücksichtigt</strong> - Präzise Zoom-Übertragung </div> </div> <button id="ptsm-close-popup" style=" background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); color: white; border: none; border-radius: 8px; padding: 12px 24px; font-size: 14px; font-weight: 600; cursor: pointer; transition: all 0.2s ease; "> 🚀 Los geht's! </button> `; overlay.appendChild(popup); document.body.appendChild(overlay); // Close button event var closeBtn = popup.querySelector('#ptsm-close-popup'); closeBtn.addEventListener('click', function() { overlay.remove(); try { localStorage.setItem(ptsmUpdateKey, 'true'); } catch (e) { // localStorage not available } }); closeBtn.addEventListener('mouseover', function() { this.style.transform = 'translateY(-2px)'; this.style.boxShadow = '0 4px 12px rgba(0, 123, 255, 0.3)'; }); closeBtn.addEventListener('mouseout', function() { this.style.transform = 'translateY(0)'; this.style.boxShadow = 'none'; }); // Schließen bei Klick auf Overlay overlay.addEventListener('click', function(e) { if (e.target === overlay) { overlay.remove(); try { localStorage.setItem(ptsmUpdateKey, 'true'); } catch (e) { // localStorage not available } } }); } function getCenterZoom() { var map = W.map.getOLMap(); var zoom = map.getZoom(); var center = map.getCenter().transform(new OpenLayers.Projection('EPSG:900913'), new OpenLayers.Projection('EPSG:4326')); center.zoom = zoom; return center; } function saveDropdownStates() { const states = {}; document.querySelectorAll('.ptsm-category').forEach(category => { const className = category.className.match(/ptsm-category-(\w+)/); if (className) { states[className[1]] = category.classList.contains('open'); } }); try { localStorage.setItem('wme-ptsm-dropdown-states', JSON.stringify(states)); } catch (e) { console.log('PTSM: localStorage not available'); } } function loadDropdownStates() { try { const saved = localStorage.getItem('wme-ptsm-dropdown-states'); return saved ? JSON.parse(saved) : {}; } catch (e) { return {}; } } function saveCompactMode(isCompact) { try { localStorage.setItem('wme-ptsm-compact-mode', isCompact ? 'true' : 'false'); } catch (e) { console.log('PTSM: localStorage not available'); } } function loadCompactMode() { try { const saved = localStorage.getItem('wme-ptsm-compact-mode'); return saved === 'true'; } catch (e) { return false; } } function createCategory(title, className, defaultOpen = false) { const savedStates = loadDropdownStates(); const categoryKey = className.replace('ptsm-category-', ''); const isOpen = savedStates.hasOwnProperty(categoryKey) ? savedStates[categoryKey] : defaultOpen; var category = document.createElement('div'); category.className = 'ptsm-category ' + className + (isOpen ? ' open' : ''); var header = document.createElement('button'); header.className = 'ptsm-category-header'; header.innerHTML = title + '<div class="ptsm-dropdown-arrow"></div>'; var content = document.createElement('div'); content.className = 'ptsm-category-content'; header.addEventListener('click', function() { category.classList.toggle('open'); setTimeout(saveDropdownStates, 100); }); category.appendChild(header); category.appendChild(content); return { category, content }; } function createMapButton(text, className, clickHandler) { var btn = document.createElement('button'); btn.textContent = text; btn.className = 'ptsm-map-btn ' + className; btn.addEventListener('click', clickHandler); return btn; } function createCompactButton() { var btn = document.createElement('button'); btn.className = 'ptsm-compact-btn'; btn.innerHTML = '🔧 Kompakt-Modus'; const isCompact = loadCompactMode(); if (isCompact) { btn.innerHTML = '🔧 Normal-Modus'; btn.classList.add('active'); } btn.addEventListener('click', function() { const container = document.querySelector('.ptsm-container'); const isCurrentlyCompact = container.classList.contains('compact'); if (isCurrentlyCompact) { container.classList.remove('compact'); btn.innerHTML = '🔧 Kompakt-Modus'; btn.classList.remove('active'); saveCompactMode(false); } else { container.classList.add('compact'); btn.innerHTML = '🔧 Normal-Modus'; btn.classList.add('active'); saveCompactMode(true); } }); return btn; } function addButtons() { if (ptsmInitialized) { return; } if (!document.getElementById('user-info')) { setTimeout(addButtons, 500); return; } if (!W.loginManager.user) { if (!ptsmInitialized) { W.loginManager.events.register('login', null, function() { if (!ptsmInitialized) addButtons(); }); W.loginManager.events.register('loginStatus', null, function() { if (!ptsmInitialized) addButtons(); }); } if (!W.loginManager.user) { return; } } ptsmInitialized = true; if (typeof proj4 === "undefined") { var script = document.createElement('script'); script.src = 'https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.4.4/proj4.js'; document.head.appendChild(script); } // Add CSS var style = document.createElement('style'); style.textContent = ` .ptsm-container { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif; padding: 8px; background: #fff; font-size: 12px; } .ptsm-category { margin-bottom: 8px; border-radius: 6px; overflow: hidden; background: #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.08); border: 1px solid #e1e5e9; } .ptsm-category-header { width: 100%; padding: 8px 12px; background: linear-gradient(135deg, #6c757d 0%, #495057 100%); color: white; border: none; cursor: pointer; font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; display: flex; justify-content: space-between; align-items: center; transition: all 0.2s ease; } .ptsm-category-header:hover { background: linear-gradient(135deg, #5a6268 0%, #343a40 100%); } .ptsm-dropdown-arrow { width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-top: 6px solid white; transition: transform 0.2s ease; } .ptsm-category.open .ptsm-dropdown-arrow { transform: rotate(180deg); } .ptsm-category-content { max-height: 0; overflow: hidden; padding: 0 8px; transition: max-height 0.3s ease, padding 0.2s ease; } .ptsm-category.open .ptsm-category-content { max-height: 500px; padding: 8px; } .ptsm-map-btn { width: calc(33.333% - 4px); height: 28px; margin: 2px; padding: 4px 6px 4px 24px; background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; font-size: 10px; font-weight: 500; color: #495057; cursor: pointer; position: relative; display: inline-flex; align-items: center; justify-content: flex-start; transition: all 0.15s ease; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04); text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } .ptsm-map-btn::before { content: ''; position: absolute; left: 4px; top: 50%; transform: translateY(-50%); width: 12px; height: 12px; background-size: contain; background-repeat: no-repeat; background-position: center; flex-shrink: 0; } .ptsm-map-btn:hover { transform: translateY(-1px); background: linear-gradient(145deg, #ffffff 0%, #f1f3f4 100%); border-color: #007bff; color: #0056b3; box-shadow: 0 2px 8px rgba(0, 123, 255, 0.12); } .ptsm-compact-btn { width: calc(100% - 4px); height: 32px; margin: 2px; padding: 8px 12px; background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%); border: none; border-radius: 4px; font-size: 11px; font-weight: 600; color: white; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); text-transform: uppercase; letter-spacing: 0.5px; } .ptsm-compact-btn:hover { transform: translateY(-1px); background: linear-gradient(135deg, #1e7e34 0%, #155724 100%); box-shadow: 0 2px 8px rgba(40, 167, 69, 0.25); } .ptsm-compact-btn.active { background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); } .ptsm-compact-btn.active:hover { background: linear-gradient(135deg, #c82333 0%, #a02834 100%); box-shadow: 0 2px 8px rgba(220, 53, 69, 0.25); } /* Kompakt-Modus Styles */ .ptsm-container.compact .ptsm-category { margin-bottom: 4px; } .ptsm-container.compact .ptsm-category-header { padding: 6px 10px; font-size: 10px; } .ptsm-container.compact .ptsm-category.open .ptsm-category-content { padding: 4px; } .ptsm-container.compact .ptsm-map-btn { width: calc(33.333% - 3px); height: 24px; margin: 1.5px; padding: 3px 5px 3px 20px; font-size: 9px; } .ptsm-container.compact .ptsm-map-btn::before { width: 10px; height: 10px; left: 3px; } .ptsm-container.compact .ptsm-compact-btn { height: 28px; font-size: 10px; padding: 6px 10px; } /* Category colors */ .ptsm-category-allgem .ptsm-category-header { background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); } .ptsm-category-allgem .ptsm-category-header:hover { background: linear-gradient(135deg, #0056b3 0%, #004085 100%); } .ptsm-category-baustell .ptsm-category-header { background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%); } .ptsm-category-baustell .ptsm-category-header:hover { background: linear-gradient(135deg, #1e7e34 0%, #155724 100%); } .ptsm-category-blitzer .ptsm-category-header { background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); } .ptsm-category-blitzer .ptsm-category-header:hover { background: linear-gradient(135deg, #c82333 0%, #a02834 100%); } .ptsm-category-bilder .ptsm-category-header { background: linear-gradient(135deg, #17a2b8 0%, #138496 100%); } .ptsm-category-bilder .ptsm-category-header:hover { background: linear-gradient(135deg, #138496 0%, #0f6674 100%); } .ptsm-category-geoportal .ptsm-category-header { background: linear-gradient(135deg, #6f42c1 0%, #59359a 100%); } .ptsm-category-geoportal .ptsm-category-header:hover { background: linear-gradient(135deg, #59359a 0%, #4c2c85 100%); } .ptsm-category-misc .ptsm-category-header { background: linear-gradient(135deg, #fd7e14 0%, #e65100 100%); } .ptsm-category-misc .ptsm-category-header:hover { background: linear-gradient(135deg, #e65100 0%, #bf360c 100%); } /* Icons */ .ptsm-google::before { background-image: url(https://i.ibb.co/d0zx6Pdt/google-maps.png); } .ptsm-f4map::before { background-image: url(https://i.ibb.co/5WxjKkLp/F-Logo.png); } .ptsm-apple::before { background-image: url(https://i.ibb.co/WsH15zC/Apple-Jetzt.png); } .ptsm-bing::before { background-image: url(https://i.ibb.co/0LF74p6/bing.png); } .ptsm-nrw::before { background-image: url(https://i.ibb.co/37q7H37/nrw.png); } .ptsm-osm::before { background-image: url(https://i.ibb.co/20wtGrsL/osm.png); } .ptsm-autobahn::before { background-image: url(https://i.ibb.co/2Y3pT8v2/Autobahn-Logo.png); } .ptsm-poi-karte::before { background-image: url(https://i.ibb.co/nMRSSKKp/POI-Karte.jpg); } .ptsm-poi-base::before { background-image: url(https://i.ibb.co/xS7vJQr8/POI-Base.jpg); } .ptsm-viamichelin::before { background-image: url(https://i.ibb.co/RTzJP87C/viamichelin.png); } .ptsm-here::before { background-image: url(https://i.ibb.co/MC9JF7T/h-logo.png); } .ptsm-mapillary::before { background-image: url(https://i.ibb.co/JWkZnh0X/mapillary.png); } .ptsm-osbrowser::before { background-image: url(https://i.ibb.co/RdQSgsY/osb.png); } .ptsm-mappy::before { background-image: url(https://i.ibb.co/wrhH7H95/mappy.png); } .ptsm-blitzer::before { background-image: url(https://i.ibb.co/gVKMwKS/blitzer.png); } .ptsm-bayernatlas::before { background-image: url(https://i.ibb.co/KxnBpv7J/bayernatlas.png); } .ptsm-tomtom::before { background-image: url(https://i.ibb.co/hDq5bys/tomtom-icon2.png); } .ptsm-basemap-de::before { background-image: url(https://i.ibb.co/V3jJJrb/de-map.png); } .ptsm-reporting::before { background-image: url(https://i.ibb.co/rZb76j2/pin.png); } .ptsm-kartaview::before { background-image: url(https://i.ibb.co/xgnTMFf/kartaview.png); } .ptsm-bayerninfo::before { background-image: url(https://i.ibb.co/R0K3SSs/bayerninfo.png); } .ptsm-timonline::before { background-image: url(https://i.ibb.co/bPJ4qRy/das-da2.png); } .ptsm-geoadmin::before { background-image: url(https://i.ibb.co/Np5chv4/CH-Icon-20.png); } .ptsm-basemap-at::before { background-image: url(https://i.ibb.co/MCKhDSH/AT-Icon.png); } .ptsm-adac::before { background-image: url(https://i.ibb.co/6YsGCFy/adac.png); } .ptsm-here-edit::before { background-image: url(https://i.ibb.co/VghMgy8/here.png); } .ptsm-umsehen::before { background-image: url(https://i.ibb.co/XYqjkYX/umsehen-icon.png); } .ptsm-hackintosh::before { background-image: url(https://i.ibb.co/8xP5RyC/Hackintosh.png); } .ptsm-archive::before { background-image: url(https://i.ibb.co/QHpvd85/Das-Logo.png); } .ptsm-state-info { font-size: 9px; color: #6c757d; font-style: italic; text-align: center; margin-top: 6px; margin-bottom: 4px; } .ptsm-warning { background: #fff8e1; border: 1px solid #ffcc02; border-radius: 4px; padding: 8px; margin-top: 8px; margin-bottom: 8px; display: flex; align-items: flex-start; } .ptsm-warning .w-icon { font-size: 14px; color: #f57c00; margin-right: 6px; flex-shrink: 0; } .ptsm-warning-text { font-size: 9px; color: #e65100; line-height: 1.3; } @media (max-width: 768px) { .ptsm-map-btn { width: calc(50% - 4px); } } @media (max-width: 480px) { .ptsm-map-btn { width: calc(100% - 4px); } } `; document.head.appendChild(style); // Create all map buttons var btn1 = createMapButton('Google', 'ptsm-google', () => { var cz = getCenterZoom(); // Bessere Google Maps Zoom-Level Umrechnung var googleZoom; if (cz.zoom >= 20) googleZoom = 19; // Sehr nah else if (cz.zoom >= 18) googleZoom = 17; // Nah else if (cz.zoom >= 16) googleZoom = 15; // Mittel-nah else if (cz.zoom >= 14) googleZoom = 13; // Mittel else if (cz.zoom >= 12) googleZoom = 11; // Mittel-weit else if (cz.zoom >= 10) googleZoom = 9; // Weit else googleZoom = Math.max(1, cz.zoom - 2); // Sehr weit window.open('https://www.google.com/maps/@' + cz.lat + ',' + cz.lon + ',' + googleZoom + 'z/data=!5m1!1e1', '_blank'); }); var btn2 = createMapButton('Bing', 'ptsm-bing', () => { var cz = getCenterZoom(); cz.zoom -= 1; window.open('https://www.bing.com/maps/traffic?cp=' + cz.lat + '~' + cz.lon + '&lvl=' + cz.zoom, '_blank'); }); var btn3 = createMapButton('Ver. NRW', 'ptsm-nrw', () => { var cz = getCenterZoom(); window.open('https://www.verkehr.nrw/?center=' + cz.lat + ',' + cz.lon + '&zoom=' + cz.zoom + '&layer=Verkehrslage,Baustellen,Haltestellen,Parken,Webcams,Verkehrsmeldungen,ELadesaeulen,Tankstellen&highlightRoute=false', '_blank'); }); var btn3a = createMapButton('OSM', 'ptsm-osm', () => { var cz = getCenterZoom(); window.open('https://www.openstreetmap.org/#map=' + cz.zoom + '/' + cz.lat + '/' + cz.lon, '_blank'); }); var btn4 = createMapButton('F4 3D Map', 'ptsm-f4map', () => { var cz = getCenterZoom(); window.open('https://demo.f4map.com/#lat=' + cz.lat + '&lon=' + cz.lon + '&zoom=' + cz.zoom, '_blank'); }); var btn5 = createMapButton('Apple', 'ptsm-apple', () => { var cz = getCenterZoom(); window.open('https://maps.apple.com/look-around?coordinate=' + cz.lat + '%2C' + cz.lon, '_blank'); }); var btn6 = createMapButton('Autobahn', 'ptsm-autobahn', () => { var cz = getCenterZoom(); window.open('https://verkehr.vz-deutschland.de/?layer=raststellen,baustellen,stau,verkehrsmeldungen&zoom=' + cz.zoom + '&lat=' + cz.lat + '&lon=' + cz.lon, '_blank'); }); var btn7 = createMapButton('POI Karte', 'ptsm-poi-karte', () => { var cz = getCenterZoom(); // Bessere Zoom-Level-Übertragung: Je höher das Waze-Zoom, desto kleiner der Radius var radius; if (cz.zoom >= 18) radius = 500; // Sehr nah - 500m Radius else if (cz.zoom >= 16) radius = 1000; // Nah - 1km Radius else if (cz.zoom >= 14) radius = 2500; // Mittel - 2.5km Radius else if (cz.zoom >= 12) radius = 5000; // Weit - 5km Radius else if (cz.zoom >= 10) radius = 10000; // Sehr weit - 10km Radius else radius = 25000; // Maximum - 25km Radius window.open('https://www.flosm.org/de/POI-Karte.html?lat=' + cz.lat + '&lon=' + cz.lon + '&r=' + radius + '&st=0&sw=speedcamera', '_blank'); }); var btn8 = createMapButton('POI Base', 'ptsm-poi-base', () => { var cz = getCenterZoom(); window.open('https://www.poibase.com/de/karte/#/map/coords-' + cz.lon + ',' + cz.lat + '/zoom-' + cz.zoom, '_blank'); }); var btn9 = createMapButton('ViaM', 'ptsm-viamichelin', () => { var cz = getCenterZoom(); // ViaMichelin moderne URL-Struktur mit bounds und center // Zoom-abhängige Bounds-Berechnung für bessere Darstellung var zoomFactor; if (cz.zoom >= 18) zoomFactor = 0.001; // Sehr nah else if (cz.zoom >= 16) zoomFactor = 0.002; // Nah else if (cz.zoom >= 14) zoomFactor = 0.005; // Mittel-nah else if (cz.zoom >= 12) zoomFactor = 0.01; // Mittel else if (cz.zoom >= 10) zoomFactor = 0.02; // Mittel-weit else if (cz.zoom >= 8) zoomFactor = 0.05; // Weit else zoomFactor = 0.1; // Sehr weit // Bounds berechnen (Rechteck um den Mittelpunkt) var latMin = (cz.lat - zoomFactor).toFixed(6); var latMax = (cz.lat + zoomFactor).toFixed(6); var lonMin = (cz.lon - zoomFactor).toFixed(6); var lonMax = (cz.lon + zoomFactor).toFixed(6); var viaMichelinUrl = 'https://www.viamichelin.de/karten-stadtplan/verkehr?bounds=' + lonMin + '%7E' + latMin + '%7E' + lonMax + '%7E' + latMax + '¢er=' + cz.lon.toFixed(6) + '%7E' + cz.lat.toFixed(6) + '&page=1&poiCategories=0&showPolandModal=false'; window.open(viaMichelinUrl, '_blank'); }); var btn10 = createMapButton('Here', 'ptsm-here', () => { var cz = getCenterZoom(); window.open('https://wego.here.com/?map=' + cz.lat + ',' + cz.lon + ',' + cz.zoom + ',normal', '_blank'); }); var btn11 = createMapButton('Mapillary', 'ptsm-mapillary', () => { var cz = getCenterZoom(); cz.zoom -= 1; window.open('https://www.mapillary.com/app/?lat=' + cz.lat + '&lng=' + cz.lon + '&z=' + cz.zoom, '_blank'); }); var btn12 = createMapButton('OSBrowser', 'ptsm-osbrowser', () => { var cz = getCenterZoom(); window.open('https://www.openstreetbrowser.org/#map=' + cz.zoom + '/' + cz.lat + '/' + cz.lon + '&categories=car_maxspeed', '_blank'); }); var btn13 = createMapButton('Mappy', 'ptsm-mappy', () => { var cz = getCenterZoom(); window.open('https://en.mappy.com/plan#/' + cz.lat + ',' + cz.lon, '_blank'); }); var btn14 = createMapButton('Blitzer.de', 'ptsm-blitzer', () => { var cz = getCenterZoom(); window.open('https://map.atudo.com/v5/?lat=' + cz.lat + '&lng=' + cz.lon + '&zoom=' + cz.zoom, '_blank'); }); var btn16 = createMapButton('BY Atlas', 'ptsm-bayernatlas', () => { var cz = getCenterZoom(); cz.zoom -= 5; if (typeof proj4 === "undefined") { alert('proj4 library not loaded'); return; } var firstProj = '+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'; var utm = proj4(firstProj, [cz.lon, cz.lat]); window.open('https://geoportal.bayern.de/bayernatlas/index.html?zoom=' + cz.zoom + '&E=' + utm[0] + '&N=' + utm[1], '_blank'); }); var btn18 = createMapButton('TomTom', 'ptsm-tomtom', () => { var cz = getCenterZoom(); cz.zoom -= 1; window.open('https://plan.tomtom.com/de?p=' + cz.lat + ',' + cz.lon + ',' + cz.zoom + 'z', '_blank'); }); var btn19 = createMapButton('Basemap.de', 'ptsm-basemap-de', () => { var cz = getCenterZoom(); cz.zoom = 0.985 * cz.zoom - 1.05; window.open('https://basemap.de/viewer?config=' + btoa('{"lat":' + cz.lat + ',"lon":' + cz.lon + ',"zoom":' + cz.zoom + ',"styleID":0,"pitch":0,"bearing":0,"saturation":0,"brightness":0,"hiddenControls":[],"hiddenLayers":[],"changedLayers":[],"hiddenSubGroups":[],"changedSubGroups":[],"externalStyleURL":""}'), '_blank'); }); var btn20 = createMapButton('Reporting', 'ptsm-reporting', () => { var cz = getCenterZoom(); cz.zoom -= 1; window.open('https://www.waze.com/partnerhub/map-tool?lat=' + cz.lat + '&lon=' + cz.lon + '&zoom=' + cz.zoom, '_blank'); }); var btn21 = createMapButton('KartaView', 'ptsm-kartaview', () => { var cz = getCenterZoom(); cz.zoom -= 1; window.open('https://kartaview.org/map/@' + cz.lat + ',' + cz.lon + ',' + cz.zoom + 'z', '_blank'); }); var btn22 = createMapButton('Bayerninfo', 'ptsm-bayerninfo', () => { var cz = getCenterZoom(); cz.zoom -= 2; var now = new Date(); var then = new Date(); then.setDate(then.getDate() + 60); var mapsUrl = 'https://www.bayerninfo.de/de/baustellenkalender?geo=' + cz.lat + ',' + cz.lon + '&zoom=' + cz.zoom; mapsUrl += '&datetimeFrom=' + now.toISOString() + '&datetimeTo=' + then.toISOString(); window.open(mapsUrl, '_blank'); }); var btn30 = createMapButton('TimOnline', 'ptsm-timonline', () => { var cz = getCenterZoom(); cz.zoom = 454959671.96858*Math.exp(-0.693*cz.zoom); window.open('https://www.tim-online.nrw.de/tim-online2/?center=' + cz.lat + ',' + cz.lon + '&scale=' + cz.zoom, '_blank'); }); var btn31 = createMapButton('GeoAdmin', 'ptsm-geoadmin', () => { var cz = getCenterZoom(); cz.zoom -= 7.2; var phi1 = ((cz.lat * 3600) - 169028.66) / 10000; var lmd1 = ((cz.lon * 3600) - 26782.5) / 10000; var x = 200147.07 + 308807.95 * phi1 + 3745.25 * lmd1 * lmd1 + 76.63 * phi1 * phi1 + 119.79 * phi1 * phi1 * phi1 - 194.56 * lmd1 * lmd1 * phi1; var y = 600072.37 + 211455.93 * lmd1 - 10938.51 * lmd1 * phi1 - 0.36 * lmd1 * phi1 * phi1 - 44.54 * lmd1 * lmd1 * lmd1; window.open('https://map.geo.admin.ch/?Y=' + y.toFixed(0) + '&X=' + x.toFixed(0) + '&zoom=' + cz.zoom + '&topic=ech&lang=de&bgLayer=ch.swisstopo.pixelkarte-farbe&layers=ch.bfs.gebaeude_wohnungs_register,ch.kantone.cadastralwebmap-farbe,ch.swisstopo.swissimage-product,ch.bfe.ladestellen-elektromobilitaet&catalogNodes=457,532,687,458,477,485,491,510,527,1743&layers_visibility=false,false,true,true&layers_timestamp=,,current', '_blank'); }); var btn32 = createMapButton('Basemap', 'ptsm-basemap-at', () => { var cz = getCenterZoom(); var x = cz.lon / 180 * 20037508.34; var y = Math.log(Math.tan((90 + cz.lat * 1) * Math.PI / 360)) / Math.PI; y *= 20037508.34; window.open('https://basemap.at/bmapp/index.html#{"center":[' + x.toFixed(10) + ',' + y.toFixed(10) + '],"zoom":' + cz.zoom + ',"rotation":0,"layers":"1000000000"}', '_blank'); }); var btn34 = createMapButton('ADAC', 'ptsm-adac', () => { var cz = getCenterZoom(); // ADAC Maps präzise Bounds-Berechnung basierend auf Bildvergleich // Das Problem: ADAC zeigt zu viel östlich und zu nah gezoomt var zoomFactor; if (cz.zoom >= 19) zoomFactor = 0.002; // Extrem nah - größerer Bereich else if (cz.zoom >= 18) zoomFactor = 0.003; // Sehr nah else if (cz.zoom >= 17) zoomFactor = 0.004; // Nah+ else if (cz.zoom >= 16) zoomFactor = 0.006; // Nah else if (cz.zoom >= 15) zoomFactor = 0.008; // Mittel-nah+ else if (cz.zoom >= 14) zoomFactor = 0.012; // Mittel-nah else if (cz.zoom >= 13) zoomFactor = 0.016; // Mittel+ else if (cz.zoom >= 12) zoomFactor = 0.022; // Mittel else if (cz.zoom >= 11) zoomFactor = 0.030; // Mittel-weit+ else if (cz.zoom >= 10) zoomFactor = 0.040; // Mittel-weit else if (cz.zoom >= 9) zoomFactor = 0.060; // Weit+ else if (cz.zoom >= 8) zoomFactor = 0.080; // Weit else zoomFactor = 0.120; // Sehr weit // Korrektur der Verschiebung: ADAC zeigt zu weit östlich und leicht nördlich // Daher verschieben wir den Mittelpunkt leicht nach Westen und Süden var correctedLat = cz.lat - (zoomFactor * 0.05); // Leichte Südverschiebung var correctedLon = cz.lon - (zoomFactor * 0.15); // Leichte Westverschiebung var latMin = (correctedLat - zoomFactor).toFixed(6); var latMax = (correctedLat + zoomFactor).toFixed(6); var lonMin = (correctedLon - zoomFactor).toFixed(6); var lonMax = (correctedLon + zoomFactor).toFixed(6); var adacUrl = 'https://maps.adac.de/?bounds=' + latMin + ',' + lonMin + '-' + latMax + ',' + lonMax + '&traffic=construction,announcements,flow'; window.open(adacUrl, '_blank'); }); var btn36 = createMapButton('Here Edit', 'ptsm-here-edit', () => { var cz = getCenterZoom(); window.open('https://mapcreator.here.com/?l=' + cz.lat + ',' + cz.lon + ',' + cz.zoom + ',autoselect', '_blank'); }); var btn37 = createMapButton('Umsehen', 'ptsm-umsehen', () => { var cz = getCenterZoom(); cz.zoom += 1.0; window.open('https://maps.apple.com/?ll=' + cz.lat + ',' + cz.lon + '&z=' + cz.zoom + '&t=m', '_blank'); }); var btn39 = createMapButton('Hackintosh', 'ptsm-hackintosh', () => { var cz = getCenterZoom(); window.open('https://lookmap.eu.pythonanywhere.com/#c=' + cz.zoom + '/' + cz.lat + '/' + cz.lon + '/', '_blank'); }); var btn40 = createMapButton('Archive', 'ptsm-archive', () => { window.open('https://archive.is/', '_blank'); }); // Kompakt-Button erstellen var compactButton = createCompactButton(); // Create container var container = document.createElement('div'); container.className = 'ptsm-container'; // Kompakt-Modus beim Laden anwenden falls gespeichert if (loadCompactMode()) { container.classList.add('compact'); } // Create categories var allgemCategory = createCategory('Allgemeine Karten', 'ptsm-category-allgem', true); var baustellCategory = createCategory('Baustellen & Verkehr', 'ptsm-category-baustell', false); var blitzerCategory = createCategory('Blitzer & Geschwindigkeit', 'ptsm-category-blitzer', false); var bilderCategory = createCategory('Straßenbilder', 'ptsm-category-bilder', false); var geoportalCategory = createCategory('Geoportale', 'ptsm-category-geoportal', false); var miscCategory = createCategory('Sonstiges', 'ptsm-category-misc', false); // Add buttons to categories // Allgemeine Karten allgemCategory.content.appendChild(btn1); // Google allgemCategory.content.appendChild(btn2); // Bing allgemCategory.content.appendChild(btn3a); // OSM allgemCategory.content.appendChild(btn4); // F4 3D allgemCategory.content.appendChild(btn5); // Apple allgemCategory.content.appendChild(btn10); // Here allgemCategory.content.appendChild(btn13); // Mappy allgemCategory.content.appendChild(btn18); // TomTom allgemCategory.content.appendChild(btn9); // ViaM // Baustellen & Verkehr baustellCategory.content.appendChild(btn3); // Ver. NRW baustellCategory.content.appendChild(btn6); // Autobahn baustellCategory.content.appendChild(btn34); // ADAC // Blitzer & Geschwindigkeit blitzerCategory.content.appendChild(btn14); // Blitzer.de blitzerCategory.content.appendChild(btn7); // POI Karte blitzerCategory.content.appendChild(btn8); // POI Base // Straßenbilder bilderCategory.content.appendChild(btn11); // Mapillary bilderCategory.content.appendChild(btn21); // KartaView bilderCategory.content.appendChild(btn12); // OSBrowser // Geoportale geoportalCategory.content.appendChild(btn19); // Basemap DE geoportalCategory.content.appendChild(btn31); // GeoAdmin geoportalCategory.content.appendChild(btn32); // Basemap AT geoportalCategory.content.appendChild(btn30); // TimOnline geoportalCategory.content.appendChild(btn16); // BY Atlas geoportalCategory.content.appendChild(btn22); // Bayerninfo // Sonstiges miscCategory.content.appendChild(btn20); // Reporting miscCategory.content.appendChild(btn36); // Here Edit miscCategory.content.appendChild(btn37); // Umsehen miscCategory.content.appendChild(btn39); // Hackintosh miscCategory.content.appendChild(btn40); // Archive miscCategory.content.appendChild(compactButton); // Kompakt-Button hinzufügen // Add categories to container container.appendChild(allgemCategory.category); container.appendChild(baustellCategory.category); container.appendChild(blitzerCategory.category); container.appendChild(bilderCategory.category); container.appendChild(geoportalCategory.category); container.appendChild(miscCategory.category); // Add version info with update link var versionInfo = document.createElement('div'); versionInfo.className = 'ptsm-state-info'; var updateLink = document.createElement('a'); updateLink.href = 'https://greasyfork.org/de/scripts/448378-wme-permalink-to-several-maps-dach'; updateLink.target = '_blank'; updateLink.textContent = 'Auf Updates überprüfen / V' + ptsmVersion; updateLink.style.cssText = 'color: #007bff; text-decoration: none; font-size: 9px;'; updateLink.addEventListener('mouseover', function() { this.style.textDecoration = 'underline'; }); updateLink.addEventListener('mouseout', function() { this.style.textDecoration = 'none'; }); versionInfo.appendChild(updateLink); container.appendChild(versionInfo); // Add warning about external services var warning = document.createElement('div'); warning.className = 'ptsm-warning'; warning.innerHTML = '<div class="w-icon">⚠</div><div class="ptsm-warning-text">Hinweis: Einige der externen Karten sind als Informationsquelle zur Kartenbearbeitung nicht zulässig!</div>'; container.appendChild(warning); // Try to use WME Userscript API first, fallback to manual insertion try { if (W.userscripts && W.userscripts.registerSidebarTab) { const result = W.userscripts.registerSidebarTab('wme-ptsm-dach'); var tabLabel = result.tabLabel; var tabPane = result.tabPane; tabLabel.textContent = 'PTSM'; tabLabel.title = 'WME Permalink to several Maps DACH'; tabPane.appendChild(container); } else { // Fallback: Try to add to existing sidebar var sidebar = document.querySelector('#sidebar') || document.querySelector('.sidebar'); if (sidebar) { // Create a collapsible section var section = document.createElement('div'); section.style.cssText = 'border: 1px solid #ccc; margin: 10px 0; border-radius: 5px;'; var header = document.createElement('div'); header.style.cssText = 'background: #f5f5f5; padding: 10px; cursor: pointer; font-weight: bold; user-select: none;'; header.textContent = 'PTSM DACH'; var content = document.createElement('div'); content.style.display = 'none'; content.appendChild(container); header.addEventListener('click', function() { content.style.display = content.style.display === 'none' ? 'block' : 'none'; }); section.appendChild(header); section.appendChild(content); sidebar.appendChild(section); } else { // Last resort: Create floating panel var floatingPanel = document.createElement('div'); floatingPanel.style.cssText = ` position: fixed; top: 100px; right: 10px; width: 300px; max-height: 70vh; overflow-y: auto; background: white; border: 1px solid #ccc; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); z-index: 10000; resize: both; `; var panelHeader = document.createElement('div'); panelHeader.style.cssText = ` background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); color: white; padding: 10px; font-weight: bold; cursor: move; user-select: none; display: flex; justify-content: space-between; align-items: center; `; panelHeader.innerHTML = 'PTSM DACH <span style="cursor: pointer; font-size: 18px;">×</span>'; var closeBtn = panelHeader.querySelector('span'); closeBtn.addEventListener('click', function() { floatingPanel.style.display = 'none'; }); // Make panel draggable var isDragging = false; var startX, startY, startLeft, startTop; panelHeader.addEventListener('mousedown', function(e) { if (e.target === closeBtn) return; isDragging = true; startX = e.clientX; startY = e.clientY; startLeft = parseInt(window.getComputedStyle(floatingPanel).left, 10); startTop = parseInt(window.getComputedStyle(floatingPanel).top, 10); document.addEventListener('mousemove', drag); document.addEventListener('mouseup', stopDrag); }); function drag(e) { if (!isDragging) return; var newLeft = startLeft + e.clientX - startX; var newTop = startTop + e.clientY - startY; floatingPanel.style.left = newLeft + 'px'; floatingPanel.style.top = newTop + 'px'; } function stopDrag() { isDragging = false; document.removeEventListener('mousemove', drag); document.removeEventListener('mouseup', stopDrag); } floatingPanel.appendChild(panelHeader); floatingPanel.appendChild(container); document.body.appendChild(floatingPanel); } } } catch (e) { console.error('PTSM: Error adding to sidebar:', e); } console.log('PTSM DACH v' + ptsmVersion + ' loaded successfully'); // Update-Popup anzeigen (einmalig pro Version) setTimeout(showUpdatePopup, 1000); } // Initialize when page loads if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', addButtons); } else { setTimeout(addButtons, 1000); } // Also try to initialize when Waze editor loads if (typeof W !== 'undefined') { if (W.loginManager && W.loginManager.events) { W.loginManager.events.register('loginStateChanged', null, addButtons); } setTimeout(addButtons, 2000); } else { // Wait for Waze object to be available var checkForWaze = setInterval(function() { if (typeof W !== 'undefined' && W.loginManager) { clearInterval(checkForWaze); setTimeout(addButtons, 1000); } }, 500); }