Panoramica

Il linguaggio di scripting di JuliuS è un JavaScript esteso con direttive speciali. Ogni script è un file di testo (.js) composto da due tipi di istruzioni che coesistono:

  • Direttive JuliuS — righe che iniziano con //#*#, interpretate dal motore Delphi per controllare browser, timing, OS e flusso.
  • Blocchi JavaScript — codice JS puro racchiuso tra //#*#SNIPPET=BEGIN e //#*#SNIPPET=END, eseguito nel browser Chromium.
Nota: Le direttive //#*# sembrano commenti JS ma vengono intercettate dall'engine prima di qualsiasi valutazione JavaScript, garantendo piena compatibilità con editor JS standard.

Struttura di uno script

1

Intestazione / Commento

Titolo, descrizione, nome della compagnia/target.

2

GLOBALV — Dichiarazione variabili

Blocco GLOBALV=BEGIN / END con tutte le variabili di input.

3

Configurazione iniziale

SCREEN_SIZE, WAIT, TARGET_FRAME=MAIN.

4

Navigazione verso l'URL target

URL_GOTO seguito da WAIT per il caricamento.

5

Interazione con la pagina

Sequenza di SNIPPET, MOUSE_CLICK, WRITETO, IF/ELSE/ENDIF, WAIT.

6

Estrazione del risultato

Definizione della funzione JS di estrazione, EVALJS, CAPTURE_SCREENSHOT.

Ciclo di esecuzione

L'engine legge lo script riga per riga in un thread separato. Per ogni riga:

  • Se inizia con //#*# → viene interpretata come direttiva JuliuS.
  • Se è compresa tra SNIPPET=BEGIN e SNIPPET=END → viene accumulata e inviata al browser come JavaScript.
  • Se inizia con /* → l'engine salta tutte le righe fino al corrispondente */.
  • Altrimenti → la riga viene ignorata dall'engine.
⚠ Attenzione: Il codice JavaScript al di fuori dei blocchi SNIPPET non viene eseguito nel browser. Tutto il JS da eseguire va obbligatoriamente dentro un blocco SNIPPET.

GLOBALV — Variabili globali

dati
//#*#GLOBALV=BEGIN … //#*#GLOBALV=ENDDichiara le variabili dello script
Definisce il blocco delle variabili globali dello script. Tutto ciò che è compreso tra GLOBALV=BEGIN e GLOBALV=END viene caricato nella lista interna GlobalV di JuliuS e può essere iniettato nel browser con GLOBALV=INJECT. Ogni riga deve essere una dichiarazione JavaScript valida var nome="valore";. I valori vengono estratti dall'engine per l'interpolazione con la sintassi {{{NOME}}}.
//#*#GLOBALV=BEGIN var marca="HONDA"; var modello="XL 650 V TRANSALP"; var data_nasc="10/01/1986"; var cu="1"; //#*#GLOBALV=END

GLOBALV=INJECT

javascript
//#*#GLOBALV=INJECTInietta le variabili nel contesto JS del browser
Esegue il testo del blocco GlobalV nel contesto JavaScript del browser. Dopo l'inject, tutte le variabili del blocco GLOBALV sono disponibili come variabili JS nella pagina corrente e possono essere usate nei successivi blocchi SNIPPET. Poiché ogni navigazione azzera il contesto JS, è necessario re-iniettare dopo ogni cambio pagina.
//#*#GLOBALV=INJECT //#*#WAIT=1 //#*#SNIPPET=BEGIN document.getElementById('inputMarca').value = marca; //#*#SNIPPET=END
💡 Best practice: Ri-iniettare GLOBALV=INJECT dopo ogni navigazione verso una nuova pagina.

Interpolazione {{{VAR}}}

dati

Le variabili definite in GLOBALV possono essere interpolate nei parametri delle direttive JuliuS usando {{{NOME_VARIABILE}}}. L'engine sostituisce il placeholder con il valore prima di eseguire il comando. I nomi sono case-insensitive.

//#*#WRITETO="TEXT={{{MARCA}}}{{TAB}}"&"CHAR_INT_MS=200" // Se il placeholder racchiude una espressione JS, viene valutata a runtime: //#*#WRITETO="ELEMENTID={{{document.querySelector('.active').id}}}"&"TEXT=ciao"

HTTP_GET / HTTP_POST

http
//#*#HTTP_GET=... / //#*#HTTP_POST=...Chiama endpoint HTTP dallo script
Esegue una chiamata HTTP sincrona dal thread dello script e, se indicato il parametro VAR, salva la risposta testuale in GLOBALV. I parametri supportano l'interpolazione {{{VAR}}}, quindi URL, body e header possono usare valori dichiarati o prodotti durante l'esecuzione.
Iniezione immediata: Se indichi VAR, JuliuS inietta subito la variabile anche nel browser corrente. Uno SNIPPET immediatamente successivo puo quindi leggere la response senza aspettare un GLOBALV=INJECT. Dopo una navigazione serve comunque re-iniettare le variabili.

Parametri

