// ==UserScript== // @name Plenty: Auftrags-ID & Artikel-ID entfernen + Vorauswahl (prod) // @namespace http://tampermonkey.net/ // @version 4.5 // @description Entfernt "Auftrags-ID" & "Artikel-ID" aus der Autocomplete-Liste, markiert erste gültige Option visuell und wählt sie erst bei Enter. Produktiv, keine Debug-Logs. // @match *://p7615.my.plentysystems.com/* // @run-at document-idle // @grant none // ==/UserScript== (function () { 'use strict'; const REMOVE_KEYWORDS = ['Auftrags-ID', 'Artikel-ID']; const DEBOUNCE_MS = 160; let searchField = null; let listenersAttached = false; let processTimer = null; function isVisible(el) { if (!el) return false; const r = el.getBoundingClientRect(); return r.width > 0 && r.height > 0; } function findSearchField() { const active = document.activeElement; if (active && active.tagName && active.tagName.toLowerCase() === 'input' && isVisible(active)) { return active; } const sel = 'input[type="text"], input[type="search"], input[placeholder], input[aria-label]'; const inputs = Array.from(document.querySelectorAll(sel)).filter(isVisible); if (inputs.length) { inputs.sort((a,b) => (b.value||'').length - (a.value||'').length); return inputs[0]; } return null; } function collectOptionElements() { let opts = []; try { opts = opts.concat(Array.from(document.querySelectorAll('mat-option'))); } catch (e) {} try { const overlays = Array.from(document.querySelectorAll('.cdk-overlay-container, .cdk-overlay-pane')); overlays.forEach(container => { try { opts = opts.concat(Array.from(container.querySelectorAll('mat-option, [role="option"], li, .mat-mdc-option'))); } catch (e) {} }); } catch (e) {} const uniq = Array.from(new Set(opts)).filter(el => el && isVisible(el)); return uniq; } function hideOption(opt) { try { opt.setAttribute('aria-hidden', 'true'); opt.hidden = true; opt.style.display = 'none'; } catch (e) { /* still continue silently */ } } function showPreselect(el) { document.querySelectorAll('.tm-preselect-outline').forEach(x => { x.classList.remove('tm-preselect-outline'); x.style.outline = ''; x.style.backgroundColor = ''; }); if (!el) return; if (!el.id) el.id = `tm-opt-${Date.now()}-${Math.random().toString(36).slice(2,8)}`; el.classList.add('tm-preselect-outline'); el.style.outline = '3px solid rgba(0,200,120,0.95)'; el.style.backgroundColor = 'rgba(0,200,120,0.06)'; } function processDropdown() { if (processTimer) { clearTimeout(processTimer); processTimer = null; } if (!searchField) searchField = findSearchField(); const searchVal = searchField ? (searchField.value || '').trim() : ''; const containsLetters = /[a-zA-ZÄÖÜäöüß]/.test(searchVal); const opts = collectOptionElements(); if (!opts.length) return; let firstValid = null; for (const o of opts) { const txt = (o.textContent || '').trim(); if (containsLetters && REMOVE_KEYWORDS.some(k => txt.includes(k))) { hideOption(o); } else { if (!firstValid) firstValid = o; } } if (firstValid) { showPreselect(firstValid); try { if (searchField) searchField.setAttribute('aria-activedescendant', firstValid.id); } catch (e) {} } else { showPreselect(null); } } function scheduleProcess() { if (processTimer) clearTimeout(processTimer); processTimer = setTimeout(processDropdown, DEBOUNCE_MS); } function onEnterHandler(ev) { if (ev.key === 'Enter') { ev.stopPropagation(); ev.stopImmediatePropagation(); ev.preventDefault(); const active = document.querySelector('.tm-preselect-outline') || document.querySelector('.mat-mdc-option-active'); if (active) { active.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true })); active.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true })); active.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); } } } function attachListenersOnce() { if (listenersAttached) return; listenersAttached = true; window.addEventListener('keydown', onEnterHandler, true); const inputObserver = new MutationObserver(() => { const f = findSearchField(); if (f && f !== searchField) { searchField = f; if (!f.__tm_input_hooked) { f.__tm_input_hooked = true; f.addEventListener('input', scheduleProcess, { passive: true }); f.addEventListener('keyup', scheduleProcess, { passive: true }); } } }); inputObserver.observe(document.body, { childList: true, subtree: true }); const overlayObserver = new MutationObserver((mutations) => { for (const m of mutations) { if (m.addedNodes.length || m.removedNodes.length) { scheduleProcess(); break; } } }); overlayObserver.observe(document.body, { childList: true, subtree: true }); } // Startup setTimeout(() => { try { attachListenersOnce(); searchField = findSearchField(); if (searchField && !searchField.__tm_input_hooked) { searchField.__tm_input_hooked = true; searchField.addEventListener('input', scheduleProcess, { passive: true }); searchField.addEventListener('keyup', scheduleProcess, { passive: true }); } scheduleProcess(); } catch (e) { /* silent fail in prod */ } }, 900); })();