JS pane: skrypty Run-on-demand, bez auto-run na każdym wejściu
JS reguła JustZix odpala się automatycznie, kiedy URL pasuje. Świetnie dla rzeczy które zawsze mają działać — auto-skip cookie bannerów, custom shortcuts. Ale niektóre skrypty są destrukcyjne: „opróżnij koszyk", „skasuj draft maila", „resetuj formularz". Tych nie chcesz auto-run. Chcesz kliknąć ▶ tylko gdy chcesz. To jest JS pane (v2.13.56+).
Trzy okna JS — który do czego
| Typ okna | Kiedy odpala | Use case |
|---|---|---|
| JS reguła | Auto na każdym load matching URL | Auto-skip cookies, custom shortcuts, GTM logger |
| JS Console | Każde Ctrl+Enter = nowy eval | Ad-hoc REPL, jednorazowe sprawdzenia |
| JS pane | Tylko po Ctrl+Enter / klik ▶ | Persistent kod, destruktywne actions, bulk ops |
JS pane wygląda prawie jak CSS pane (textarea, draggable, kolorowa kropka), ale w headerze ma dodatkowy przycisk ▶ Run. Kod siedzi w textarea, nie wykonuje się nigdy sam z siebie — wyjątkiem jest resume po reload (jeśli przed F5 zostało coś w sessionStorage, JustZix odpala to ponownie żeby wrócić do stanu sprzed odświeżenia).
Pierwsze użycie
- Options JustZix → folder/grupa/reguła → „Okna" → „+ JS pane".
- Nazwa: „Empty cart", kolor: amber (domyślny #D65D0E).
- Wejdź na
shop.com/cart. Pane pojawia się w top-right z headerem („• Empty cart [▶]") i pustą textareą. - Wpisz:
document.querySelectorAll('.cart-item .remove-btn') .forEach(btn => btn.click()); - Ctrl+Enter (lub klik ▶). Wszystkie przyciski „Usuń" klikane.
Dirty state — wizualnie wiesz że jest zmiana
Po wpisaniu / edycji kodu, dopóki go nie odpalisz (lub nie cofniesz do ostatnio uruchomionej wersji), Run button ma wyróżniony stan „dirty" (z customowym kolorem runColor — od v2.13.64 możesz wybrać własny). To wizualny cue: „masz niezapisane / nieodpalone zmiany".
Klik ▶ → kod się odpala, dirty state znika. Cofnij textareę do wcześniejszej wartości → dirty znów się pojawia. JustZix porównuje aktualną treść z el.dataset.jzLastRun.
Error overlay — nie musisz mieć DevTools otwartego
Gdy eval rzuca exception, na dole pane'a pojawia się czerwony pasek (.jz-pane-error):
JS error: Cannot read properties of null (reading 'click')
Klik ▶ ponownie z poprawionym kodem → error znika. Bez wymachiwania F12. Dla async errorów (setTimeout(...) rzucający) overlay nie złapie — to znane ograniczenie i async errors trzeba śledzić w DevTools Console / JS Console JustZix.
Persistent vs ulotny — który scenariusz
JS pane treść persystuje w sessionStorage['jz_pane_{id}_content'] per tab. Konsekwencje:
- F5 / wewnętrzna nawigacja — pane się remount-uje, textarea wczytuje kod, auto-resume uruchamia go ponownie. Czyli stan strony po reload = stan po pierwszym uruchomieniu.
- Nowa karta na tej samej domenie — pane pojawia się pusty. Każda karta ma własny sessionStorage.
- Zamknięcie karty — treść kodu w pane'ie znika. Sama definicja pane'a (nazwa, kolor, scope) zostaje bo to chrome.storage, ale textarea wraca do pustki.
Jeśli chcesz kod na stałe (nawet po zamknięciu karty) — to nie pane, tylko JS reguła. Pane = scratchpad z możliwością Run.
Use case 1 — destrukcyjne akcje per stan
Cleanup w panelu admina sklepu. Akcja „Wyczyść wszystkie produkty z koszyka demo":
// Działa tylko gdy klikniesz ▶. Auto-run = katastrofa.
if (!location.href.includes('/admin/demo')) {
throw new Error('Tylko dla /admin/demo');
}
const rows = document.querySelectorAll('tr.product');
console.log(`Usuwam ${rows.length} produktów...`);
for (const row of rows) {
await fetch('/api/products/' + row.dataset.id, { method: 'DELETE' });
row.remove();
}
console.log('Done.');
Defense: guard na URL pattern + nazwa pane'a „CLEANUP DEMO" + amber dot. Trudno przypadkiem.
Use case 2 — bulk operations
Każdy z 50 użytkowników musi zostać oznaczony jako „zweryfikowany". UI dopuszcza klik per user. JS pane:
const rows = document.querySelectorAll('.user-row:not(.verified)');
let count = 0;
for (const row of rows) {
row.querySelector('.btn-verify')?.click();
await new Promise(r => setTimeout(r, 200)); // throttle żeby API nie krzyknęło
count++;
}
console.log(`Verified ${count} users.`);
Jeden klik ▶, 50 użytkowników. Sleep 200 ms żeby nie zalać API. Trzy razy szybsze niż prawdziwy bulk endpoint którego nie ma.
Use case 3 — scripted demo
Pokazujesz klientowi flow „dodaj 3 produkty + przejdź do checkout + wypełnij dane testowe". 30 sekund każdorazowo. Skrypt w pane'ie odpala wszystko w 2 sekundy:
// Demo flow
[1, 2, 3].forEach(i => document.querySelector(`[data-product-id="${i}"] .add-btn`)?.click());
await new Promise(r => setTimeout(r, 500));
document.querySelector('.checkout-btn').click();
await new Promise(r => setTimeout(r, 1000));
Object.entries({
email: 'demo@example.com', name: 'Demo', address: 'Test 1'
}).forEach(([k, v]) => {
const el = document.querySelector(`[name="${k}"]`);
if (el) { el.value = v; el.dispatchEvent(new Event('input', { bubbles: true })); }
});
Klient widzi flow „auto-pilot". Profesjonalnie. Bez wpisywania w real time.
Pułapki
- Async errors nie pojawiają się w overlay —
setTimeout(() => { throw new Error('x') }, 100)wyrzuci w global console, nie w pane error box. Workaround: wrappy try/catch w środku async funkcji. - Resume po reload zaskakuje — jeśli wczoraj nawpisywałeś coś destruktywnego, dziś reload → wykona ponownie. Best practice: pane od którego nie chcesz auto-resume → kasuj zawartość przed zamknięciem karty (Ctrl+A, Delete, ▶ na pustej = clears
jzLastRun). - Top-level await NIE działa. Wrap w IIFE:
(async () => { await ... })(). - MAIN world access — JS pane wykonuje się w page context (przez
chrome.scripting.executeScriptworld=MAIN), więc widzi globale strony (React, Redux store, jQuery itp.). To samo co JS reguły.
Co dalej
JS pane jest 2. typem „okna na froncie" w JustZix. Wcześniej pisaliśmy o CSS pane (live edytor CSS) i JS Console (REPL). Cała trójka razem to mini-IDE wprost w karcie przeglądarki, scoped per domena.
Zainstaluj JustZix i miej skrypty Run-on-demand na każdej stronie, bez ryzyka auto-run.
Oceń ten wpis
Brak ocen — oceń jako pierwszy.