ParametroTipoDescrizione
URLstringEndpoint da chiamare. Obbligatorio.
VARstringNome della variabile GLOBALV in cui salvare la risposta.
BODYstringPayload per HTTP_POST. Con HTTP_GET viene accodato alla URL come query string (?BODY o &BODY se la URL ha gia parametri). Supporta interpolazione.
CONTENTTYPEstringContent-Type del POST, ad esempio application/json o application/x-www-form-urlencoded.
TIMEOUTMSintegerTimeout connessione/risposta in millisecondi. Default: 30000.
HEADER_NomestringAggiunge un header HTTP. Gli underscore nel nome vengono convertiti in trattini, ad esempio HEADER_X_API_KEY diventa X-API-KEY.
Nota: Il parser separa i parametri solo quando dopo & trova una chiave nota, quindi query string e body form-urlencoded possono contenere &. CONTENTTYPE ha un alias equivalente CONTENT_TYPE.
⚠ Attenzione: l'elenco di chiavi note è condiviso con il parser di DOWNLOAD_UPLOAD e include anche FIELD, ONCE, CLEAR, DELETE, DELETEAFTERUPLOAD e FORM_*. Una stringa letterale come &FIELD= o &DELETE= dentro un BODY o una URL di HTTP_GET/HTTP_POST verrebbe interpretata come inizio di un nuovo parametro: evitare questi token nei valori oppure codificarli.
Placeholder: I placeholder {{{nome}}} vengono risolti prima dalle variabili GLOBALV; se non vengono trovati, JuliuS prova a valutarli nel contesto JavaScript del browser con EvalJS. Questo permette di usare nel BODY, nell'URL o negli header anche valori calcolati in uno SNIPPET precedente.
//#*#GLOBALV=BEGIN var api_key="..."; var request_id="ABC123"; var val1="pippo"; var val2="pluto"; //#*#GLOBALV=END //#*#HTTP_GET="URL=https://api.example.test/status?id={{{request_id}}}"&"VAR=http_response"&"HEADER_X_API_KEY={{{api_key}}}"&"TIMEOUTMS=45000" //#*#HTTP_GET="URL=https://api.example.test/status"&"VAR=http_response"&"BODY=id={{{request_id}}}&json=1" //#*#HTTP_POST="URL=https://api.example.test/jobs"&"VAR=http_response"&"CONTENTTYPE=application/json"&"HEADER_X_API_KEY={{{api_key}}}"&"BODY={"id":"{{{request_id}}}"}" //#*#HTTP_POST="URL=https://api.example.test/form"&"VAR=http_response"&"CONTENTTYPE=application/x-www-form-urlencoded"&"BODY=var1={{{val1}}}&var2={{{val2}}}" //#*#GLOBALV=INJECT //#*#SNIPPET=BEGIN console.log(http_response); //#*#SNIPPET=END
Attenzione: Non inserire chiavi o token direttamente negli script condivisi. Usa variabili locali o configurazioni esterne quando lo script deve essere versionato.

DOWNLOAD_UPLOAD ⚠️ non attiva

http
⚠ Non ancora agganciata al parser: ExecuteDownloadUploadCommand e tutta la logica di download/upload sono implementate in uFrmScript.pas/uMainBrowser.pas, ma il ciclo principale di esecuzione script (ExecuteScript) non ha alcun ramo StartsWith('//#*#DOWNLOAD_UPLOAD='). Inserire questa direttiva in uno script oggi non produce alcun effetto (no-op silenzioso). La sezione è mantenuta come riferimento per quando il collegamento verrà aggiunto: non usarla in script di produzione fino ad allora.
//#*#DOWNLOAD_UPLOAD=...Invia in POST multipart il prossimo download completato
Configura l'upload automatico del prossimo file scaricato dal browser. Il download resta gestito da Chromium, quindi usa la sessione/cookie del sito; quando CEF segnala il file come completato, JuliuS invia un POST multipart/form-data all'endpoint indicato.

Parametri

ParametroTipoDescrizione
URLstringEndpoint di upload. Obbligatorio.
FIELDstringNome del campo multipart che contiene il file. Default: file.
VARstringNome della variabile GLOBALV in cui salvare la response testuale dell'upload.
TIMEOUTMSintegerTimeout connessione/risposta in millisecondi. Default: 120000.
HEADER_NomestringHeader HTTP aggiuntivo. Gli underscore nel nome vengono convertiti in trattini.
FORM_NomestringCampo form multipart aggiuntivo, oltre al file. Supporta interpolazione.
ONCEbooleanSe true, la configurazione vale solo per il prossimo download. Default: true.
DELETE / DELETEAFTERUPLOADbooleanSe true, elimina il file locale dopo upload riuscito. Default: false.
CLEARbooleanSe true, rimuove la configurazione corrente senza attendere un download.
//#*#GLOBALV=BEGIN var token="..."; var job_id="12345"; //#*#GLOBALV=END //#*#DOWNLOAD_UPLOAD="URL=https://api.example.test/files"&"FIELD=file"&"VAR=upload_response"&"HEADER_AUTHORIZATION=Bearer {{{token}}}"&"FORM_jobId={{{job_id}}}"&"ONCE=true"&"TIMEOUTMS=120000" //#*#URL_GOTO=https://sito.example.test/report/download // Per disarmare manualmente: //#*#DOWNLOAD_UPLOAD="CLEAR=true"

URL_GOTO

navigazione
//#*#URL_GOTO=<url>Naviga il browser verso un URL
Forza il browser Chromium embedded a navigare verso l'URL specificato. L'operazione è asincrona: usare sempre WAIT subito dopo per attendere il caricamento completo della pagina prima di interagire con il DOM.
//#*#URL_GOTO=https://www.esempio.it/pagina-target //#*#WAIT=5

WAIT

controllo flusso
//#*#WAIT=<secondi>Pausa l'esecuzione per N secondi interi
Mette in pausa l'esecuzione dello script per il numero di secondi interi specificato. Usare attese brevi (1–3 s) per operazioni UI locali, attese più lunghe (5–15 s) dopo navigazioni o submit di form con round-trip server.
//#*#WAIT=3 //#*#WAIT=10

BACK

navigazione
//#*#BACKTorna alla pagina precedente
Equivale al pulsante "Indietro" del browser. Naviga alla pagina precedente nella history del browser. Seguire sempre con un WAIT e un GLOBALV=INJECT per ripristinare il contesto JS.
//#*#BACK //#*#WAIT=3 //#*#GLOBALV=INJECT

