From b526cea64a961ba101837303eefcfbea264690c5 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 01:07:20 +0100 Subject: [PATCH 01/19] Introduction to browser events italian translation. --- .../01-introduction-browser-events/article.md | 306 +++++++++--------- 1 file changed, 151 insertions(+), 155 deletions(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 19394e49e..c5515d7c1 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -1,93 +1,90 @@ -# Introduction to browser events +# Introduzione agli aventi del browser -*An event* is a signal that something has happened. All DOM nodes generate such signals (but events are not limited to DOM). +*Un evento* è un segnale che sta ad indicare che è avvenuto qualcosa. Tutti i nodi DOM generano questi segnali (anche se gli eventi non sono limitati al DOM). -Here's a list of the most useful DOM events, just to take a look at: +Ecco quindi una lista, degli eventi DOM più utili: -**Mouse events:** -- `click` -- when the mouse clicks on an element (touchscreen devices generate it on a tap). -- `contextmenu` -- when the mouse right-clicks on an element. -- `mouseover` / `mouseout` -- when the mouse cursor comes over / leaves an element. -- `mousedown` / `mouseup` -- when the mouse button is pressed / released over an element. -- `mousemove` -- when the mouse is moved. +**Eventi del mouse:** +- `click` -- quando si clicca col mouse su un elemento (i dispositivi touch lo generano tramite il tocco). +- `contextmenu` -- quando si clicca col tasto destro su un elemento. +- `mouseover` / `mouseout` -- quando il cursore passa sopra/abbandona un elemento. +- `mousedown` / `mouseup` -- quando viene premuto/rilasciato il pulsante del mouse su un elemento. +- `mousemove` -- quando si sposta il mouse. -**Keyboard events:** -- `keydown` and `keyup` -- when a keyboard key is pressed and released. +**Eventi da tastiera:** +- `keydown` e `keyup` -- quando viene premuto e rilasciato un tasto. -**Form element events:** -- `submit` -- when the visitor submits a `
`. -- `focus` -- when the visitor focuses on an element, e.g. on an ``. +**Eventi degli elementi del form:** +- `submit` -- quando l'utente invia un ``. +- `focus` -- quando l'utente attiva il focus su un elemento, ad esempio su un ``. -**Document events:** -- `DOMContentLoaded` -- when the HTML is loaded and processed, DOM is fully built. +**Eventi del Document:** +- `DOMContentLoaded` -- quando l'HTML viene caricato e processato, e la struttura del DOM è stata completata. -**CSS events:** -- `transitionend` -- when a CSS-animation finishes. +**Eventi dei CSS:** +- `transitionend` -- quando termina un'animazione CSS (CSS-animation). -There are many other events. We'll get into more details of particular events in next chapters. +Ci sono tanto altri eventi più specifici, che verranno affrontati in dettaglio nei prossimi capitoli. -## Event handlers +## Gestori di evento -To react on events we can assign a *handler* -- a function that runs in case of an event. +Per reagire agli eventi possiamo assegnare un *gestore* (handler), che non è che una funzione che viene eseguita contestualmente alla generazione di un evento. -Handlers are a way to run JavaScript code in case of user actions. +I gestori, quindi, sono un modo per eseguire codice JavaScript al verificarsi delle azioni dell'utente ed esistono vari modi per assegnare un evento. -There are several ways to assign a handler. Let's see them, starting from the simplest one. +Partiamo dal più semplice. -### HTML-attribute +### Attributo HTML (HTML-attribute) -A handler can be set in HTML with an attribute named `on`. +Un gestore può essere impostato in HTML con un attributo chiamato `on`. -For instance, to assign a `click` handler for an `input`, we can use `onclick`, like here: +Ad esempio, per assegnare un gestore al `click` di un `input`, possiamo usare `onclick`: ```html run - + ``` +Al click del mouse, il codice dentro `onclick` verrà eseguito. -On mouse click, the code inside `onclick` runs. +Nota bene che dentro `onclick` useremo gli apici singoli, in quanto l'attributo stesso è già inserito all'interno di apici doppi. Se ci dimenticassimo che il codice stesse dentro l'attributo, ed usassimo gli apici doppi come in questo caso: `onclick="alert("Click!")"`, il codice non funzionerebbe. -Please note that inside `onclick` we use single quotes, because the attribute itself is in double quotes. If we forget that the code is inside the attribute and use double quotes inside, like this: `onclick="alert("Click!")"`, then it won't work right. +Un attributo HTML non è un buon posto per scrivere tanto codice, quindi è molto meglio creare una funzione JavaScript per poterla richiamare. -An HTML-attribute is not a convenient place to write a lot of code, so we'd better create a JavaScript function and call it there. - -Here a click runs the function `countRabbits()`: +In questo esempio, al click viene eseguita la funzione `countRabbits()`: ```html autorun height=50 - + ``` +Come sappiamo, gli attributi HTML non sono case-sensitive, quindi scrivere `ONCLICK` va bene tanto quanto `onClick` e `onCLICK`...ma solitamente vengono scritti in minuscolo: `onclick`. -As we know, HTML attribute names are not case-sensitive, so `ONCLICK` works as well as `onClick` and `onCLICK`... But usually attributes are lowercased: `onclick`. - -### DOM property +### Proprietà del DOM -We can assign a handler using a DOM property `on`. +Possiamo assegnare un gestore usando una proprietà DOM `on`. -For instance, `elem.onclick`: +Ad esempio, `elem.onclick`: ```html autorun - + ``` +Se il gestore viene assegnato usando un attributo HTML, il browser lo riconosce, crea una nuova funzione partendo dal contenuto dell'attributo e la scrive nella proprietà del DOM. -If the handler is assigned using an HTML-attribute then the browser reads it, creates a new function from the attribute content and writes it to the DOM property. +In sostanza, questa modalità equivale alla precedente. -So this way is actually the same as the previous one. - -These two code pieces work the same: +I due codici messi a confronto, infatti, lavorano alla stessa maniera: 1. Only HTML: @@ -106,147 +103,146 @@ These two code pieces work the same: */!* ``` +L'unica differenza è che nel primo esempio, l'attributo HTML viene usato per inizializzare il `button.onclick`, invece nel secondo per inizializzare lo script. -In the first example, the HTML attribute is used to initialize the `button.onclick`, while in the second example -- the script, that's all the difference. - -**As there's only one `onclick` property, we can't assign more than one event handler.** +**Dal momento che c'è solo una proprietà `onclick`, non è possibile assegnare più di un gestore evento.** -In the example below adding a handler with JavaScript overwrites the existing handler: +Aggiungendo un gestore tramite JavaScript, si va a sovrascrivere il gestore esistente: ```html run height=50 autorun - + ``` -To remove a handler -- assign `elem.onclick = null`. +Per rimuovere un gestore, assegnare `elem.onclick = null`. -## Accessing the element: this +## Accedere all'elemento: this -The value of `this` inside a handler is the element. The one which has the handler on it. +Il valore di `this` all'interno di un gestore è l'elemento contenente il gestore. -In the code below `button` shows its contents using `this.innerHTML`: +Qui il `button` mostra il suo contenuto tramite `this.innerHTML`: ```html height=50 autorun - + ``` -## Possible mistakes +## Possibili errori -If you're starting to work with events -- please note some subtleties. +Se stai affrontando da poco l'argomento degli eventi, nota bene alcune sottigliezze. -We can set an existing function as a handler: +Possiamo impostare come gestore una funzione esistente: ```js function sayThanks() { - alert('Thanks!'); + alert('Grazie!'); } elem.onclick = sayThanks; ``` -But be careful: the function should be assigned as `sayThanks`, not `sayThanks()`. +Ma attenzione: la funzione deve essere assegnata scrivendo `sayThanks`, e non `sayThanks()`. ```js -// right +// corretto button.onclick = sayThanks; -// wrong +// errato button.onclick = sayThanks(); ``` -If we add parentheses, then `sayThanks()` becomes is a function call. So the last line actually takes the *result* of the function execution, that is `undefined` (as the function returns nothing), and assigns it to `onclick`. That doesn't work. +Se aggiungessimo le parentesi, allora `sayThanks()` diverrebbe una chiamata a funzione, di conseguenza il valore dell'assegnazione dell'ultima riga dell'esempio, sarebbe il risultato della chiamata, il quale, a sua volta, sarebbe `undefined` (dato che la funzione non restituisce nulla), che verrebbe assegnato ad `onclick`. Ovviamente così non potrebbe andare bene, ed inoltre non sarebbe nemmeno l'effetto voluto. -...On the other hand, in the markup we do need the parentheses: +...D'altra parte, però, nel markup abbiamo bisogno delle parentesi: ```html ``` -The difference is easy to explain. When the browser reads the attribute, it creates a handler function with body from the attribute content. +La differenza è molto semplice: quando il browser legge l'attributo, crea una funzione che fa da gestore, il cui corpo è il contenuto dell'attributo. -So the markup generates this property: +Quindi il markup crea questa proprietà: ```js button.onclick = function() { *!* - sayThanks(); // <-- the attribute content goes here + sayThanks(); // <-- il contenuto dell'attributo va a finire qui */!* }; ``` -**Don't use `setAttribute` for handlers.** +**Non usare `setAttribute` per i gestori.** -Such a call won't work: +Ed ancora, una chiamata del genere non funzionerà: ```js run no-beautify -// a click on will generate errors, -// because attributes are always strings, function becomes a string +// un click sul genera errori, +// perché gli attributi sono sempre stringhe, e la funzione diventa una stringa document.body.setAttribute('onclick', function() { alert(1) }); ``` -**DOM-property case matters.** +**Il case della proprietà DOM è rilevante.** -Assign a handler to `elem.onclick`, not `elem.ONCLICK`, because DOM properties are case-sensitive. +Assegnare un gestore a `elem.onclick`, e non a `elem.ONCLICK`, in quanto le proprietà del DOM sono case-sensitive. ## addEventListener -The fundamental problem of the aforementioned ways to assign handlers -- we can't assign multiple handlers to one event. +Il problema principale della sopracitata maniera di assegnare i gestori è che non abbiamo modo di assegnare dei gestori multipli a un evento. -Let's say, one part of our code wants to highlight a button on click, and another one wants to show a message on the same click. +Mettiamo il caso che una parte del nostro codice serva ad evidenziare un pulsante al click, e che un altro serva a mostrare un messaggio al medesimo click. -We'd like to assign two event handlers for that. But a new DOM property will overwrite the existing one: +Per fare questo sarebbe bello poter assegnare due eventi distinti, ma sappiamo che ogni nuova proprietà DOM con lo stesso nome, sovrascriverà la precedente: ```js no-beautify input.onclick = function() { alert(1); } // ... -input.onclick = function() { alert(2); } // replaces the previous handler +input.onclick = function() { alert(2); } // sostituisce il gestore precedente ``` -Developers of web standards understood that long ago and suggested an alternative way of managing handlers using special methods `addEventListener` and `removeEventListener`. They are free of such a problem. +Gli sviluppatori degli standard web hanno intuito la cosa tempo addietro, e hanno suggerito un modo alternativo per trattare i gestori, usando i metodi speciali `addEventListener` e `removeEventListener`, i quali non sono affetti da questi problemi. -The syntax to add a handler: +Ecco la sintassi per aggiungere un gestore: ```js element.addEventListener(event, handler, [options]); ``` `event` -: Event name, e.g. `"click"`. +: Nome dell'evento, ad esempio `"click"`. `handler` -: The handler function. +: La funzione che fa da gestore. `options` -: An additional optional object with properties: - - `once`: if `true`, then the listener is automatically removed after it triggers. - - `capture`: the phase where to handle the event, to be covered later in the chapter . For historical reasons, `options` can also be `false/true`, that's the same as `{capture: false/true}`. - - `passive`: if `true`, then the handler will not call `preventDefault()`, we'll explain that later in . +: Un oggetto opzionale aggiuntivo con delle proprietà: + - `once`: se `true`, il listener viene rimosso automaticamente una volta innescato. + - `capture`: la fase in cui deve essere gestito l'evento, argomento affrontato più avanti nel capitolo . Per ragioni storiche, `options` possono essere anche `false/true`, ed è equivale a scrivere `{capture: false/true}`. + - `passive`: se `true`, il gestore non chiamerà `preventDefault()`, anche questo, verrà spiegato successivamente nel capitolo . -To remove the handler, use `removeEventListener`: +Per rimuovere l'evento, si usa `removeEventListener`: ```js element.removeEventListener(event, handler, [options]); ``` -````warn header="Removal requires the same function" -To remove a handler we should pass exactly the same function as was assigned. +````warn header="La rimozione prevede la stessa identica funzione" +Per rimuovere un gestore dobbiamo passare come parametro, la stessa funzione che abbiamo usato per l'assegnazione. -This doesn't work: +Il seguente codice non fa quello che ci aspetteremmo: ```js no-beautify -elem.addEventListener( "click" , () => alert('Thanks!')); +elem.addEventListener( "click" , () => alert('Grazie!')); // .... -elem.removeEventListener( "click", () => alert('Thanks!')); +elem.removeEventListener( "click", () => alert('Grazie!')); ``` -The handler won't be removed, because `removeEventListener` gets another function -- with the same code, but that doesn't matter, as it's a different function object. +Il gestore non verrà rimosso, perchè `removeEventListener` prende come parametro un'altra funzione: è certamente con lo stesso codice, ma questo non ha alcuna rilevanza, dal momento che è un oggetto funzione differente (fanno riferimento a due differenti indirizzi di memoria N.d.T). -Here's the right way: +La maniera corretta per farlo è questa: ```js function handler() { @@ -258,112 +254,111 @@ input.addEventListener("click", handler); input.removeEventListener("click", handler); ``` -Please note -- if we don't store the function in a variable, then we can't remove it. There's no way to "read back" handlers assigned by `addEventListener`. +Nota bene: se non assegnassimo la funzione a una variabile, non potremmo rimuoverla: non c'è alcun modo di "risalire" ai gestori assegnati tramite `addEventListener`. ```` -Multiple calls to `addEventListener` allow to add multiple handlers, like this: +Chiamate multiple a `addEventListener` permettono di aggiungere gestori multipli: ```html run no-beautify ``` -As we can see in the example above, we can set handlers *both* using a DOM-property and `addEventListener`. But generally we use only one of these ways. +Come visto nell'esempio, possiamo impostare i gestori *in entrambi i modi* sia con l'ausilio di una proprietà DOM che di `addEventListener`. Generalmente però, scegliamo un solo approccio. -````warn header="For some events, handlers only work with `addEventListener`" -There exist events that can't be assigned via a DOM-property. Only with `addEventListener`. +````warn header="Per alcuni eventi, i gestori funzionano solo con `addEventListener`" +Esistono eventi che non possono essere assegnati tramite una proprietà DOM, ma solo con `addEventListener`. -For instance, the `DOMContentLoaded` event, that triggers when the document is loaded and DOM is built. +Un esempio di ciò, è l'evento `DOMContentLoaded`, innescato quando viene completamente caricato il documento e costruita tutta la struttura del DOM. ```js -// will never run +// non viene mai eseguito document.onDOMContentLoaded = function() { - alert("DOM built"); + alert("DOM costruito"); }; ``` ```js -// this way it works +// in questo modo funziona document.addEventListener("DOMContentLoaded", function() { - alert("DOM built"); + alert("DOM costruito"); }); ``` -So `addEventListener` is more universal. Although, such events are an exception rather than the rule. +Conseguentemente, `addEventListener` è più universale, benché questi eventi siano un'eccezione più che la regola. ```` -## Event object +## Oggetto evento -To properly handle an event we'd want to know more about what's happened. Not just a "click" or a "keydown", but what were the pointer coordinates? Which key was pressed? And so on. +Per gestire correttamente un evento, vorremmo saperne di più su cosa è avvenuto. Non solamente se è stato un "click" o un "keydown", ma, ad esempio, quali erano le coordinate del puntatore? Che tasto è stato premuto? E così via. -When an event happens, the browser creates an *event object*, puts details into it and passes it as an argument to the handler. +Quando c'è un evento, il browser crea un *oggetto evento* (event object), inserisce i dettagli al suo interno e lo passa come argomento al gestore. -Here's an example of getting pointer coordinates from the event object: +Ecco un esempio per ottenere le coordinate dall'oggetto evento: ```html run - + ``` -Some properties of `event` object: +Alcune proprietà dell'oggetto `event`: `event.type` -: Event type, here it's `"click"`. +: Tipo di evento, in questo caso è un `"click"`. `event.currentTarget` -: Element that handled the event. That's exactly the same as `this`, unless the handler is an arrow function, or its `this` is bound to something else, then we can get the element from `event.currentTarget`. +: L'elemento che ha gestito l'evento. Questo è equivalente a `this`, ma se il gestore è una arrow function, o se il suo `this` è legato a qualcos'altro, possiamo usare `event.currentTarget`. `event.clientX / event.clientY` -: Window-relative coordinates of the cursor, for pointer events. +: Coordinate del cursore relative alla Window, per eventi del puntatore. -There are more properties. Many of them depend on the event type: keyboard events have one set of properties, pointer events - another one, we'll study them later when we come to different events in details. +Esistono tante altre proprietà., molte delle quali dipendono dal tipo di evento: gli eventi della tastiera hanno un gruppo di proprietà, gli eventi del puntatore un altro ancora, e li studieremo più avanti quando andremo a vedere i vari eventi nel dettaglio. -````smart header="The event object is also available in HTML handlers" -If we assign a handler in HTML, we can also use the `event` object, like this: +````smart header="L'oggetto evento è disponibile anche nei gestori HTML" +Se assegniamo un gestore dentro l'HTML, possiamo usare l'oggetto `evento`: ```html autorun height=60 ``` -That's possible because when the browser reads the attribute, it creates a handler like this: `function(event) { alert(event.type) }`. That is: its first argument is called `"event"`, and the body is taken from the attribute. +Questo è possibile perché quando il browser legge l'attributo, crea un gestore con questa forma: `function(event) { alert(event.type) }`. Il primo argomento viene chiamato `"event"`, e il corpo è preso dall'attributo. ```` -## Object handlers: handleEvent +## Gestori oggetto: handleEvent -We can assign not just a function, but an object as an event handler using `addEventListener`. When an event occurs, its `handleEvent` method is called. - -For instance: +Con `addEventListener` possiamo assegnare non solo una funzione, ma anche un oggetto. Quando viene generato un evento, viene chiamato il suo metodo `handleEvent`. +Ad esempio: ```html run - + ``` -As we can see, when `addEventListener` receives an object as the handler, it calls `obj.handleEvent(event)` in case of an event. - -We could also use a class for that: +Come possiamo osservare, se `addEventListener` riceve un oggetto come gestore, allora chiama `obj.handleEvent(event)` nel caso ci sia un evento. +Possiamo usare anche una classe: ```html run - + ``` -Here the same object handles both events. Please note that we need to explicitly setup the events to listen using `addEventListener`. The `menu` object only gets `mousedown` and `mouseup` here, not any other types of events. +L'oggetto gestisce entrambi gli eventi. Nota bene che usando `addEventListener` dobbiamo impostare esplicitamente gli eventi affinché rimangano in ascolto. + -The method `handleEvent` does not have to do all the job by itself. It can call other event-specific methods instead, like this: +Nel nostro esempio, l'oggetto `menu` rimane in ascolto solamente per `mousedown` e `mouseup`, e nessun altro tipo di evento. +Tuttavia, il metodo `handleEvent` non deve necessariamente fare tutto il lavoro da solo. Può infatti chiamare altri metodi specifici per tipologia di evento: ```html run - + ``` -Now event handlers are clearly separated, that may be easier to support. +Qui i gestori sono chiaramente separati, il che può essere più comodo da gestire. -## Summary +## Riepilogo -There are 3 ways to assign event handlers: +Ci sono 3 modalità per assegnare dei gestori di evento: -1. HTML attribute: `onclick="..."`. -2. DOM property: `elem.onclick = function`. -3. Methods: `elem.addEventListener(event, handler[, phase])` to add, `removeEventListener` to remove. +1. Attributo HTML: `onclick="..."`. +2. Proprietà DOM: `elem.onclick = function`. +3. Metodi: `elem.addEventListener(event, handler[, phase])` per aggiungerlo, `removeEventListener` per rimuoverlo. -HTML attributes are used sparingly, because JavaScript in the middle of an HTML tag looks a little bit odd and alien. Also can't write lots of code in there. +Gli attributi HTML vengono usati raramente, perchè un JavaScript nel bel mezzo di un tag HTML, non solo è un po' strano, ma è anche avulso dal contesto. Inoltre in questo modo non vi si può inserire dentro tanto codice. -DOM properties are ok to use, but we can't assign more than one handler of the particular event. In many cases that limitation is not pressing. +Le proprietà DOM si possono usare, ma non potremo assegnare più di un gestore per un particolare evento. In molti casi questa limitazione non è troppo pesante. -The last way is the most flexible, but it is also the longest to write. There are few events that only work with it, for instance `transitionend` and `DOMContentLoaded` (to be covered). Also `addEventListener` supports objects as event handlers. In that case the method `handleEvent` is called in case of the event. +L'ultimo modo è il più flessibile, ma è anche il più lungo da scrivere. Alcuni eventi funzionano solo con quest'ultima modalità, ad esempio `transitionend` e `DOMContentLoaded` (affrontato più avanti). Inoltre `addEventListener` supporta gli oggetti come gestori di evento. In questo caso, però, verrà chiamato il metodo `handleEvent` al verificarsi degli eventi. -No matter how you assign the handler -- it gets an event object as the first argument. That object contains the details about what's happened. +Non importa come assegni un gestore, in ogni caso il primo argomento passato sarà un oggetto evento, contenente i dettagli su ciò che è avvenuto. -We'll learn more about events in general and about different types of events in the next chapters. +Nei prossimi capitoli, avremo modo di approfondire il tema degli eventi in generale ed le loro differenti tipologie. From d397c21692bf3459e90ee0cea7a2f33158ce7799 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 12:15:30 +0100 Subject: [PATCH 02/19] Delete article.md --- 5-network/12-server-sent-events/article.md | 266 --------------------- 1 file changed, 266 deletions(-) delete mode 100644 5-network/12-server-sent-events/article.md diff --git a/5-network/12-server-sent-events/article.md b/5-network/12-server-sent-events/article.md deleted file mode 100644 index 414c52456..000000000 --- a/5-network/12-server-sent-events/article.md +++ /dev/null @@ -1,266 +0,0 @@ -# Server Sent Events - -La specifica [Server-Sent Events](https://html.spec.whatwg.org/multipage/comms.html#the-eventsource-interface) descrive una classe built-in `EventSource`, che mantiene la connessione con il server e permette di ricevere eventi da esso. - -In modo simile ai `WebSocket`, la connessione è persistente. - -Ci sono però delle differenze sostanziali: - -| `WebSocket` | `EventSource` | -|-------------|---------------| -| Bidirezionale: sia il client che il server possono scambiare messaggi | Unidirezionale: solamente il server può inviare messaggi | -| Dati binari e testuali | Solo testuali | -| Protocollo WebSocket | HTTP standard | - -`EventSource` è un modo meno potente di comunicare con il server rispetto ai `WebSocket`. - -Perché dovremmo usarli? - -La ragione principale: è semplice da usare. In molte applicazioni, la potenza dei `WebSocket` è anche troppa. - -Se abbiamo necessità di ricevere un flusso di dati da un server: che siano messaggi di chat o variazioni di prezzo dei mercati. Allora è ciò per cui `EventSource` è fatto. Supporta anche l'auto riconnessione, la qualcosa dovremmo invece implementare manualmente nei `WebSocket`. Oltretutto, è un normalissimo HTTP, e non un nuovo protocollo. - -## Ottenere i messaggi - -Per cominciare a ricevere messaggi, dobbiamo solamente creare un `new EventSource(url)`. - -Il browser si connetterà all'url e terrà la connessione aperta, in attesa di eventi. - -Il server dovrebbe rispondere con status 200 ed header `Content-Type: text/event-stream`, dopodiché mantenere aperta la connessione e scrivere i messaggi all'interno di esso in un formato speciale del tipo: - -``` -data: Message 1 - -data: Message 2 - -data: Message 3 -data: of two lines -``` - -- Un messaggio di testo segue la stringa `data:`, lo spazio dopo la virgola è opzionale. -- I messaggi sono delimitati con un doppio line break `\n\n`. -- Per inviare un line break `\n`, possiamo inviare immediatamente un altro `data:` (il terzo messaggio nell'esempio precedente). - -In pratica, i messaggi complessi sono solitamente inviati tramite oggetti codificati in JSO. I Line-breaks sono codificati come `\n`, e in questo modo i messaggi `data:` multiriga non sono necessari - -Ad esempio: - -```js -data: {"user":"John","message":"First line*!*\n*/!* Second line"} -``` - -...In questo modo possiamo assumere che ogni `data` contenga esattamente un messaggio. - -Per ognuno di questi messaggi, viene generato l'evento `message`: - -```js -let eventSource = new EventSource("/events/subscribe"); - -eventSource.onmessage = function(event) { - console.log("New message", event.data); - //logghera' 3 volte per il data stream poco sopra -}; - -// oppure eventSource.addEventListener('message', ...) -``` - -### Richieste Cross-origin - -`EventSource` supporta le richieste cross-origin, come `fetch` e qualunque altro metodo di rete. Possiamo usare qualunque URL: - -```js -let source = new EventSource("https://another-site.com/events"); -``` -Il server remoto otterrà l'header `Origin` e dovrà rispondere con `Access-Control-Allow-Origin` per continuare. - -Per inviare credenziali, dovremmo impostare le opzioni aggiuntive `withCredentials`, in questo modo: - -```js -let source = new EventSource("https://another-site.com/events", { - withCredentials: true -}); -``` - -Si prega di guardare il capitolo per maggiori informazioni sugli headers cross-origin. - - -## Riconnessione - -In fase di creazione, `new EventSource` si connette al server, e se la connessione si interrompe -- si riconnette. - -Ciò è molto conveniente, dal momento che non ci dobbiamo curare della cosa. - -C'è un piccolo ritardo tra le riconnessioni, pochi secondi di default. - -Il server può impostare il ritardo raccomandato usando `retry:` nella risposta (in millisecondi) - -```js -retry: 15000 -data: Hello, I set the reconnection delay to 15 seconds -``` - -Il `retry:` può arrivare insieme ad altri dati, o come messaggio singolo. - -Il browser dovrebbe attendere questi millisecondi prima di riconnettersi. O anche di più, ad esempio se il browser sa (dall'OS) che non c'è connessione in quel momento, può attendere fino a quando la connessione non ritorna, e successivamente riprovare. - -- Se il server vuole che il browser smetta di riconnettersi, dovrebbe rispondere con uno status HTTP 204. -- Se il browser vuole chiudere la connessione, dovrebbe chiamare il metodo `eventSource.close()`: - -```js -let eventSource = new EventSource(...); - -eventSource.close(); -``` -Inoltre, non avverrà alcuna riconnessione se la risposta ha un `Content-type` non valido o se il suo HTTP status è diverso da 301, 307, 200 o 204. In questi casi verrà emesso l'evento `"error"`, e il browser non si riconnetterà. - -```smart -Quando una connessione è finalemente chiusa, non ci sarà modo di "riaprirla". Se volessimo riconnetterci nuovamente, dovremmo ricreare un nuovo `EventSource`. -``` - -## Message id - -Quando una connessione si interrompe per motivi di problemi di rete, ogni lato non può essere sicuro di quale messaggi siano stati ricevuti, e quali no. -Per riprendere correttamente la connessione, ogni messaggio dovrebbe avere un campo `id`, come questo: -``` -data: Message 1 -id: 1 - -data: Message 2 -id: 2 - -data: Message 3 -data: of two lines -id: 3 -``` -Quando viene ricevuto un messaggio con `id:`, il browser: - -- Imposta la proprietà `eventSource.lastEventId` su quel valore. -- In fase di riconnessione invia l'header `Last-Event-ID` con quell'`id`, in modo da permettere al server di reinviare i messaggi successivi. - -```smart header="Inserisci `id:` dopo `data:`" -Nota bene: l'`id` viene aggiunto dopo il messaggio `data` dal server, per assicurarsi che `lastEventId` venga aggiornato solamente dopo che il messaggio sia stato ricevuto. -``` - -## Stato della conessione: readyState - -L'oggetto `EventSource` possiede la proprietà `readyState`, che può assumere uno dei seguenti valori: - -```js no-beautify -EventSource.CONNECTING = 0; // connessione o riconnessione -EventSource.OPEN = 1; // connesso -EventSource.CLOSED = 2; // connessione chiusa -``` - -Quando viene creato un oggetto, o se la connessione è assente, viene valorizzato sempre a `EventSource.CONNECTING` (equivale a `0`). - -Possiamo interrogare questa proprietà per sapere lo stato di `EventSource`. - -## Tipi di evento - -Di base l'oggetto `EventSource` genera tre eventi: - -- `message` -- un messaggio ricevuto, disponibile come `event.data`. -- `open` -- la connessione è aperta. -- `error` -- la connessaione non può essere stabilita, ad esempio, il server ha risposto con lo status HTTP 500. - -Il server può specificare un altro tipo di evento con `event: ...` all'inizio dell'evento. - -Per esempio: - -``` -event: join -data: Bob - -data: Hello - -event: leave -data: Bob -``` - -Per gestire eventi custom, dobbiamo usare `addEventListener`, e non `onmessage`: - -```js -eventSource.addEventListener('join', event => { - alert(`Joined ${event.data}`); -}); - -eventSource.addEventListener('message', event => { - alert(`Said: ${event.data}`); -}); - -eventSource.addEventListener('leave', event => { - alert(`Left ${event.data}`); -}); -``` - -## Esempio completo - -Qui c'è il server che invia messaggi con `1`, `2`, `3`, ed infine `bye` interrompendo la connessione. - -Dopo il browser si riconnette automaticamente. - -[codetabs src="eventsource"] - -## Riepilogo - -L'oggetto `EventSource` stabilisce automaticamente una connessione persistente e permette al server di inviare dei messaggi attraverso di essa. - -Offrendo: -- Riconnessione automatica, con timeout di `retry` regolabili. -- Id dei messaggi per riprendere gli eventi, l'ultimo id ricevuto viene inviato nell'header `Last-Event-ID` in fase di riconnessione. -- Lo stato corrente è dentro la proprietà `readyState`. - -Ciò rende `EventSource` una valida alternativa ai `WebSocket`, il quale è più a basso livello e manca di alcune funzionalità built-in (sebbene possano essere implementate). - -In molte applicazioni reali, la potenza di `EventSource` è già sufficiente. - -Supportato in tutti i browser moderni (non IE). - -La sintassi è: - -```js -let source = new EventSource(url, [credentials]); -``` - -Il secondo argomento consta di una sola opzione possibile: `{ withCredentials: true }`, la quale permette di inviare credenziali cross-origin. - -Complessivamente la sicurezza del cross-origin è la stessa di `fetch` e altri metodi di rete. - -### Proprietà di un oggetto `EventSource` - -`readyState` -: Lo stato corrente della connessione: uno tra `EventSource.CONNECTING (=0)`, `EventSource.OPEN (=1)` o `EventSource.CLOSED (=2)`. - -`lastEventId` -: L'ultimo `id` ricevuto.In fase di riconnessione il browser lo invia nell'header `Last-Event-ID`. - -### Metodi - -`close()` -: Chiude la connessione. - -### Eventi - -`message` -: Messagio ricevuto, il dato è dentro `event.data`. - -`open` -: La connessione è stabilita. - -`error` -: In caso di errori, inclusi la connessione persa (con riconnessione automatica) ed errori fatali. Possiamo controllare `readyState` per vedere se è stata tentata la riconnessione. - -Il server può impostare un evento personalizzato dentro `event:`. Questi eventi andrebbero gestiti usando `addEventListener`, e non `on`. - -### Formato della risposta del server - -Il server invia messaggi, delimitati da `\n\n`. - -Un messaggio può avere i seguenti campi: - -- `data:` -- corpo del messaggio, una sequenza di `data` multipli viene interpretata come un messaggio singolo, con `\n` tra la parti. -- `id:` -- aggiorna `lastEventId`, inviato dentro `Last-Event-ID` in fase di riconnessione. -- `retry:` -- raccomanda una ritardo nel tentativo di riconessione in millisecondi. Non c'è modo di impostarlo da JavaScript. -- `event:` -- event name, must precede `data:`. - -Un messaggio può includere uno o più campi in qualunque ordine, ma l'`id:` solitamente va per ultimo. From cf1314c3e17fa039ff6e1ccc427f112197c69df4 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 16:46:44 +0100 Subject: [PATCH 03/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Andrea <45577511+longo-andrea@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 1 + 1 file changed, 1 insertion(+) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index c5515d7c1..7b370cd3d 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -80,6 +80,7 @@ Ad esempio, `elem.onclick`: */!* ``` + Se il gestore viene assegnato usando un attributo HTML, il browser lo riconosce, crea una nuova funzione partendo dal contenuto dell'attributo e la scrive nella proprietà del DOM. In sostanza, questa modalità equivale alla precedente. From 81a0ca9fe5b1cbe6fe45f7ca8038b3d8b5089567 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 16:46:54 +0100 Subject: [PATCH 04/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Andrea <45577511+longo-andrea@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 7b370cd3d..2a67862f2 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -34,7 +34,7 @@ I gestori, quindi, sono un modo per eseguire codice JavaScript al verificarsi de Partiamo dal più semplice. -### Attributo HTML (HTML-attribute) +### Attributo HTML Un gestore può essere impostato in HTML con un attributo chiamato `on`. From 5090123bd69f9878949b52b34902d171e1ffb79a Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 16:47:02 +0100 Subject: [PATCH 05/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Andrea <45577511+longo-andrea@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 2a67862f2..71b7fca6a 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -19,7 +19,7 @@ Ecco quindi una lista, degli eventi DOM più utili: - `focus` -- quando l'utente attiva il focus su un elemento, ad esempio su un ``. **Eventi del Document:** -- `DOMContentLoaded` -- quando l'HTML viene caricato e processato, e la struttura del DOM è stata completata. +- `DOMContentLoaded` -- quando l'HTML viene caricato e processato, e la costruzione del DOM è stata completata. **Eventi dei CSS:** - `transitionend` -- quando termina un'animazione CSS (CSS-animation). From d6e6a393a7f962a0513869923fc5456c376e6000 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 16:47:14 +0100 Subject: [PATCH 06/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Andrea <45577511+longo-andrea@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 71b7fca6a..a6ad90626 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -28,7 +28,7 @@ Ci sono tanto altri eventi più specifici, che verranno affrontati in dettaglio ## Gestori di evento -Per reagire agli eventi possiamo assegnare un *gestore* (handler), che non è che una funzione che viene eseguita contestualmente alla generazione di un evento. +Per reagire agli eventi possiamo assegnare un *gestore* (handler), che non è altro che una funzione che viene eseguita contestualmente alla generazione di un evento. I gestori, quindi, sono un modo per eseguire codice JavaScript al verificarsi delle azioni dell'utente ed esistono vari modi per assegnare un evento. From 4fe76a03ac2dba3387458240e84a225eca7043c3 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 16:47:21 +0100 Subject: [PATCH 07/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Andrea <45577511+longo-andrea@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 1 + 1 file changed, 1 insertion(+) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index a6ad90626..f456378cf 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -43,6 +43,7 @@ Ad esempio, per assegnare un gestore al `click` di un `input`, possiamo usare `o ```html run ``` + Al click del mouse, il codice dentro `onclick` verrà eseguito. Nota bene che dentro `onclick` useremo gli apici singoli, in quanto l'attributo stesso è già inserito all'interno di apici doppi. Se ci dimenticassimo che il codice stesse dentro l'attributo, ed usassimo gli apici doppi come in questo caso: `onclick="alert("Click!")"`, il codice non funzionerebbe. From 95cab36b6c4d018ee3f0504332e16ca7d710776d Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 16:47:29 +0100 Subject: [PATCH 08/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Andrea <45577511+longo-andrea@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index f456378cf..9361fbd25 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -195,7 +195,7 @@ Assegnare un gestore a `elem.onclick`, e non a `elem.ONCLICK`, in quanto le prop Il problema principale della sopracitata maniera di assegnare i gestori è che non abbiamo modo di assegnare dei gestori multipli a un evento. -Mettiamo il caso che una parte del nostro codice serva ad evidenziare un pulsante al click, e che un altro serva a mostrare un messaggio al medesimo click. +Ipotizziamo che una parte del nostro codice serva ad evidenziare un pulsante al click, e che un altro serva a mostrare un messaggio al medesimo click. Per fare questo sarebbe bello poter assegnare due eventi distinti, ma sappiamo che ogni nuova proprietà DOM con lo stesso nome, sovrascriverà la precedente: From c14382eb60f5d3c3b3ff08d3e21355af7af3d381 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 16:47:40 +0100 Subject: [PATCH 09/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Andrea <45577511+longo-andrea@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 9361fbd25..e9b2e508f 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -242,7 +242,7 @@ elem.addEventListener( "click" , () => alert('Grazie!')); elem.removeEventListener( "click", () => alert('Grazie!')); ``` -Il gestore non verrà rimosso, perchè `removeEventListener` prende come parametro un'altra funzione: è certamente con lo stesso codice, ma questo non ha alcuna rilevanza, dal momento che è un oggetto funzione differente (fanno riferimento a due differenti indirizzi di memoria N.d.T). +Il gestore non verrà rimosso, perchè `removeEventListener` prende come parametro un'altra funzione: è certamente con lo stesso codice, ma questo non ha alcuna rilevanza, dal momento che è un oggetto funzione differente (fanno riferimento a due differenti indirizzi di memoria). La maniera corretta per farlo è questa: From 88b76650c465f3e7caf745a35524d37046a1d058 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 16:47:58 +0100 Subject: [PATCH 10/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Andrea <45577511+longo-andrea@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index e9b2e508f..e362684a1 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -88,7 +88,7 @@ In sostanza, questa modalità equivale alla precedente. I due codici messi a confronto, infatti, lavorano alla stessa maniera: -1. Only HTML: +1. Solo HTML: ```html autorun height=50 From f394522223b5a55950dd97e3af02fd4ecc1330fd Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sat, 23 Jan 2021 22:18:19 +0100 Subject: [PATCH 11/19] Revert "Delete article.md" This reverts commit d397c21692bf3459e90ee0cea7a2f33158ce7799. --- 5-network/12-server-sent-events/article.md | 266 +++++++++++++++++++++ 1 file changed, 266 insertions(+) create mode 100644 5-network/12-server-sent-events/article.md diff --git a/5-network/12-server-sent-events/article.md b/5-network/12-server-sent-events/article.md new file mode 100644 index 000000000..414c52456 --- /dev/null +++ b/5-network/12-server-sent-events/article.md @@ -0,0 +1,266 @@ +# Server Sent Events + +La specifica [Server-Sent Events](https://html.spec.whatwg.org/multipage/comms.html#the-eventsource-interface) descrive una classe built-in `EventSource`, che mantiene la connessione con il server e permette di ricevere eventi da esso. + +In modo simile ai `WebSocket`, la connessione è persistente. + +Ci sono però delle differenze sostanziali: + +| `WebSocket` | `EventSource` | +|-------------|---------------| +| Bidirezionale: sia il client che il server possono scambiare messaggi | Unidirezionale: solamente il server può inviare messaggi | +| Dati binari e testuali | Solo testuali | +| Protocollo WebSocket | HTTP standard | + +`EventSource` è un modo meno potente di comunicare con il server rispetto ai `WebSocket`. + +Perché dovremmo usarli? + +La ragione principale: è semplice da usare. In molte applicazioni, la potenza dei `WebSocket` è anche troppa. + +Se abbiamo necessità di ricevere un flusso di dati da un server: che siano messaggi di chat o variazioni di prezzo dei mercati. Allora è ciò per cui `EventSource` è fatto. Supporta anche l'auto riconnessione, la qualcosa dovremmo invece implementare manualmente nei `WebSocket`. Oltretutto, è un normalissimo HTTP, e non un nuovo protocollo. + +## Ottenere i messaggi + +Per cominciare a ricevere messaggi, dobbiamo solamente creare un `new EventSource(url)`. + +Il browser si connetterà all'url e terrà la connessione aperta, in attesa di eventi. + +Il server dovrebbe rispondere con status 200 ed header `Content-Type: text/event-stream`, dopodiché mantenere aperta la connessione e scrivere i messaggi all'interno di esso in un formato speciale del tipo: + +``` +data: Message 1 + +data: Message 2 + +data: Message 3 +data: of two lines +``` + +- Un messaggio di testo segue la stringa `data:`, lo spazio dopo la virgola è opzionale. +- I messaggi sono delimitati con un doppio line break `\n\n`. +- Per inviare un line break `\n`, possiamo inviare immediatamente un altro `data:` (il terzo messaggio nell'esempio precedente). + +In pratica, i messaggi complessi sono solitamente inviati tramite oggetti codificati in JSO. I Line-breaks sono codificati come `\n`, e in questo modo i messaggi `data:` multiriga non sono necessari + +Ad esempio: + +```js +data: {"user":"John","message":"First line*!*\n*/!* Second line"} +``` + +...In questo modo possiamo assumere che ogni `data` contenga esattamente un messaggio. + +Per ognuno di questi messaggi, viene generato l'evento `message`: + +```js +let eventSource = new EventSource("/events/subscribe"); + +eventSource.onmessage = function(event) { + console.log("New message", event.data); + //logghera' 3 volte per il data stream poco sopra +}; + +// oppure eventSource.addEventListener('message', ...) +``` + +### Richieste Cross-origin + +`EventSource` supporta le richieste cross-origin, come `fetch` e qualunque altro metodo di rete. Possiamo usare qualunque URL: + +```js +let source = new EventSource("https://another-site.com/events"); +``` +Il server remoto otterrà l'header `Origin` e dovrà rispondere con `Access-Control-Allow-Origin` per continuare. + +Per inviare credenziali, dovremmo impostare le opzioni aggiuntive `withCredentials`, in questo modo: + +```js +let source = new EventSource("https://another-site.com/events", { + withCredentials: true +}); +``` + +Si prega di guardare il capitolo per maggiori informazioni sugli headers cross-origin. + + +## Riconnessione + +In fase di creazione, `new EventSource` si connette al server, e se la connessione si interrompe -- si riconnette. + +Ciò è molto conveniente, dal momento che non ci dobbiamo curare della cosa. + +C'è un piccolo ritardo tra le riconnessioni, pochi secondi di default. + +Il server può impostare il ritardo raccomandato usando `retry:` nella risposta (in millisecondi) + +```js +retry: 15000 +data: Hello, I set the reconnection delay to 15 seconds +``` + +Il `retry:` può arrivare insieme ad altri dati, o come messaggio singolo. + +Il browser dovrebbe attendere questi millisecondi prima di riconnettersi. O anche di più, ad esempio se il browser sa (dall'OS) che non c'è connessione in quel momento, può attendere fino a quando la connessione non ritorna, e successivamente riprovare. + +- Se il server vuole che il browser smetta di riconnettersi, dovrebbe rispondere con uno status HTTP 204. +- Se il browser vuole chiudere la connessione, dovrebbe chiamare il metodo `eventSource.close()`: + +```js +let eventSource = new EventSource(...); + +eventSource.close(); +``` +Inoltre, non avverrà alcuna riconnessione se la risposta ha un `Content-type` non valido o se il suo HTTP status è diverso da 301, 307, 200 o 204. In questi casi verrà emesso l'evento `"error"`, e il browser non si riconnetterà. + +```smart +Quando una connessione è finalemente chiusa, non ci sarà modo di "riaprirla". Se volessimo riconnetterci nuovamente, dovremmo ricreare un nuovo `EventSource`. +``` + +## Message id + +Quando una connessione si interrompe per motivi di problemi di rete, ogni lato non può essere sicuro di quale messaggi siano stati ricevuti, e quali no. +Per riprendere correttamente la connessione, ogni messaggio dovrebbe avere un campo `id`, come questo: +``` +data: Message 1 +id: 1 + +data: Message 2 +id: 2 + +data: Message 3 +data: of two lines +id: 3 +``` +Quando viene ricevuto un messaggio con `id:`, il browser: + +- Imposta la proprietà `eventSource.lastEventId` su quel valore. +- In fase di riconnessione invia l'header `Last-Event-ID` con quell'`id`, in modo da permettere al server di reinviare i messaggi successivi. + +```smart header="Inserisci `id:` dopo `data:`" +Nota bene: l'`id` viene aggiunto dopo il messaggio `data` dal server, per assicurarsi che `lastEventId` venga aggiornato solamente dopo che il messaggio sia stato ricevuto. +``` + +## Stato della conessione: readyState + +L'oggetto `EventSource` possiede la proprietà `readyState`, che può assumere uno dei seguenti valori: + +```js no-beautify +EventSource.CONNECTING = 0; // connessione o riconnessione +EventSource.OPEN = 1; // connesso +EventSource.CLOSED = 2; // connessione chiusa +``` + +Quando viene creato un oggetto, o se la connessione è assente, viene valorizzato sempre a `EventSource.CONNECTING` (equivale a `0`). + +Possiamo interrogare questa proprietà per sapere lo stato di `EventSource`. + +## Tipi di evento + +Di base l'oggetto `EventSource` genera tre eventi: + +- `message` -- un messaggio ricevuto, disponibile come `event.data`. +- `open` -- la connessione è aperta. +- `error` -- la connessaione non può essere stabilita, ad esempio, il server ha risposto con lo status HTTP 500. + +Il server può specificare un altro tipo di evento con `event: ...` all'inizio dell'evento. + +Per esempio: + +``` +event: join +data: Bob + +data: Hello + +event: leave +data: Bob +``` + +Per gestire eventi custom, dobbiamo usare `addEventListener`, e non `onmessage`: + +```js +eventSource.addEventListener('join', event => { + alert(`Joined ${event.data}`); +}); + +eventSource.addEventListener('message', event => { + alert(`Said: ${event.data}`); +}); + +eventSource.addEventListener('leave', event => { + alert(`Left ${event.data}`); +}); +``` + +## Esempio completo + +Qui c'è il server che invia messaggi con `1`, `2`, `3`, ed infine `bye` interrompendo la connessione. + +Dopo il browser si riconnette automaticamente. + +[codetabs src="eventsource"] + +## Riepilogo + +L'oggetto `EventSource` stabilisce automaticamente una connessione persistente e permette al server di inviare dei messaggi attraverso di essa. + +Offrendo: +- Riconnessione automatica, con timeout di `retry` regolabili. +- Id dei messaggi per riprendere gli eventi, l'ultimo id ricevuto viene inviato nell'header `Last-Event-ID` in fase di riconnessione. +- Lo stato corrente è dentro la proprietà `readyState`. + +Ciò rende `EventSource` una valida alternativa ai `WebSocket`, il quale è più a basso livello e manca di alcune funzionalità built-in (sebbene possano essere implementate). + +In molte applicazioni reali, la potenza di `EventSource` è già sufficiente. + +Supportato in tutti i browser moderni (non IE). + +La sintassi è: + +```js +let source = new EventSource(url, [credentials]); +``` + +Il secondo argomento consta di una sola opzione possibile: `{ withCredentials: true }`, la quale permette di inviare credenziali cross-origin. + +Complessivamente la sicurezza del cross-origin è la stessa di `fetch` e altri metodi di rete. + +### Proprietà di un oggetto `EventSource` + +`readyState` +: Lo stato corrente della connessione: uno tra `EventSource.CONNECTING (=0)`, `EventSource.OPEN (=1)` o `EventSource.CLOSED (=2)`. + +`lastEventId` +: L'ultimo `id` ricevuto.In fase di riconnessione il browser lo invia nell'header `Last-Event-ID`. + +### Metodi + +`close()` +: Chiude la connessione. + +### Eventi + +`message` +: Messagio ricevuto, il dato è dentro `event.data`. + +`open` +: La connessione è stabilita. + +`error` +: In caso di errori, inclusi la connessione persa (con riconnessione automatica) ed errori fatali. Possiamo controllare `readyState` per vedere se è stata tentata la riconnessione. + +Il server può impostare un evento personalizzato dentro `event:`. Questi eventi andrebbero gestiti usando `addEventListener`, e non `on`. + +### Formato della risposta del server + +Il server invia messaggi, delimitati da `\n\n`. + +Un messaggio può avere i seguenti campi: + +- `data:` -- corpo del messaggio, una sequenza di `data` multipli viene interpretata come un messaggio singolo, con `\n` tra la parti. +- `id:` -- aggiorna `lastEventId`, inviato dentro `Last-Event-ID` in fase di riconnessione. +- `retry:` -- raccomanda una ritardo nel tentativo di riconessione in millisecondi. Non c'è modo di impostarlo da JavaScript. +- `event:` -- event name, must precede `data:`. + +Un messaggio può includere uno o più campi in qualunque ordine, ma l'`id:` solitamente va per ultimo. From 41a7198293ebd3a8ccdd500ff1b10d4215f4bb3c Mon Sep 17 00:00:00 2001 From: Andrea Longo Date: Sat, 23 Jan 2021 23:38:59 +0100 Subject: [PATCH 12/19] Revert "Update 2-ui/2-events/01-introduction-browser-events/article.md" This reverts commit 88b76650c465f3e7caf745a35524d37046a1d058. --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index e362684a1..e9b2e508f 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -88,7 +88,7 @@ In sostanza, questa modalità equivale alla precedente. I due codici messi a confronto, infatti, lavorano alla stessa maniera: -1. Solo HTML: +1. Only HTML: ```html autorun height=50 From b6f95f511134aad59cff69c0429768bf8deb4c4b Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sun, 24 Jan 2021 18:48:17 +0100 Subject: [PATCH 13/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Simone Pasini <66781510+pasor1@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index e9b2e508f..5b9eb88f6 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -447,4 +447,4 @@ L'ultimo modo è il più flessibile, ma è anche il più lungo da scrivere. Alcu Non importa come assegni un gestore, in ogni caso il primo argomento passato sarà un oggetto evento, contenente i dettagli su ciò che è avvenuto. -Nei prossimi capitoli, avremo modo di approfondire il tema degli eventi in generale ed le loro differenti tipologie. +Nei prossimi capitoli, avremo modo di approfondire il tema degli eventi in generale e le loro differenti tipologie. From 74d187455174ec1ddfbe1a49c4aefa75cee92e92 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sun, 24 Jan 2021 18:49:31 +0100 Subject: [PATCH 14/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Simone Pasini <66781510+pasor1@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 5b9eb88f6..a6d3db702 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -158,7 +158,7 @@ button.onclick = sayThanks; button.onclick = sayThanks(); ``` -Se aggiungessimo le parentesi, allora `sayThanks()` diverrebbe una chiamata a funzione, di conseguenza il valore dell'assegnazione dell'ultima riga dell'esempio, sarebbe il risultato della chiamata, il quale, a sua volta, sarebbe `undefined` (dato che la funzione non restituisce nulla), che verrebbe assegnato ad `onclick`. Ovviamente così non potrebbe andare bene, ed inoltre non sarebbe nemmeno l'effetto voluto. +Se aggiungessimo le parentesi, allora `sayThanks()` diverrebbe una chiamata a funzione. Di conseguenza il valore dell'assegnazione dell'ultima riga dell'esempio, sarebbe il risultato della chiamata, ossia `undefined` (dato che la funzione non restituisce nulla), e verrebbe assegnato ad `onclick`. Ovviamente così non potrebbe andare bene, ed inoltre non sarebbe nemmeno l'effetto voluto. ...D'altra parte, però, nel markup abbiamo bisogno delle parentesi: From d593c6825ae840a6fd839607e8486a7affb346c5 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sun, 24 Jan 2021 18:49:41 +0100 Subject: [PATCH 15/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Simone Pasini <66781510+pasor1@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index a6d3db702..fde568209 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -338,7 +338,7 @@ Alcune proprietà dell'oggetto `event`: Esistono tante altre proprietà., molte delle quali dipendono dal tipo di evento: gli eventi della tastiera hanno un gruppo di proprietà, gli eventi del puntatore un altro ancora, e li studieremo più avanti quando andremo a vedere i vari eventi nel dettaglio. ````smart header="L'oggetto evento è disponibile anche nei gestori HTML" -Se assegniamo un gestore dentro l'HTML, possiamo usare l'oggetto `evento`: +Anche se assegniamo un gestore dentro l'HTML, possiamo usare l'oggetto `evento`: ```html autorun height=60 From 80d6e280f9939ddbc5483eb8cb780edde5936806 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sun, 24 Jan 2021 18:49:48 +0100 Subject: [PATCH 16/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Simone Pasini <66781510+pasor1@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index fde568209..bf2be62ce 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -231,7 +231,7 @@ Per rimuovere l'evento, si usa `removeEventListener`: element.removeEventListener(event, handler, [options]); ``` -````warn header="La rimozione prevede la stessa identica funzione" +````warn header="La rimozione richiede la stessa identica funzione" Per rimuovere un gestore dobbiamo passare come parametro, la stessa funzione che abbiamo usato per l'assegnazione. Il seguente codice non fa quello che ci aspetteremmo: From ad67b9e893e025f5dbca51d56897a4c4ad1dcb77 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sun, 24 Jan 2021 18:50:14 +0100 Subject: [PATCH 17/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Simone Pasini <66781510+pasor1@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index bf2be62ce..66aa23e8f 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -28,7 +28,7 @@ Ci sono tanto altri eventi più specifici, che verranno affrontati in dettaglio ## Gestori di evento -Per reagire agli eventi possiamo assegnare un *gestore* (handler), che non è altro che una funzione che viene eseguita contestualmente alla generazione di un evento. +Per reagire agli eventi possiamo assegnare un *gestore* (handler). Questo non è altro che una funzione che viene eseguita contestualmente alla generazione di un evento. I gestori, quindi, sono un modo per eseguire codice JavaScript al verificarsi delle azioni dell'utente ed esistono vari modi per assegnare un evento. From 89567791b5161afefadecf20977fc15f0cb55411 Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sun, 24 Jan 2021 18:50:56 +0100 Subject: [PATCH 18/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Simone Pasini <66781510+pasor1@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 66aa23e8f..0cbb9ff71 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -24,7 +24,7 @@ Ecco quindi una lista, degli eventi DOM più utili: **Eventi dei CSS:** - `transitionend` -- quando termina un'animazione CSS (CSS-animation). -Ci sono tanto altri eventi più specifici, che verranno affrontati in dettaglio nei prossimi capitoli. +Ci sono molti altri eventi più specifici, che verranno affrontati in dettaglio nei prossimi capitoli. ## Gestori di evento From e55d2a16144a6824a3efcd24341083378fd1cd6a Mon Sep 17 00:00:00 2001 From: pierangelomiceli Date: Sun, 24 Jan 2021 18:51:24 +0100 Subject: [PATCH 19/19] Update 2-ui/2-events/01-introduction-browser-events/article.md Co-authored-by: Simone Pasini <66781510+pasor1@users.noreply.github.com> --- 2-ui/2-events/01-introduction-browser-events/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2-ui/2-events/01-introduction-browser-events/article.md b/2-ui/2-events/01-introduction-browser-events/article.md index 0cbb9ff71..bf6b015ea 100644 --- a/2-ui/2-events/01-introduction-browser-events/article.md +++ b/2-ui/2-events/01-introduction-browser-events/article.md @@ -1,4 +1,4 @@ -# Introduzione agli aventi del browser +# Introduzione agli eventi del browser *Un evento* è un segnale che sta ad indicare che è avvenuto qualcosa. Tutti i nodi DOM generano questi segnali (anche se gli eventi non sono limitati al DOM).