// ==UserScript==
// @name IDEA ERP – KFZ
// @namespace http://tampermonkey.net/
// @version 0.16
// @description Przełączanie widoczności produktów z korektą w module KFZ IDEA ERP
// @author Adam
// @match https://emma.ideaerp.pl/*
// @icon https://emma.ideaerp.pl/web/static/src/img/favicon.ico
// @downloadURL https://n8n.emma.net.pl/webhook/kfz-zd
// @updateURL https://n8n.emma.net.pl/webhook/kfz-zd
// @grant none
// @run-at document-end
// ==/UserScript==
try {
console.log('[Tampermonkey KFZ] Skrypt załadowany - wersja 0.16');
} catch(e) {
alert('Błąd w Tampermonkey KFZ: ' + e);
}
/* ========================OPIS==============================
WERSJA 0.16 - Znajdowanie kolumny po indeksie (data-name tylko w th, nie w td)
WYMAGANE PARAMETRY URL:
- action=276 (ID akcji KFZ - Korekty zakupu)
- menu_id=141 (ID menu KFZ)
- view_type=form (tylko widok formularza)
- Skrypt działa TYLKO na stronie faktury korygującej (KFZ)
WYMAGANE ELEMENTY:
- Element .o_notebook ul.nav.nav-tabs (zakładki na stronie)
- Tabela .o_field_x2many[name="invoice_line_ids"] table.o_list_table
- Kolumna data-name="price_subtotal" (wartość korekty)
- Element .o_pager .o_pager_value (zakres paginacji)
- Element .o_pager .o_pager_limit (całkowita liczba produktów)
DZIAŁANIE SKRYPTU:
- Dodaje przycisk w zakładkach strony
- "Pokaż korygowane produkty" → ładuje wszystkie produkty i ukrywa wiersze z wartością = 0
- "Pokaż wszystko" → pokazuje wszystkie wiersze i resetuje do domyślnego widoku
- Filtrowanie po kolumnie price_subtotal (nie używa indeksów kolumn)
- Bezpieczne obsługiwanie dla < 41 produktów (brak paginacji)
FUNKCJE:
- runScriptCheck() - sprawdza czy hash się zmienił i czy to właściwa strona, dodaje przycisk tylko raz
- isCorrectPage() - sprawdza czy to właściwa strona KFZ (action=276, menu_id=141, view_type=form)
- createTestButton() - tworzy przycisk w interfejsie
- parsePolishNumber() - parsuje polskie wartości numeryczne (przecinek, zł, etc.)
- toggleValueRows() - filtruje wiersze według wartości (ukrywa/pokazuje wartość = 0)
- changePaginationRange() - pomocnicza funkcja do zmiany zakresu paginacji
- loadAllProducts() - ładuje wszystkie produkty
- resetToDefault() - resetuje do domyślnego widoku (1-40)
- init() - inicjalizuje skrypt i czeka na poprawne parametry URL w SPA (do 5 sek)
- startElementCheck() - sprawdza elementy DOM po potwierdzeniu poprawności URL
NASTĘPNE KROKI:
- Zapamiętywanie stanu filtra między sesjami
- Dodanie wskaźnika liczby widocznych/ukrytych wierszy
AUTOMATYCZNE AKTUALIZACJE:
- Serwer aktualizacji: https://n8n.emma.net.pl/webhook/kfz-zd
- Tampermonkey automatycznie sprawdza dostępność nowych wersji
CHANGELOG:
v0.16 (2025) - ZNAJDOWANIE KOLUMNY PO INDEKSIE Z NAGŁÓWKA
- Naprawiono problem z brakiem atrybutu data-name w komórkach
- Teraz znajdujemy kolumnę po indeksie z nagłówka |
- Pobieramy indeks kolumny z nagłówka i używamy go do znalezienia komórki w wierszu
- Dodano obsługę wielu wierszy w thead (pomijamy .i7_list_search_wrap)
- Dodano szczegółowe logi pokazujące liczbę znalezionych komórek w wierszu
- Podwyższenie numeru wersji do 0.16
v0.15 (2025) - POPRAWIONO PARSOWANIE WARTOŚCI Z &NBSP; I PRZECINKAMI
- Naprawiono funkcję parsePolishNumber() - zamiana WSZYSTKICH przecinków na kropki
- Dodano obsługę (zakodowany entity) w atrybucie title
- Dodano szczegółowe logi parsowania każdej wartości
- Naprawiono problem z filtrowaniem wierszy z wartościami ujemnymi (np. -10,15)
- Filtrowanie teraz poprawnie rozpoznaje wartości z przecinkami i spacjami
- Podwyższenie numeru wersji do 0.16
v0.14 (2025) - DODANO NASŁUCHIWANIE NA ZMIANY HASH
- Dodano window.addEventListener('hashchange') do nasłuchiwania zmian URL
- Dodano funkcję runScriptCheck() która sprawdza czy dodano przycisk
- Dodano zmienną buttonAdded żeby nie dodawać przycisku wielokrotnie
- Gdy hash się zmienia, resetujemy stan i ponownie sprawdzamy
- Naprawiono problem z brakiem działania przy nawigacji z listingu
- Podwyższenie numeru wersji do 0.16
v0.13 (2025) - ZMIANA @run-at NA document-end
- Zmieniono @run-at z document-start na document-end
- Dodano try-catch blok dla wychwycenia błędów
- document-end jest bardziej kompatybilny z SPA aplikacjami
- Naprawiono problem z brakiem uruchomienia skryptu
- Podwyższenie numeru wersji do 0.16
v0.12 (2025) - ELASTYCZNE SPRAWDZANIE PARAMETRÓW URL
- Funkcja isCorrectPage() teraz rozróżnia brak view_type od błędnego view_type
- Gdy action=276 i menu_id=141 są OK, ale view_type jest null - skrypt czeka
- Dodano specjalny log "⏳ Czekam na view_type=form..." gdy parametry są częściowo poprawne
- To pozwala na dłuższe czekanie aż view_type zostanie ustawiony asynchronicznie
- Podwyższenie numeru wersji do 0.12
v0.11 (2025) - ZWIĘKSZONO CZAS OCZEKIWANIA NA URL
- Zwiększono czas oczekiwania z 5 do 10 sekund (100 prób)
- Dodano logowanie co 10 prób (mniej spam w konsoli)
- Naprawiono problem z brakiem działania przy nawigacji z listingu
- Skrypt teraz czeka dłużej na asynchroniczne ustawienie parametrów URL
- Dodano więcej szczegółowych logów przy timeout
- Podwyższenie numeru wersji do 0.11
v0.10 (2025) - @run-at document-start + natychmiastowy console.log
- Zmieniono @run-at z document-end na document-start dla wcześniejszego uruchomienia
- Dodano natychmiastowy console.log przed IIFE dla debugowania
- Naprawiono problem z brakiem logów w konsoli
- Skrypt uruchamia się teraz na samym początku ładowania strony
- Podwyższenie numeru wersji do 0.10
v0.9 (2025) - OBSŁUGA ASYNCHRONICZNEGO URL W SPA
- Skrypt czeka do 5 sekund na ustawienie prawidłowych parametrów URL
- Naprawiono problem z brakiem przycisku gdy przechodzi się z listingu
- Dodano rozszerzone logi sprawdzające parametry URL
- Funkcja startElementCheck() - osobna funkcja do sprawdzania elementów DOM
- Skrypt działa zarówno przy bezpośrednim linku jak i przy nawigacji z listingu
- URLSearchParams parsuje parametry niezależnie od kolejności
- Podwyższenie numeru wersji do 0.9
v0.8 (2025) - DODANO KONTROLĘ URL
- Dodano funkcję isCorrectPage() sprawdzającą parametry URL
- Skrypt działa tylko na stronie KFZ (action=276, menu_id=141, view_type=form)
- Poprawiono parametry z action=278 na action=276
- Zmieniono menu_id=167 lub 141 na tylko menu_id=141
- Dodano sprawdzanie view_type=form (tylko widok formularza)
- Skrypt nie uruchamia się na niewłaściwych stronach
- Podwyższenie numeru wersji do 0.8
v0.7 (2025) - DODANO FILTROWANIE WIERSZY WEDŁUG WARTOŚCI
- Dodano funkcję toggleValueRows() do ukrywania wierszy z wartością = 0
- Dodano funkcję parsePolishNumber() do parsowania polskich wartości
- Filtrowanie po kolumnie data-name="price_subtotal" (nie używa indeksów)
- "Pokaż korygowane produkty" → ukrywa wiersze z wartością = 0
- "Pokaż wszystko" → pokazuje wszystkie wiersze
- Dodano logi pokazujące wartość każdego wiersza
- Podwyższenie numeru wersji do 0.7
v0.6 (2025) - POPRAWKA SPRAWDZANIA PUSTYCH WARTOŚCI PAGINACJI
- Dodano sprawdzenie czy totalProducts i currentRange nie są puste
- Eliminacja problemu z ustawianiem zakresu "1-" (pusta wartość)
- Teraz poprawnie wykrywa gdy wartości są puste i przerywa działanie
- Podwyższenie numeru wersji do 0.6
v0.5 (2025) - POPRAWKA OBSŁUGI < 41 PRODUKTÓW
- Dodano lepsze zabezpieczenia w loadAllProducts() dla < 41 produktów
- Dodano sprawdzenie w resetToDefault() - nie resetuje gdy brak paginacji
- Eliminacja problemu z pojawianiem się paginacji po pierwszym kliknięciu
- Dodano szczegółowe logi do debugowania
- Podwyższenie numeru wersji do 0.5
v0.4 (2025) - POPRAWKA LOGIKI PAGINACJI I BEZPIECZEŃSTWA
- Dodano funkcję changePaginationRange() - wspólna logika zmiany zakresu
- Dodano funkcję resetToDefault() - reset do domyślnego widoku
- Poprawiono logikę przycisku: "Pokaż korygowane" → wszystkie produkty, "Pokaż wszystko" → 1-40
- Bezpieczne obsługiwanie < 41 produktów (brak paginacji nie powoduje błędów)
- Eliminacja problemu z pokazywaniem tylko ostatniego produktu
- Podwyższenie numeru wersji do 0.4
v0.3 (2025) - POPRAWKA ZAKRESU PAGINACJI
- Poprawiono zakres paginacji z "195" na "1-195" (pełny zakres)
- Teraz pokazuje wszystkie produkty zamiast tylko ostatniego
- Zaktualizowano logi konsoli dla lepszej czytelności
- Podwyższenie numeru wersji do 0.3
v0.2 (2025) - ŁADOWANIE WSZYSTKICH PRODUKTÓW
- Dodano funkcję loadAllProducts() do automatycznego ładowania wszystkich produktów
- Po kliknięciu przycisku zmienia zakres paginacji z "1-40" na "1-{całkowita_liczba}"
- Implementacja poprzez kliknięcie w .o_pager_value, wpisanie wartości i naciśnięcie Enter
- Podwyższenie numeru wersji do 0.2
v0.1 (2025) - TESTOWA WERSJA
- Dodano podstawowy przycisk w zakładkach
- Przycisk zmienia swoją nazwę po kliknięciu
- Brak funkcjonalności filtrowania –
- Podwyższenie numeru wersji do 0.1 (testowa wersja)
============================================================ */
(() => {
'use strict';
console.log('[Tampermonkey KFZ] Wersja 0.16 - znajdowanie kolumny po indeksie z nagłówka');
// Zmienne do śledzenia stanu
let lastHash = '';
let buttonAdded = false;
// Funkcja do uruchomienia skryptu
function runScriptCheck() {
console.log('[Tampermonkey KFZ] runScriptCheck wywołane, hash:', window.location.hash);
// Jeśli już dodaliśmy przycisk, nie dodajemy ponownie
if (buttonAdded) {
console.log('[Tampermonkey KFZ] Przycisk już dodany, pomijam');
return;
}
// Jeśli hash się nie zmienił, nie sprawdzamy ponownie
if (lastHash === window.location.hash) {
console.log('[Tampermonkey KFZ] Hash bez zmian, pomijam');
return;
}
lastHash = window.location.hash;
// Sprawdzamy czy to właściwa strona
if (isCorrectPage()) {
console.log('[Tampermonkey KFZ] ✅ Poprawna strona, uruchamiam startElementCheck()');
buttonAdded = true; // Oznaczamy że dodaliśmy przycisk
startElementCheck();
}
}
// Funkcja sprawdzająca czy to właściwa strona (KFZ - korekty zakupu)
function isCorrectPage() {
const hash = window.location.hash;
console.log('[Tampermonkey KFZ] Sprawdzam URL hash:', hash);
console.log('[Tampermonkey KFZ] Pełny URL:', window.location.href);
// Parametry są w hash, np. #action=276&menu_id=141&view_type=form
if (!hash || hash.length <= 1) {
console.log('[Tampermonkey KFZ] Brak parametrów w hash lub hash jest pusty');
return false;
}
if (!hash.includes('action=')) {
console.log('[Tampermonkey KFZ] Hash nie zawiera parametru action');
return false;
}
// Parsujemy parametry z hash
const params = new URLSearchParams(hash.substring(1)); // usuwamy #
const action = params.get('action');
const menuId = params.get('menu_id');
const viewType = params.get('view_type');
console.log('[Tampermonkey KFZ] Parsowanie: action =', action, ', menu_id =', menuId, ', view_type =', viewType);
// Sprawdzamy czy to strona korekty zakupu
// Wymagamy action=276 i menu_id=141
// view_type może być jeszcze nie ustawiony (będzie ustawiony później)
const hasCorrectAction = action === '276';
const hasCorrectMenu = menuId === '141';
const hasFormView = viewType === 'form';
const isWaitingForViewType = hasCorrectAction && hasCorrectMenu && !viewType;
const isCorrect = hasCorrectAction && hasCorrectMenu && hasFormView;
if (isWaitingForViewType) {
console.log('[Tampermonkey KFZ] ⏳ Czekam na view_type=form...');
console.log('[Tampermonkey KFZ] Otrzymano: action=' + action + ', menu_id=' + menuId + ', view_type=' + viewType);
return false; // Jeszcze czekamy
}
if (!isCorrect) {
console.log('[Tampermonkey KFZ] ❌ To nie jest strona KFZ (korekty zakupu na formularzu)');
console.log('[Tampermonkey KFZ] Wymagane: action=276, menu_id=141, view_type=form');
console.log('[Tampermonkey KFZ] Otrzymano: action=' + action + ', menu_id=' + menuId + ', view_type=' + viewType);
} else {
console.log('[Tampermonkey KFZ] ✅ Poprawna strona KFZ wykryta');
}
return isCorrect;
}
// Funkcja pomocnicza do zmiany zakresu paginacji
function changePaginationRange(newRange) {
console.log('[Tampermonkey KFZ] Zmieniam zakres paginacji na:', newRange);
const pager = document.querySelector('.o_field_x2many[name="invoice_line_ids"] .o_pager');
if (!pager) {
console.log('[Tampermonkey KFZ] Nie znaleziono paginacji (mniej niż 41 produktów)');
return false;
}
const pagerValue = pager.querySelector('.o_pager_value');
if (!pagerValue) {
console.log('[Tampermonkey KFZ] Nie znaleziono elementu .o_pager_value');
return false;
}
pagerValue.click();
setTimeout(() => {
const input = pager.querySelector('.o_pager_value input');
if (input) {
input.value = newRange;
const enterEvent = new KeyboardEvent('keydown', {
key: 'Enter',
code: 'Enter',
keyCode: 13,
bubbles: true
});
input.dispatchEvent(enterEvent);
console.log('[Tampermonkey KFZ] Ustawiono zakres na:', newRange);
}
}, 500);
return true;
}
// Funkcja do parsowania polskich wartości numerycznych
function parsePolishNumber(value) {
if (!value) return 0;
console.log('[Tampermonkey KFZ] Parsuję wartość:', value);
// Usuwamy "zł", wszystkie spacje (w tym i ), zastępujemy przecinki kropkami
let cleanValue = value
.replace(/zł/gi, '') // Usuń zł
.replace(/\s+/g, '') // Usuń wszystkie białe znaki (w tym zwykłe spacje)
.replace(/ /g, '') // Usuń
.replace(/ /g, '') // Usuń zakodowane
.replace(/,/g, '.'); // Zamień WSZYSTKIE przecinki na kropki
console.log('[Tampermonkey KFZ] Oczyszczona wartość:', cleanValue);
const result = parseFloat(cleanValue) || 0;
console.log('[Tampermonkey KFZ] Wynik:', result);
return result;
}
// Funkcja do filtrowania wierszy - ukrywanie/pokazywanie wierszy z wartością = 0
function toggleValueRows(showOnlyWithValue) {
console.log('[Tampermonkey KFZ] Filtruję wiersze - pokazuję tylko z wartością ≠ 0:', showOnlyWithValue);
// Szukamy tabeli pozycji faktury
const table = document.querySelector('.o_field_x2many[name="invoice_line_ids"] table.o_list_table');
if (!table) {
console.log('[Tampermonkey KFZ] Nie znaleziono tabeli');
return;
}
// Szukamy nagłówka kolumny "Wartość" po data-name
// W thead może być kilka wierszy, bierzemy pierwszy (nie .i7_list_search_wrap)
const headerRow = table.querySelector('thead tr:not(.i7_list_search_wrap)');
const headers = headerRow.querySelectorAll('th');
let priceSubtotalIndex = -1;
headers.forEach((th, idx) => {
if (th.getAttribute('data-name') === 'price_subtotal') {
priceSubtotalIndex = idx;
console.log('[Tampermonkey KFZ] Znaleziono kolumnę price_subtotal na indeksie', priceSubtotalIndex);
}
});
if (priceSubtotalIndex === -1) {
console.log('[Tampermonkey KFZ] Nie znaleziono kolumny "price_subtotal"');
return;
}
// Pobieramy wszystkie wiersze danych
const rows = table.querySelectorAll('tbody tr.o_data_row');
console.log('[Tampermonkey KFZ] Znaleziono', rows.length, 'wierszy');
let hiddenCount = 0;
let visibleCount = 0;
// Przetwarzamy każdy wiersz
rows.forEach((row, index) => {
// Szukamy wszystkich komórek w wierszu (włączając th i td)
const cells = row.querySelectorAll('th, td');
console.log('[Tampermonkey KFZ] Wiersz', index + 1, '- znaleziono', cells.length, 'komórek');
// Pobieramy komórkę po indeksie kolumny
// UWAGA: W wierszu pierwsza komórka to | , więc indeks się zgadza
const valueCell = cells[priceSubtotalIndex];
if (!valueCell) {
console.log('[Tampermonkey KFZ] Wiersz', index + 1, '- brak komórki na indeksie', priceSubtotalIndex);
return;
}
console.log('[Tampermonkey KFZ] Wiersz', index + 1, '- komórka:', valueCell);
// Pobieramy wartość z atrybutu title lub textContent
const valueText = valueCell.getAttribute('title') || valueCell.textContent;
const numericValue = parsePolishNumber(valueText);
console.log('[Tampermonkey KFZ] Wiersz', index + 1, ':', valueText, '->', numericValue);
if (showOnlyWithValue) {
// Pokaż tylko wiersze z wartością ≠ 0
if (numericValue !== 0) {
row.style.display = '';
visibleCount++;
} else {
row.style.display = 'none';
hiddenCount++;
}
} else {
// Pokaż wszystkie wiersze
row.style.display = '';
visibleCount++;
}
});
console.log('[Tampermonkey KFZ] Filtrowanie zakończone - widoczne:', visibleCount, 'ukryte:', hiddenCount);
}
// Funkcja do ładowania wszystkich produktów
function loadAllProducts() {
console.log('[Tampermonkey KFZ] Ładuję wszystkie produkty...');
// Szukamy elementów paginacji - trzeba znaleźć je w kontekście tabeli pozycji faktury
const pager = document.querySelector('.o_field_x2many[name="invoice_line_ids"] .o_pager');
// Jeśli nie ma paginacji, to znaczy że jest mniej niż 41 produktów - wszystkie są już widoczne
if (!pager) {
console.log('[Tampermonkey KFZ] Nie ma paginacji - wszystkie produkty (< 41) są już widoczne');
return;
}
const pagerLimit = pager.querySelector('.o_pager_limit');
const pagerValue = pager.querySelector('.o_pager_value');
if (!pagerLimit || !pagerValue) {
console.log('[Tampermonkey KFZ] Nie znaleziono elementów paginacji');
return;
}
const totalProducts = pagerLimit.textContent.trim();
const currentRange = pagerValue.textContent.trim();
console.log('[Tampermonkey KFZ] Aktualny zakres:', currentRange, 'Całkowita liczba:', totalProducts);
// Jeśli wartości są puste, to znaczy że nie ma prawidłowej paginacji
if (!totalProducts || !currentRange) {
console.log('[Tampermonkey KFZ] Wartości paginacji są puste - wszystkie produkty są już widoczne');
return;
}
// Sprawdzamy, czy już są pokazane wszystkie produkty
if (currentRange.includes(`1-${totalProducts}`)) {
console.log('[Tampermonkey KFZ] Wszystkie produkty są już załadowane');
return;
}
console.log('[Tampermonkey KFZ] Zmieniam zakres z', currentRange, 'na 1-', totalProducts);
changePaginationRange(`1-${totalProducts}`);
}
// Funkcja do resetowania do domyślnego widoku
function resetToDefault() {
console.log('[Tampermonkey KFZ] Resetuję do domyślnego widoku...');
// Sprawdzamy czy w ogóle jest paginacja
const pager = document.querySelector('.o_field_x2many[name="invoice_line_ids"] .o_pager');
if (!pager) {
console.log('[Tampermonkey KFZ] Nie ma paginacji (< 41 produktów) - reset nie jest potrzebny');
return;
}
changePaginationRange('1-40');
}
function createTestButton() {
// Szukamy przycisku w zakładkach
const nav = document.querySelector('.o_notebook ul.nav.nav-tabs');
if (!nav) {
console.log('[Tampermonkey KFZ] Nie znaleziono nav-tabs');
return;
}
console.log('[Tampermonkey KFZ] Znaleziono nav-tabs, tworzę przycisk');
// Tworzymy element li
const li = document.createElement('li');
li.className = 'nav-item';
// Tworzymy link
const a = document.createElement('a');
a.href = '#';
a.className = 'nav-link';
a.textContent = 'Pokaż korygowane produkty';
// Dodajemy event listener
a.addEventListener('click', async (e) => {
e.preventDefault();
// Sprawdzamy aktualną nazwę
if (a.textContent === 'Pokaż korygowane produkty') {
a.textContent = 'Pokaż wszystko';
console.log('[Tampermonkey KFZ] Zmieniono nazwę na: Pokaż wszystko');
// Ładujemy wszystkie produkty
loadAllProducts();
// Po załadowaniu filtrujemy wiersze (ukrywamy wartość = 0)
setTimeout(() => {
toggleValueRows(true);
}, 1000);
} else {
a.textContent = 'Pokaż korygowane produkty';
console.log('[Tampermonkey KFZ] Zmieniono nazwę na: Pokaż korygowane produkty');
// Pokaż wszystkie wiersze
toggleValueRows(false);
// Resetujemy do domyślnego widoku
resetToDefault();
}
});
li.appendChild(a);
nav.appendChild(li);
console.log('[Tampermonkey KFZ] Przycisk dodany pomyślnie');
}
// Funkcja inicjalizująca
function init() {
console.log('[Tampermonkey KFZ] Inicjalizacja...');
// W aplikacji SPA parametry URL mogą być ustawiane asynchronicznie
// Czekamy do 10 sekund na poprawne parametry URL
let attempts = 0;
const maxAttempts = 100; // 100 * 100ms = 10 sekund
console.log('[Tampermonkey KFZ] Rozpoczynam sprawdzanie URL (max 100 prób co 100ms)');
// Nasłuchujemy na zmiany URL (hashchange)
window.addEventListener('hashchange', () => {
console.log('[Tampermonkey KFZ] 🎯 Hash changed!');
buttonAdded = false; // Resetujemy stan - możliwa nowa strona
lastHash = ''; // Resetujemy hash żeby wykryć zmianę
setTimeout(runScriptCheck, 200);
});
const urlCheckInterval = setInterval(() => {
attempts++;
// Log co 10 prób
if (attempts % 10 === 0 || attempts === 1) {
console.log('[Tampermonkey KFZ] Próba', attempts, '/', maxAttempts, 'sprawdzenia URL...');
}
runScriptCheck();
if (attempts >= maxAttempts) {
console.log('[Tampermonkey KFZ] ❌ Timeout po', attempts, 'próbach');
clearInterval(urlCheckInterval);
}
}, 100); // Sprawdzamy co 100ms
}
// Funkcja sprawdzająca elementy strony po potwierdzeniu URL
function startElementCheck() {
// Szukamy elementów strony
const checkInterval = setInterval(() => {
const nav = document.querySelector('.o_notebook ul.nav.nav-tabs');
console.log('[Tampermonkey KFZ] Sprawdzam nav-tabs:', !!nav);
if (nav) {
clearInterval(checkInterval);
createTestButton();
}
}, 500);
// Timeout po 10 sekundach
setTimeout(() => {
clearInterval(checkInterval);
console.log('[Tampermonkey KFZ] Timeout - nie znaleziono nav-tabs');
}, 10000);
}
// Start
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
|