SCREEN_SIZE

navigazione
//#*#SCREEN_SIZE=<width>,<height>Imposta le dimensioni del pannello browser
Ridimensiona il pannello del browser embedded. Tutte le coordinate dei successivi MOUSE_CLICK e OS_BROWSER_CLICK devono essere calibrate sulla risoluzione impostata con questo comando.
//#*#SCREEN_SIZE=1024,768

MOUSE_CLICK

interazione CEF
//#*#MOUSE_CLICK=<X>,<Y>Click sintetico CEF a coordinate relative al browser
Simula un click del mouse nel browser CEF alle coordinate pixel specificate, relative al pannello. Agisce tramite l'API interna CEF. Per click su elementi che non rispondono agli eventi CEF (es. elementi con pointer-events:none, scrollbar native, dialog Windows) usare OS_BROWSER_CLICK.
//#*#MOUSE_CLICK=374,494 //#*#WAIT=1

WRITETO

interazione CEF
//#*#WRITETO="..."&"..."Simula digitazione da tastiera nel browser CEF
Simula la digitazione di testo in un campo HTML del browser CEF. I parametri sono separati da & e racchiusi tra virgolette doppie. Supporta interpolazione {{{VAR}}} e tasti speciali {{TASTO}}.

Parametri

ParametroTipoDescrizione
ELEMENTIDstringID HTML dell'elemento su cui mettere il focus. Usare none per saltare il focus.
FRAMENAMEstringNome del frame/iframe target. Se omesso usa il frame con focus corrente.
TEXTstringTesto da digitare. Supporta {{{VAR}}} e {{KEY}}.
CHAR_INT_MSintegerIntervallo ms tra un carattere e l'altro (default: 200).
CHAR_INT_RANDOMS / NSe S, ogni intervallo tra due caratteri diventa un valore casuale uniforme tra 0 e CHAR_INT_MS-1 (non una variazione attorno al valore configurato).
⚠ Interpolazione non uniforme: ELEMENTID supporta il fallback su valutazione JS (come HTTP_GET/HTTP_POST); il parametro TEXT supporta solo la sostituzione diretta delle variabili GLOBALV — un'espressione JS scritta dentro {{{...}}} nel TEXT non viene valutata a runtime.
//#*#WRITETO="ELEMENTID=ctl00_txtNome"&"TEXT={{{NOME}}}{{TAB}}"&"CHAR_INT_MS=150" //#*#WRITETO="TEXT={{SELECT_ALL}}{{CANC}}{{{MODELLO}}}"&"CHAR_INT_MS=200"&"CHAR_INT_RANDOM=N"

Tasti speciali

interazione CEF

All'interno del parametro TEXT del comando WRITETO:

{{ENTER}}Invio (↵)
{{TAB}}Tabulazione
{{CANC}}Canc (Delete)
{{DELETE}}Canc (alias)
{{BACK_SPACE}}Backspace (←)
{{ESC}}Escape
{{ESCAPE}}Escape (alias)
{{HOME}}Inizio riga
{{END}}Fine riga
{{ARROW_DOWN}}Freccia giù
{{ARROW_UP}}Freccia su
{{ARROW_LEFT}}Freccia sinistra
{{ARROW_RIGHT}}Freccia destra
{{SELECT_ALL}}Seleziona tutto (Ctrl+A)
Nota: nel codice sorgente esiste anche l'alias storico {{ARROW_RIGTH}} (typo di "RIGHT"), mantenuto per compatibilità con script esistenti — negli script nuovi usare {{ARROW_RIGHT}}. {{SELECT_ALL}} è gestito a un livello diverso rispetto agli altri placeholder: divide il testo sul marker e invia la combinazione Ctrl+A in quel punto, direttamente dentro la routine di digitazione. Qualsiasi altro carattere non elencato (inclusi accentati e simboli) viene digitato come carattere letterale.

SNIPPET

javascript
//#*#SNIPPET=BEGIN[&NOFRAME] … //#*#SNIPPET=ENDEsegue un blocco JavaScript nel browser
Tutto il codice tra SNIPPET=BEGIN e SNIPPET=END viene eseguito nel contesto JavaScript del browser Chromium. È il meccanismo principale per interagire con il DOM. L'opzione NOFRAME forza l'esecuzione nel frame principale (window) invece del frame con focus corrente.
//#*#SNIPPET=BEGIN $('#ddlMarca').val(marca).keydown(); //#*#SNIPPET=END //#*#SNIPPET=BEGIN&NOFRAME window.scrollTo(0, 0); //#*#SNIPPET=END
⚠ Attenzione: I blocchi SNIPPET non possono essere annidati. Ogni SNIPPET=BEGIN deve avere il suo SNIPPET=END.

EVALJS

javascript
//#*#EVALJS=<espressione JS>Valuta un'espressione JS e ne memorizza il risultato
Esegue una singola espressione JavaScript nel browser (timeout 10 s) e memorizza il valore restituito come risultato dell'operazione corrente, recuperabile poi via API con ?operation=getresult. Pensato per chiamare funzioni di estrazione già definite in un SNIPPET precedente.
//#*#EVALJS=preventivo(); //#*#EVALJS=document.getElementById("risultato").innerText

TARGET_FRAME

navigazione
//#*#TARGET_FRAME=MAIN | POPUPSeleziona il frame/finestra target
Imposta il contesto di esecuzione per i successivi comandi. MAIN seleziona il frame principale; POPUP seleziona una finestra popup figlia identificata dall'URL nella riga successiva.
ValoreDescrizione
MAINFrame principale della finestra browser corrente.
POPUPPopup figlio. Deve essere seguito da //#*#TARGET_URL=<url>.
//#*#TARGET_FRAME=MAIN //#*#TARGET_FRAME=POPUP //#*#TARGET_URL=https://www.esempio.it/popup-login

Regole di matching di TARGET_URL

ValoreComportamento
* o vuotoUsa l'ultimo popup attivo (nessun match per URL).
URL esattoCerca un popup la cui URL corrisponde esattamente.
URL parzialeSe non trova corrispondenza esatta, cerca un popup la cui URL contiene il valore indicato (match a sottostringa).
⚠ Attenzione: Se il popup con l'URL specificato non è aperto, l'engine lancia un'eccezione e interrompe lo script.

IF / ELSE / ENDIF

controllo flusso
//#*#IF= … //#*#ELSE … //#*#ENDIFEsecuzione condizionale basata su espressione JS
Permette di eseguire blocchi di direttive in modo condizionale. L'espressione dopo IF= viene valutata nel browser tramite EvalJS: se il risultato è truthy il blocco IF viene eseguito e il blocco ELSE saltato; se è falsy il blocco IF viene saltato e il blocco ELSE (opzionale) eseguito. Il blocco ELSE è opzionale. Gli IF possono essere annidati: l'engine gestisce correttamente la profondità di annidamento.

Valori considerati falsy

Stringa vuota "", "false", "0", "null", "undefined". Qualsiasi altro valore è considerato truthy.

// Esempio base: IF senza ELSE //#*#IF=document.querySelector('#btnAccetta') !== null //#*#SNIPPET=BEGIN document.querySelector('#btnAccetta').click(); //#*#SNIPPET=END //#*#WAIT=2 //#*#ENDIF // Esempio con ELSE //#*#IF=document.querySelector('.errore-pagina') !== null //#*#PAUSE // c'è un errore: sospende per intervento manuale //#*#ELSE //#*#SNIPPET=BEGIN $('#btnAvanti').click(); //#*#SNIPPET=END //#*#WAIT=8 //#*#ENDIF // Esempio con variabili GlobalV //#*#IF=guida === "Libera" //#*#SNIPPET=BEGIN $('#rdoGuidaLibera').click(); //#*#SNIPPET=END //#*#ENDIF // Esempio con IF annidati //#*#IF=cu < 5 //#*#IF=guida === "Libera" //#*#MOUSE_CLICK=200,300 //#*#ELSE //#*#MOUSE_CLICK=250,300 //#*#ENDIF //#*#ENDIF
Note tecniche: L'espressione viene valutata via EvalJS nel thread principale. Le variabili iniettate con GLOBALV=INJECT sono disponibili nell'espressione. Il risultato della valutazione viene scritto nel log di JuliuS per facilitare il debug (IF [expr] = valore → true/false).

PAUSE

controllo flusso
//#*#PAUSESospende l'esecuzione fino a ripresa manuale
Sospende l'esecuzione dello script fino a quando l'utente non riprende manualmente (tramite UI o API ?operation=start). Utile per interventi manuali (es. risoluzione captcha, login manuale) in punti critici del flusso. Spesso usato in combinazione con IF per sospendere solo in caso di condizioni anomale.
Ripresa non solo manuale: se il Captcha Interceptor è attivo e un resolver remoto invia un messaggio 'go' via WSS, lo script si sblocca e riparte automaticamente. Timeout di sicurezza: se non arriva attività remota per più di 120s, JuliuS esce comunque dalla pausa.
//#*#IF=document.querySelector('.captcha-box') !== null //#*#PAUSE // sospende: l'operatore risolve il captcha //#*#ENDIF

Commenti

controllo flusso

JuliuS supporta entrambe le sintassi di commento JavaScript. I blocchi /* ... */ sono utili per disabilitare temporaneamente intere sezioni, incluse direttive JuliuS.

// Commento su riga singola — ignorato dall'engine /* Blocco multi-riga — tutto ciò che è compreso tra /* e */ viene saltato dall'engine JuliuS, incluse eventuali direttive //#*# al suo interno. */

CAPTURE_SCREENSHOT

output CEF
//#*#CAPTURE_SCREENSHOTScreenshot del pannello browser CEF
Cattura lo stato visuale corrente del browser CEF e salva il file JPG nella cartella Settings.Data.screenShotPath. Il nome file è costruito automaticamente come ExcelLogLineNameBase_N.jpg. Il percorso viene aggiunto alla screenShotList del risultato operazione, recuperabile via API. Se al momento della cattura è attivo TARGET_FRAME=POPUP, viene salvata la pagina completa del popup corrente invece della finestra browser principale.
//#*#CAPTURE_SCREENSHOT //#*#SNIPPET=BEGIN $('#btnAvanti').click(); //#*#SNIPPET=END

OS_SCREENSHOT

output OS
//#*#OS_SCREENSHOT[=nomeFile]Screenshot dell'intero desktop Windows
Cattura l'intero desktop Windows (non solo il browser CEF) e salva il file JPG. Utile per catturare dialog nativi, popup di sistema e qualsiasi finestra fuori dal browser. Il percorso generato viene aggiunto alla screenShotList del risultato operazione.
VarianteDescrizione
//#*#OS_SCREENSHOTNome file automatico: ExcelLogLineNameBase_OS_N.jpg
//#*#OS_SCREENSHOT=nomeFileNome file personalizzato: nomeFile.jpg
//#*#OS_SCREENSHOT //#*#OS_SCREENSHOT=popup_conferma
Differenza con CAPTURE_SCREENSHOT: CAPTURE_SCREENSHOT cattura solo il pannello CEF. OS_SCREENSHOT cattura l'intero desktop Windows incluse finestre native, taskbar e popup di sistema.

Funzione di risultato

javascript

Per restituire un risultato recuperabile via API, definire una funzione JS in un blocco SNIPPET e richiamarla con EVALJS. Per convenzione si chiama preventivo(), ma è possibile usare qualsiasi nome.

//#*#SNIPPET=BEGIN function preventivo() { var el = document.querySelector('#tabs-Proposta0-label font'); return el ? el.innerHTML : 'non trovato'; } //#*#SNIPPET=END //#*#WAIT=2 //#*#EVALJS=preventivo(); // Recupera via API: GET /?operation=getresult // GET /?getresult=preventivo
Formato risposta: la risposta di operation=getresult / getresult=<nome> non è la stringa grezza restituita dalla funzione, ma un oggetto JSON con almeno i campi OperationId, rawResult (il valore ritornato dalla funzione), StartedAt e screenShotList (elenco degli screenshot catturati durante l'esecuzione). Il client deve leggere rawResult dal JSON, non trattare l'intera risposta come testo semplice.
Fuori scope: il server HTTP di JuliuS espone anche altre operation= (controllo script, DOM/ispezione pagina, screenshot, input OS, log di rete/API) non correlate al linguaggio di scripting — vedi API HTTP Reference.

OS_MOUSE_MOVE

OS — mouse
//#*#OS_MOUSE_MOVE=<X>,<Y>Sposta il cursore a coordinate assolute di schermo
Sposta il cursore del mouse alle coordinate assolute di schermo usando le API del sistema operativo. Agisce sull'intero desktop, non solo sul browser CEF. Utile per interagire con dialog nativi Windows, popup di sistema o altre applicazioni.
//#*#OS_MOUSE_MOVE=640,480 //#*#WAIT=1

OS_MOUSE_CLICK

OS — mouse
//#*#OS_MOUSE_CLICKClick sinistro nella posizione corrente del cursore SO
Simula un click sinistro del mouse nella posizione corrente del cursore di sistema. Usare dopo OS_MOUSE_MOVE. Agisce a livello SO e può interagire con qualsiasi finestra visibile sul desktop.
//#*#OS_MOUSE_MOVE=500,350 //#*#OS_MOUSE_CLICK

OS_MOUSE_RCLICK

OS — mouse
//#*#OS_MOUSE_RCLICKClick destro nella posizione corrente del cursore SO
Simula un click destro del mouse nella posizione corrente del cursore di sistema, per aprire menu contestuali nativi del SO o di applicazioni Windows.
//#*#OS_MOUSE_MOVE=500,350 //#*#OS_MOUSE_RCLICK //#*#WAIT=1

OS_MOUSE_MOVE_CLICK

OS — mouse
//#*#OS_MOUSE_MOVE_CLICK=<X>,<Y>Move + click sinistro SO in un'unica istruzione
Combina OS_MOUSE_MOVE e OS_MOUSE_CLICK in una sola direttiva usando coordinate assolute di schermo. Le coordinate dipendono dalla posizione della finestra JuliuS sul desktop: se la finestra viene spostata, le coordinate devono essere ricalcolate. Per click indipendenti dalla posizione della finestra, preferire OS_BROWSER_CLICK.
//#*#OS_MOUSE_MOVE_CLICK=640,400 //#*#WAIT=1

OS_MOUSE_DOUBLE_CLICK

OS — mouse
//#*#OS_MOUSE_DOUBLE_CLICK=<X>,<Y>Doppio click a coordinate assolute di schermo
Sposta il cursore a X,Y ed esegue due click sinistri rapidi (con 80ms di pausa tra i due) per simulare un doppio click nativo del sistema operativo. Usa coordinate assolute di schermo.
//#*#OS_MOUSE_DOUBLE_CLICK=300,200 //#*#WAIT=1

OS_MOUSE_MOVE_PATH

OS — mouse
//#*#OS_MOUSE_MOVE_PATH=x1,y1,d1;x2,y2,d2;...Muove il cursore SO lungo una sequenza di punti
Muove il cursore del sistema operativo attraverso una sequenza di punti, per simulare un movimento del mouse più naturale rispetto a un singolo salto. È la direttiva generata automaticamente dal Macro Recorder in modalità "Uman" (vedi Macro Recorder), ma può essere usata anche scritta a mano.
Sintassi: elenco di terne x,y,delay separate da ;. delay è il tempo in millisecondi da attendere prima di muoversi verso quel punto (clampato a un massimo di 400ms per segmento).
//#*#OS_MOUSE_MOVE_PATH=300,200,0;340,210,40;380,225,40;420,240,40 //#*#WAIT=1

OS_BROWSER_CLICK

OS — mouse
//#*#OS_BROWSER_CLICK=<X>,<Y>Click SO a coordinate relative al pannello browser
Esegue un click sinistro a livello sistema operativo usando coordinate relative al pannello browser CEF — la stessa origine di MOUSE_CLICK e degli snapshot. Internamente, JuliuS converte le coordinate browser in coordinate assolute di schermo tramite ClickOnBrowserRelative, quindi il click funziona correttamente indipendentemente da dove è posizionata la finestra JuliuS sul desktop e dal fattore di scala DPI. È la scelta più robusta quando si vuole un click OS su un elemento del browser.

Quando usarlo rispetto alle alternative

DirettivaTipo clickCoordinateQuando usarla
MOUSE_CLICKCEF internoRelative browserCaso generale: elementi DOM standard
OS_MOUSE_MOVE_CLICKSOAssolute schermoClick su finestre esterne al browser
OS_BROWSER_CLICKSORelative browserElementi che non rispondono al CEF, scrollbar, dropdown nativi, pointer-events:none
//#*#OS_BROWSER_CLICK=374,494 //#*#WAIT=1

OS_BROWSER_INFO

OS — debug
//#*#OS_BROWSER_INFOScrive nel log le coordinate della finestra e del browser
Scrive nel log di JuliuS le informazioni sulla posizione e le dimensioni della finestra principale e del pannello browser CEF, incluse le coordinate assolute di schermo e il fattore di scala DPI. Non produce output nello script né interagisce con il browser. È uno strumento di sviluppo e debug: utile per calibrare le coordinate assolute da usare nei comandi OS_MOUSE_MOVE e OS_MOUSE_MOVE_CLICK.
//#*#OS_BROWSER_INFO // Esempio output nel log: // [OS_BROWSER_INFO] {"mainForm":{"left":100,"top":50,"width":1200,"height":800}, // "browser":{"left":0,"top":60,"width":1024,"height":768, // "screenLeft":100,"screenTop":110},"scaleFactor":1.25}

OS_KEY_PRESS

OS — tastiera
//#*#OS_KEY_PRESS=<keycode>Preme un tasto tramite keycode numerico VK
Invia la pressione di un tasto alla finestra attiva del sistema operativo tramite il suo keycode Virtual Key. A differenza di WRITETO che scrive nel browser CEF, questo comando agisce a livello SO e funziona su qualsiasi finestra attiva: dialog nativi Windows, form non web, applicazioni desktop.
KeycodeTastoKeycodeTasto
13ENTER27ESC
9TAB32SPAZIO
8BACKSPACE46DELETE
37← LEFT38↑ UP
39→ RIGHT40↓ DOWN
112–123F1–F1265–90A–Z
//#*#OS_KEY_PRESS=13 // ENTER //#*#OS_KEY_PRESS=27 // ESC

OS_KEY

OS — tastiera
//#*#OS_KEY=<nome_tasto>Preme un tasto per nome (alternativa leggibile a OS_KEY_PRESS)
Alternativa più leggibile a OS_KEY_PRESS: accetta il nome del tasto invece del keycode numerico. Agisce a livello sistema operativo sulla finestra attiva. I nomi non riconosciuti vengono loggati e ignorati senza interrompere lo script.
ValoreTastoValoreTasto
enterENTEResc / escapeESC
tabTABbackspaceBACKSPACE
spaceSPAZIOarrow_up
arrow_downarrow_left
arrow_right
//#*#OS_KEY=enter //#*#OS_KEY=arrow_down //#*#OS_KEY=tab

OS_KEY_COMBO

OS — tastiera
//#*#OS_KEY_COMBO=<modifier>+<key>Combinazione di tasti SO (Ctrl/Shift/Alt + tasto)
Simula una combinazione di tasti a livello SO tramite keybd_event. La sintassi è modificatore+tasto in minuscolo. Disponibile solo su Windows: su altre piattaforme il comando viene loggato come non implementato e ignorato senza interrompere lo script.
CampoValori accettati
modifierctrl, shift, alt
keyLettera singola (az), oppure: f4f12, tab, enter, esc, del, home, end, pageup, pagedown
//#*#OS_KEY_COMBO=ctrl+c // Copia //#*#OS_KEY_COMBO=ctrl+v // Incolla //#*#OS_KEY_COMBO=ctrl+a // Seleziona tutto //#*#OS_KEY_COMBO=alt+f4 // Chiudi finestra //#*#OS_KEY_COMBO=shift+tab // Tab inverso

RNDWAIT

controllo flusso
//#*#RNDWAIT=<secondi>Attesa casuale per simulare comportamento umano
Attende un numero di secondi scelto casualmente nell'intervallo [N div 2 .. N]. Da usare al posto di WAIT fissi sulle pause lunghe (submit form, caricamento pagina) per ridurre il rischio di rilevamento anti-bot.
//#*#RNDWAIT=10 // attende tra 5s e 10s (random) //#*#RNDWAIT=6 // attende tra 3s e 6s (random)
💡 Best practice: usa RNDWAIT sulle pause lunghe e mantieni WAIT=1 per le sincronizzazioni brevi dove la variabilità non serve.

CAPTCHA_Y

controllo flusso
//#*#CAPTCHA_Y=<pixel>Coordinata Y di scroll per centrare il captcha
Imposta la coordinata Y in pixel a cui scrollare la pagina quando l'interceptor captcha rileva un captcha attivo. Serve a portare il div del captcha al centro dello schermo prima che JuliuS invii l'immagine al resolver automatico.
//#*#CAPTCHA_Y=350 // scrolla a Y=350 per centrare il captcha
⚠ Attenzione: va posizionato prima della navigazione verso la pagina che contiene il captcha. Se omesso, JuliuS usa la coordinata configurata nelle impostazioni globali (Settings.Data.captchaScrollCoordComma).

Captcha Interceptor & Solver Bridge

funzionalità applicativa
Non è una direttiva //#*#: è un sistema dell'applicazione, configurato in Settings, documentato qui come contesto perché influenza il comportamento a runtime di PAUSE e CAPTCHA_Y.

Captcha Interceptor + operatore remoto via WSS

Due toggle indipendenti in Settings: AI Resolver (abilita il rilevamento automatico dei captcha) e WSS (abilita la connessione al server WebSocket remoto, indirizzo configurabile). Quando il frame con focus corrisponde a un captcha (esclusi i badge invisibili), JuliuS centra la view sulla coordinata di CAPTCHA_Y e invia screenshot live al resolver remoto via WSS. Un operatore/resolver connesso può cliccare e scrollare da remoto sul browser JuliuS; quando ha risolto, invia un messaggio 'go' che sblocca automaticamente un eventuale PAUSE in corso e fa ripartire lo script. Se non arriva attività remota per più di 120s, JuliuS esce comunque dalla pausa.

Solver Bridge — API richiamabile da SNIPPET

A differenza del canale sopra, questa è un'API JavaScript utilizzabile direttamente dentro un blocco SNIPPET, indipendente dal toggle "AI Resolver":

//#*#SNIPPET=BEGIN var reqId = crypto.randomUUID(); myextension.solverRequest(reqId, 'image_b64', base64Immagine); //#*#SNIPPET=END //#*#WAIT=3 //#*#EVALJS=window.__juliusSolver && window.__juliusSolver.responses['ID_GENERATO'] ? window.__juliusSolver.responses['ID_GENERATO'].answer : ''

La risposta arriva in modo asincrono in window.__juliusSolver.responses[reqId] = {success, answer, error} (oppure via callback registrata in window.__juliusSolver.callbacks[reqId]).

⚠ Nota implementativa attuale: nel codice questo bridge non passa dal canale WSS descritto sopra — è temporaneamente collegato (bypass esplicito, commentato come "TEST DIRETTO" nel sorgente) a un server Ollama locale hardcoded (qwen3-vl:8b, endpoint OCR) invece che al resolver remoto via WSS. Verificare lo stato del codice prima di fare affidamento su questa via per script di produzione.

RESTART_CHROMIUM

sessione
//#*#RESTART_CHROMIUMReset in-memory della sessione Chromium
Esegue un reset in-memory della sessione Chromium senza riavviare fisicamente il browser, via DevTools Protocol: naviga su about:blank, Network.clearBrowserCache, Network.clearBrowserCookies, Storage.clearDataForOrigin (localStorage/sessionStorage/IndexedDB), riapplica le preferenze Chromium e torna su about:blank. Attende automaticamente ~3s di reinizializzazione. Esposto anche come tool MCP julius_restart_chromium().
//#*#RESTART_CHROMIUM //#*#WAIT=2 //#*#URL_GOTO=https://... //#*#WAIT=5 //#*#GLOBALV=INJECT
Quando usarlo: per ottenere una sessione pulita tra un preventivo e l'altro senza l'overhead della cancellazione su disco.

DELETE_CHROMIUM_CACHE

sessione
//#*#DELETE_CHROMIUM_CACHEReset profondo: in-memory + cache su disco
Reset profondo: pulisce tutto in-memory via DevTools (come RESTART_CHROMIUM) e poi cancella fisicamente la directory cache su disco (GlobalCEFApp.RootCache). Attende automaticamente ~4s (più di RESTART_CHROMIUM per via dell'I/O filesystem). Esposto anche come tool MCP julius_delete_chromium_cache().
//#*#DELETE_CHROMIUM_CACHE //#*#WAIT=2 //#*#URL_GOTO=https://...
RESTART_CHROMIUMDELETE_CHROMIUM_CACHE
Tipo resetIn-memory (DevTools)In-memory + filesystem
Velocità~3s~5s (I/O disco)
Cancella file su discoNo
Quando usareReset tra un preventivo e l'altroCache corrotta, reset completo pre-sessione
⚠ Attenzione: usare solo quando RESTART_CHROMIUM non è sufficiente (cache corrotta, sessioni persistenti problematiche, primo avvio di una nuova sessione di lavoro).

Macro Recorder

registrazione

JuliuS può generare lo script automaticamente osservando le interazioni reali dell'utente sul browser embedded. Si attiva con il ToggleSwitch REC nella finestra Script. È il modo più veloce per ottenere una bozza funzionante da rifinire.

1

Attivazione (REC → ON)

Viene iniettato un listener JS nel frame principale, negli iframe nominati e nei popup TChildForm. Si auto-protegge dalla doppia installazione (window.__jrInstalled) e resta inerte finché window.__jrActive non è true.

2

Cattura eventi

Intercetta in capture phase gli eventi click e change, costruisce un selettore CSS stabile (#id o cssPath con :nth-of-type/[name]) e invia un payload JSON via myextension.sendresulttobrowser(json, 'jsRecordEvent').

3

Generazione script

TfrmScript.RecordEvent riceve il JSON e accoda nell'editor le direttive JuliuS corrispondenti, parametrizzando i valori in GLOBALV.

4

Disattivazione (REC → OFF)

Imposta window.__jrActive=false su tutti i frame; il listener resta installato ma inerte.

Modalità "Uman"

Un secondo ToggleSwitch (separato da REC) abilita, quando REC è attivo, anche la registrazione del movimento reale del mouse a livello di sistema operativo:

  • Il movimento viene campionato da un hook OS globale già installato, con un throttling di circa 1 campione ogni 40ms e uno scarto dei movimenti inferiori a 6px.
  • I punti vengono bufferizzati (fino a 50) e, appena prima del prossimo click o input registrato, vengono emessi in un'unica riga //#*#OS_MOUSE_MOVE_PATH=... (vedi sezione dedicata).
  • Il ridimensionamento del pannello browser durante la registrazione genera anche righe //#*#SCREEN_SIZE=W,H, ma solo se l'header dello script è già stato generato.

Mappatura eventi → direttive generate

Evento utenteOutput nello script
Primo evento, editor vuotoHeader completo: GLOBALV=BEGIN/END, SCREEN_SIZE=1024,768, WAIT=1, TARGET_FRAME=MAIN, URL_GOTO=<pagina>, WAIT=8, GLOBALV=INJECT
Primo evento, editor non vuotoGarantisce un blocco GLOBALV e accoda le azioni in append
Attesa tra due azioni//#*#WAIT=N proporzionale ai secondi reali (parte intera, emesso solo se ≥1s, clamp 1–20s)
Cambio URL//#*#GLOBALV=INJECT
Cambio frame / popup//#*#TARGET_FRAME=<frame>; per i popup TARGET_FRAME=POPUP + TARGET_URL=*
Ridimensionamento finestra (modalità Uman)//#*#SCREEN_SIZE=W,H
Movimento mouse reale (modalità Uman)//#*#OS_MOUSE_MOVE_PATH=x1,y1,d1;x2,y2,d2;..., emesso subito prima del prossimo click/input
Input su campo con idVariabile in GLOBALV + //#*#WRITETO="ELEMENTID=<id>"&"TEXT={{{var}}}"&"CHAR_INT_MS=60" (intervallo fisso a 60ms)
Input su campo senza idVariabile + SNIPPET con querySelector(sel).value=var + eventi input/change
ClickCommento // [REC] click … con coordinate alternative //#*#MOUSE_CLICK=x,y + SNIPPET con scrollIntoView() + .click() + WAIT=1
Parametrizzazione automatica: ogni input digitato diventa una variabile GLOBALV (nome derivato da id/name: caratteri non alfanumerici → _, prefisso v_ se il nome inizia con una cifra, duplicati resi univoci con suffisso _N). Ri-digitazioni sullo stesso campo aggiornano la stessa variabile invece di crearne una nuova.
⚠ Bozza, non production-ready: i widget jQuery UI autocomplete e i dropdown nativi vengono catturati come change semplici. Rifinisci sostituendo con i pattern dropdown a cascata, aggiungi gestione cookie/captcha e la funzione preventivo() di estrazione risultato.

Best practice

Gestione banner cookie

//#*#SNIPPET=BEGIN&NOFRAME (function() { var btn = document.getElementById('onetrust-accept-btn-handler'); if (btn) { btn.click(); return; } var fallback = Array.from(document.querySelectorAll('button')) .find(function(b) { return b.textContent.trim().toLowerCase().includes('accetta'); }); if (fallback) { fallback.click(); return; } })(); //#*#SNIPPET=END //#*#WAIT=3

Re-inject variabili dopo navigazione

//#*#SNIPPET=BEGIN $('#btnAvanti').click(); //#*#SNIPPET=END //#*#WAIT=8 //#*#GLOBALV=INJECT // ← obbligatorio dopo ogni navigazione

Compilazione dropdown con jQuery

//#*#SNIPPET=BEGIN $('#lblctl00_ddlCampo').val(variabile).keydown(); //#*#SNIPPET=END //#*#WAIT=2 //#*#SNIPPET=BEGIN $('#ulctl00_ddlCampo li a').each(function() { if ($(this).text() == variabile) { $(this).mouseenter().click(); } }); //#*#SNIPPET=END

Esecuzione condizionale con IF

Usare IF per gestire variazioni di pagina o errori senza interrompere il flusso principale:

// Clicca il pulsante solo se è presente e visibile //#*#GLOBALV=INJECT //#*#IF=(function(){ var b=document.querySelector('#btnCalcola'); return b && b.offsetParent!==null; })() //#*#SNIPPET=BEGIN document.querySelector('#btnCalcola').click(); //#*#SNIPPET=END //#*#WAIT=5 //#*#ELSE //#*#OS_BROWSER_CLICK=915,684 // fallback: click OS sulle coordinate //#*#WAIT=3 //#*#ENDIF

Click OS con coordinate relative al browser

Preferire OS_BROWSER_CLICK a OS_MOUSE_MOVE_CLICK per non dover ricalcolare le coordinate assolute se la finestra viene spostata:

// ✗ Fragile: dipende dalla posizione assoluta della finestra //#*#OS_MOUSE_MOVE_CLICK=1015,734 // ✓ Robusto: coordinate relative al browser, indipendenti dalla posizione finestra //#*#OS_BROWSER_CLICK=374,494

Script completo — template con IF

// TEMPLATE: form + condizione + estrazione risultato //#*#GLOBALV=BEGIN var nome="Mario"; var data_nasc="01/01/1985"; var guida="Libera"; //#*#GLOBALV=END //#*#SCREEN_SIZE=1024,768 //#*#TARGET_FRAME=MAIN //#*#URL_GOTO=https://www.esempio.it/form //#*#WAIT=5 //#*#GLOBALV=INJECT // Accetta cookie (solo se presente) //#*#IF=document.getElementById('onetrust-accept-btn-handler') !== null //#*#SNIPPET=BEGIN&NOFRAME document.getElementById('onetrust-accept-btn-handler').click(); //#*#SNIPPET=END //#*#WAIT=2 //#*#ENDIF // Compila nome //#*#WRITETO="ELEMENTID=inputNome"&"TEXT={{{NOME}}}{{TAB}}"&"CHAR_INT_MS=150" //#*#WAIT=1 // Tipo guida condizionale //#*#IF=guida === "Libera" //#*#OS_BROWSER_CLICK=200,400 //#*#ELSE //#*#OS_BROWSER_CLICK=260,400 //#*#ENDIF //#*#WAIT=1 //#*#CAPTURE_SCREENSHOT // Submit //#*#SNIPPET=BEGIN document.getElementById('btnSubmit').click(); //#*#SNIPPET=END //#*#WAIT=10 //#*#GLOBALV=INJECT // Gestione errore post-submit //#*#IF=document.querySelector('.msg-errore') !== null //#*#OS_SCREENSHOT=errore_submit //#*#PAUSE //#*#ENDIF // Estrazione risultato //#*#SNIPPET=BEGIN function preventivo() { return document.querySelector('.risultato-finale')?.innerText || ''; } //#*#SNIPPET=END //#*#WAIT=2 //#*#EVALJS=preventivo(); //#*#CAPTURE_SCREENSHOT