Javascript Autore Sebastiano Maugeri Breve storia dei browser
Javascript Autore: Sebastiano Maugeri
Breve storia dei browser (1) Verso la metà degli anni ‘ 90 esistevano solo due browser: • Mosaic • Netscape Navigator Mosaic in seguito venne acquistato da Microsoft e divenne Internet Explorer. Dopo alcuni anni di dominio da parte di Navigator, Internet Explorer divenne il browser più diffuso al mondo causando la fine di Netscape Navigator.
Breve storia dei browser (2) In seguito la tecnologia alla base di Netscape Navigator venne usata per creare Firefox.
Netscape Navigator Prima dell’introduzione di Javascript, qualsiasi elaborazione – anche la più elementare – doveva essere demandata al server. Ciò significava che i dati dovevano essere inviati dal browser verso il server, elaborati dal server e, successivamente, dovevano essere nuovamente inviati al browser per la loro visualizzazione. I creatori di Netscape avevano una visione leggermente diversa: credevano in un web dinamico con una minore interazione con i server e la possibilità di avere maggiori funzionalità direttamente sui computer dell’utente.
Javascript è stato realizzato da Brendan Eich, dietro espressa richiesta da parte dei creatori di Netscape Navigator, che desideravano un linguaggio semplice da utilizzare e adatto alla creazione di script per il loro browser. Brendan Eich in seguito sarà anche il fondatore del «Mozilla Project» che porterà alla nascita di Firefox.
Come sarebbe il presente… … senza Javascript! Come disattivare Javascript su Chrome: - Accedere alla pagina chrome: //settings - Cercare Javascript - Cliccare sulla voce Impostazioni contenuti - Disabilitare Javascript
Con Javascript disattivato… … provate ad accedere prima su: - www. twitter. com e in seguito su: - www. facebook. com
Senza Javascript Come si può notare, nel caso di Twitter la navigazione è possibile utilizzando il sito in versione mobile e la qualità della user experience è evidentemente estremamente ridotta. Nel caso di Facebook ci viene direttamente impedita la navigazione.
Live. Script Il nome scelto inizialmente da Brandon Eich per il suo linguaggio di scripting era Live. Script. La versione di Live. Script creata da Microsoft, ottenuta dal suo reverse engineering, venne chiamata JScript. Successivamente l’ECMA (the European Computer Manifacture Association) decise di standardizzare il linguaggio e rilasciare le relative specifiche sotto il nome di ECMAScript.
Ma allora perché «Javascript» ? Negli anni ‘ 90 Java divenne un marchio estremamente diffuso. La scelta di utilizzare questa denominazione fu quindi strettamente legata a ragioni di «marketing» . Non c’è infatti alcuna similitudine tra Java e Javascript: Java è un linguaggio totalmente diverso da Javascript.
Front-end Language? ? ? Javascript viene considerato da sempre un linguaggio per il front-end che può essere usato per: • Gestire l’interazione con gli utenti • Creare animazioni Ma in realtà oggi lo troviamo in diversi framework per il back-end come, ad esempio, Node. js
Javascript è compatibile Il linguaggio Javascript è compatibile con tutti i browser in commercio e per tale ragione viene considerato un linguaggio di programmazione estremamente popolare.
Risorse • https: //developer. mozilla. org/it/docs/Web/Java. Script • https: //www. w 3 schools. com/js/default. asp
Primi passi Per iniziare a provare le principali istruzioni del linguaggio, possiamo utilizzare la console presente su Chrome. Per visualizzare la console, dobbiamo visualizzare i «developer tools» (gli strumenti per sviluppatori) premendo il tasto F 12. Una volta aperti i tools, occorre cliccare sulla voce Console del menù.
La funzione alert("Ciao Mondo"); • alert è il nome della funzione • Le funzioni vengono sempre seguite dalle parentesi () che, in alcuni casi, ci consentono di passare dei parametri. • "Ciao Mondo" è il parametro che stiamo passando alla funzione. Si trova tra doppie virgolette perché queste identificano l’inizio e la fine della stringa che stiamo passando. • Il ; rappresenta il terminatore di istruzione e identifica la fine del comando che stiamo passando. È (quasi) sempre necessario.
L’importanza del case Le istruzioni Javascript sono case sensitive (Javascript distingue tra le lettere maiuscole e le lettere minuscole). - alert è una funzione Javascript - Alert non è una funzione Javascript e la sua esecuzione genera un errore. - Il termine alert è una delle diverse keyword utilizzate nel linguaggio Javascript
Grammatica del linguaggio Java. Script L’insieme dei vari elementi visti finora: - Keyword alert - Parentesi () - Il parametro "Ciao Mondo" - Il terminatore di istruzione ; rappresenta la grammatica del nostro linguaggio di programmazione.
Data Types (1) Nell’esempio precedente: alert("Ciao Mondo"); abbiamo osservato la presenza del testo "Ciao Mondo", passato come parametro nella nostra funzione alert. L’uso dei doppi apici (") sta ad indicare che quello che stiamo passando è una stringa di testo e non un comando Java. Script. "Ciao Mondo" è una stringa e le stringhe sono un tipo di dato in Java. Script.
Data Types (2) Tipi di dato in Java. Script: • String (Es. "Ciao Mondo") • Number (Es. 123) • Boolean (solo due valori: true oppure false)
Esercizi con la console Apriamo la console, scriviamo i seguenti comandi ed osserviamo cosa ci viene restituito in output: • • • 2+2 alert(2+2); typeof(3); typeof("Ciao Mondo"); typeof("3"); typeof(true);
Le variabili (1) Per introdurre le variabili, apriamo Chrome e visualizziamo i developer tools. Clicchiamo quindi su Sources e creiamo un nuovo Snippet. Nello snippet scriviamo: prompt("Come ti chiami? "); e premiamo il tasto «play» visibile in basso a destra. Osserviamo che viene visualizzato un popup simile all’alert visto in precedenza, con la differenza che ci viene chiesto un dato in input.
Le variabili (2) Osserviamo che, una volta inserito il nostro nome, lo script finisce la sua esecuzione e il nostro nome non viene memorizzato da nessuna parte. Per memorizzare l’informazione inserita abbiamo bisogno di una variabile.
Esercizio Inseriamo il seguente codice nello snippet: var my. Name = "Sebastiano"; Eseguiamo il codice ed andiamo nella sezione console che si trova immediatamente sotto l’area dello snippet. Scriviamo my. Name e premiamo invio. Osserviamo che my. Name contiene la stringa "Sebastiano".
Le variabili (3) Osserviamo nel dettaglio il comando che abbiamo inserito nello snippet: var my. Name = "Sebastiano"; • var è la keyword che ci consente di definire una nuova variabile • my. Name è il nome della variabile • "Sebastiano" è il valore che stiamo dando a quella variabile.
Esercizio Scriviamo il seguente testo nello snippet: var my. Name = "Sebastiano"; var your. Name = prompt("Qual è il tuo nome? "); alert("Ciao " + your. Name + ", sono " + my. Name + " e ti do il benvenuto sul mio sito!"); Clicchiamo infine sul tasto play per eseguire lo script.
Dare il nome corretto alle variabili Nell’esempio precedente avevamo due variabili denominate my. Name e your. Name. Il nome utilizzato non cambia il funzionamento di Javascript, ma rende leggibile il codice che stiamo scrivendo. L’uso di un nome che descriva in modo chiaro la variabile è quindi importante, perché consente, a noi e ad altri, di leggere e di comprendere facilmente il codice che abbiamo scritto.
Alcune regole per un naming corretto • Non utilizzare mai una keyword Java. Script come nome della variabile • I nomi delle variabili non possono iniziare con un numero • I nomi delle variabili non possono contenere il carattere «spazio» • I nomi delle variabili possono contenere lettere, numeri ed i due caratteri $ e _
Camel case Quando si definisce il nome di una variabile, una buona pratica è quella di utilizzare il camel case. Se il nome di una variabile è composto da più parole, ad esempio nel caso della variabile: myuseraccount usare il camel case vuol dire scrivere il nome di questa variabile in questo modo: my. User. Account La prima lettera della prima parola in minuscolo e le iniziali delle altre parole tutte in maiuscolo.
String • + è il concatenatore di stringa • my. Var. length restituisce il numero di caratteri presenti nella stringa • my. Var. slice(s, e) restituisce una nuova stringa contenente i caratteri a partire dal carattere nella posizione s fino al carattere nella posizione e (escluso). N. B. i caratteri iniziano dalla posizione zero. • my. Var. to. Upper. Case() restituisce una nuova stringa in cui i caratteri di my. Var sono stati convertiti in maiuscolo. • my. Var. to. Lower. Case() restituisce una nuova stringa in cui tutti i caratteri di my. Var sono stati convertiti in minuscolo.
Esercizio Acquisiamo in input il nome dell’utente e correggiamo il case dei caratteri contenuti nel suo nome. La prima lettera del nome dovrà essere in maiuscolo, le altre lettere in minuscolo a prescindere da come siano state inserite.
Number Operatori binari da poter utilizzare con le variabili di tipo Number: • + = somma • - = sottrazione • * = moltiplicazione • / = divisione • % = Operatore modulo: restituisce il resto di una divisione euclidea (con resto)
Precedenza degli operatori L’ordine di precedenza tra gli operatori è così definito: • Operazioni tra parentesi (dalle più interne alle più esterne) • Operazioni unarie (es. -1 o 3!) • Operazioni di elevazione a potenza • Moltiplicazioni e divisioni (da sinistra verso destra) • Somme e sottrazioni (da sinistra verso destra)
Altri operatori di assegnamento x=x+1 può essere scritto come x++ x=x– 1 può essere scritto come x-x=x+5 può essere scritto come x+=5 x=x-5 può essere scritto come x-=5 x=x*5 può essere scritto come x*=5 x=x/5 può essere scritto come x/=5
Funzioni (1) Alcune porzioni di codice possono essere raggruppate in funzioni. Quando una porzione di codice viene riutilizzata con una certa frequenza, invece di copiare ed incollare il codice in più parti della nostra applicazione, è buona pratica raggruppare le istruzioni in un’unica funzione che può essere richiamata con un unico comando.
Funzioni (2) Come dichiarare una funzione: function nome. Funzione(par 1, par 2, …) { // Istruzioni return value // la funzione può // restituire un valore } Come chiamare la funzione appena creata: nome. Funzione();
console. log() Il metodo console. log() consente la scrittura di un testo, inserito come parametro tra le parentesi, nella console dei developer tools. La principale utilità di questo metodo è quella di consentire il debug delle nostre applicazioni. Un esempio di utilizzo è il seguente: console. log("Il valore della variabile è " + v);
Karel IDE Per imparare l’uso delle funzioni e la scrittura di semplice codice, possiamo utilizzare il Karel IDE messo a disposizione dalla Stanford University: http: //stanford. edu/~cpiech/karel/ide. html
Esercizio (Karel IDE) Proviamo a muovere il nostro robot all’interno di un «mondo» di 15 x 15 passi. Questa semplice funzione farà muovere il robot lungo il perimetro del «mondo» . while(left. Is. Clear()) { if (front. Is. Clear()) { move(); } else { turn. Left(); } }
Esercizio Creiamo una funzione per il calcolo del BMI. Sappiamo che: BMI = Peso (kg) / altezza^2 (m^2) Chiediamo in input tramite il prompt il peso dell’utente e la sua altezza in metri, restituiamo con un alert il suo BMI. N. B. L’elevazione a potenza si ottiene utilizzando la funzione: Math. pow(valore, esponente)
Numeri casuali con Java. Script (1) La funzione: Math. random(); consente di generare numeri casuali compresi tra 0 e 0. 99999999 (16 cifre decimali). Per ottenere un numero intero compreso tra zero ed n, possiamo moltiplicare il numero casuale generato da Javascript per il valore n+1
Numeri casuali con Java. Script (2) Esempio: var n = Math. random(); var nc = Math. floor(n * 6); alert(nc); Questo codice restituirà un numero compreso tra 0 e 5.
Controllo di flusso Le istruzioni che consentono il controllo di flusso, sono quelle istruzioni che ci consentono di definire delle regole per scegliere quale tra due (o più) blocchi di codice deve essere eseguita o di eseguire ripetutamente lo stesso blocco di codice, fino al verificarsi di una ben precisa condizione.
if(condizione) { … } Al verificarsi di una condizione, esegue una porzione di codice. Ad esempio: if(a === 1) { console. log("a è uguale ad 1"); }
if(condizione) { … } else { … } Al verificarsi di una condizione, esegue una porzione di codice, altrimenti ne esegue un’altra. Ad esempio: if(a === 1) { console. log("a è uguale ad 1"); } else { console. log("a è diverso da 1"); }
Comparatori == === !== > < >= <= «uguale a» (e dello stesso tipo) «diverso da» «è maggiore di» «è minore di» «è maggiore o uguale a» «è minore o uguale a»
Combinare i comparatori && «e» || «o» ! «diverso»
Esempio: In questo esempio le istruzioni … vengono eseguite solo se a = 1 e b = 3: if(a === 1 && b === 3) { … } In questo esempio le istruzioni … vengono eseguite se a = 1 o se b = 3: if(a === 1 || b === 3) { … }
Array var week. Days = ["Lun", "Mar", "Mer", "Gio", "Ven", "Sab", "Dom"]; week. Days. lenght Numero di elementi week. Days[0] Primo elemento dell’array week. Days. includes("Lun"); Include "Lun"? week. Days. push("New"); Aggiunge "New" week. Days. pop(); Recupera e rimuove l’ultimo inserito
Esercizio • Utilizzare la console per visualizzare un array e provare tutti i metodi descritti in precedenza (lenght, push, pop, includes, etc).
while loop Consente di eseguire ripetutamente un intero blocco di codice. Il ciclo si ripete solo se la condizione si mantiene vera. while (condizione) { … }
do … while loop Nel ciclo do…while il controllo della condizione viene inserito alla fine. Il blocco di codice contenuto nel ciclo viene quindi eseguito almeno una volta, anche se la condizione è falsa. do { … } while (condizione);
for loop Consente di eseguire un blocco di codice un numero finito di volte. for(inizio; condizione; incremento) { … } In questo esempio, il codice presente all’interno del loop viene eseguito 10 volte: for(i=1; i <= 10; i++) { … }
Costrutto switch (1) Consente l’esecuzione di un blocco di codice in funzione del valore di una espressione. switch(espressione) { case x: … break; case y: … break; default: … }
Costrutto switch (2) • L’istruzione break consente di interrompere le verifiche successive (inutili). • L’istruzione default consente di aggiungere un blocco di codice che viene eseguito solo se tutte le altre condizioni si sono rivelate false.
Istruzione break • Può essere usata in tutti i cicli • Interrompe l’esecuzione del ciclo, causando l’uscita immediata dal ciclo e la mancata esecuzione del codice. Esempio (da provare sull’editor degli snippet): for (i = 0; i < 10; i++) { if (i === 3) { break; } text += "The number is " + i + " "; }
Istruzione continue • Può essere usata in tutti i cicli • Interrompe l’esecuzione dell’iterazione attuale e continua con l’iterazione successiva. Esempio (da provare sull’editor degli snippet): for (i = 0; i < 10; i++) { if (i === 3) { continue; } text += "The number is " + i + " "; }
Java. Script e html Come accade per i CSS, ci sono tre modi per integrare il nostro Java. Script con il nostro codice html: • In uno specifico tag, usando le proprietà onload, onclick, etc. • Internal Java. Script: aggiungo tutto il codice Java. Script all’interno del tag <script />. • In un file esterno, usando il tag <script />.
Javascript in uno specifico tag Esempio: <!DOCTYPE html> <head> <title>Test</title> </head> <body onload="alert('Hello!'); "> <h 1>Test</h 1> </body> </html>
Internal Javascript Esempio: <!DOCTYPE html> <head> <title>Test</title> </head> <body> <h 1>Test</h 1> <script type="text/javascript"> alert("Hello!"); </script> </body> </html>
Java. Script in un file esterno (1) Esempio: <!DOCTYPE html> <head> <title>Test</title> </head> <body> <h 1>Test</h 1> <script src="script. js"></script> </body> </html>
Javascript in un file esterno (2) Il nostro file script. js conterrà direttamente il nostro codice js, quindi: alert("Hello!"); Importante: il codice javascript deve essere incluso alla fine della nostra pagina (immediatamente prima del tag di chiusura del body), in modo che venga eseguito quando tutti i tag sono già stati renderizzati dal browser.
Document Object Model (DOM)
Document Object Model (DOM)
HTML Tree Generator per Chrome • Cerca su google: «html tree generator chrome» • Si tratta di una estensione per Chrome che consente di visualizzare l’albero del sito web (come sono organizzati i dati all’interno del codice HTML).
document • È l’oggetto che ci consente di accedere ad ogni singolo tag del nostro documento HTML. • Se scriviamo document all’interno della console di Chrome, osserveremo che ci viene restituito un oggetto document, che conterrà l’intero codice HTML. • Osserviamo che espandendo l’oggetto restituito troviamo il doctype e l’intero codice HTML della nostra pagina.
Creiamo la seguente pagina html <!DOCTYPE html> <head> <title>Il mio sito web</title> <meta charset="utf-8" /> </head> <body> <h 1>Benvenuto</h 1> <input type="checkbox" name="selezione" id="selezione" /> <input type="button" name="pulsante" value="pulsante" /> <ul> <li><a href="https: //www. google. it/">Google</a></li> <li>Seconda opzione</li> <li>Terza opzione</li> <li>Quarta opzione</li> </ul> </body> </html>
html tree generator
document. first. Element. Child • Ci consente di accedere al primo elemento «figlio» del document • Osserviamo che il primo «figlio» di document è il tag html. Rispetto all’esempio visto in precedenza andiamo quindi a perdere il doctype. • Possiamo utilizzare la proprietà first. Element. Child su qualsiasi elemento del nostro document.
. first. Element. Child Proviamo adesso a scrivere: document. first. Element. Child Osserviamo che viene visualizzato il primo figlio dell’elemento html: l’elemento head.
. last. Element. Child Proviamo quindi a scrivere: document. first. Element. Child. last. Element. Child Osserviamo che viene visualizzato l’ultimo figlio dell’elemento html: l’elemento body. Di fatto le proprietà vengono riapplicate sull’elemento restituito. Il primo first. Element. Child ci restituisce l’elemento html, il secondo ci restituisce l’ultimo elemento figlio di html (body).
Selezioniamo l’elemento h 1 Proviamo a selezionare l’elemento h 1 utilizzando le proprietà che abbiamo utilizzato finora. Sappiamo che siamo in grado di farci restituire il body utilizzando il comando: document. first. Element. Child. last. Element. Child E sappiamo anche h 1 è il primo elemento del body. Possiamo quindi utilizzare il comando: document. first. Element. Child. last. Element. Child. firs t. Element. Child
Memorizzare l’elemento h 1 Il comando visto in precedenza ci consente di recuperare l’elemento h 1, ma è sicuramente lungo e scomodo da riutilizzare nel nostro codice. Per nostra fortuna abbiamo la possibilità di memorizzare l’elemento all’interno di una variabile: var h 1 = document. first. Element. Child. last. Eleme nt. Child. first. Element. Child
Utilizziamo la variabile h 1 • Scrivendo h 1 e premendo invio, ci viene restituito il contenuto dell’elemento h 1 • La variabile contiene «qualcosa» che ci consente di accedere all’elemento che abbiamo selezionato in precedenza e ci offre dei metodi e delle proprietà per manipolarne il suo contenuto • Una di queste proprietà è inner. HTML. Proviamo a scrivere il seguente comando: h 1. inner. HTML = "Addio!";
Utilizziamo la variabile h 1 Osserviamo che esistono diversi metodi e diverse proprietà che ci consentono di manipolare l’elemento selezionato. Per esempio possiamo cambiare il colore del testo utilizzando il comando: h 1. style. color = "red"; o possiamo cambiare l’allineamento del testo utilizzando il comando: h 1. style. text. Align = "center";
Metodo query. Selector Proviamo ad eseguire il seguente comando: document. query. Selector("input"). click(); Osserviamo che il codice appena inserito seleziona la prima input (checkbox) e simula il clic del mouse su questa input. Il risultato sarà quello di aggiungere un segno di spunta alla checkbox. Eseguendo nuovamente il codice vedremo che il segno di spunta verrà rimosso, come accade quando si clicca normalmente con il mouse su una checkbox. Il metodo query. Selector() restituisce il primo elemento che corrisponde ad uno specifico selettore CSS.
Metodi e proprietà • I metodi sono delle funzioni associate ad un oggetto. L’elemento h 1 visto in precedenza è un oggetto a cui possiamo fare riferimento grazie ad una variabile (che abbiamo chiamato h 1 per comodità). • Le proprietà sono dei «valori» associati ad un oggetto. Rappresentano lo stato dell’oggetto.
Un esempio: l’oggetto «Auto» • Metodi: – Accendi() – Spegni() – Accelera() – Frena() • Proprietà: – Colore – Numero di posti – Velocità
Selezionare gli elementi Abbiamo usato il metodo query. Selector() per selezionare la nostra input, ma esistono molti altri metodi che ci consentono di individuare i nostri elementi. • get. Elements. By. Tag. Name() • get. Elements. By. Class. Name() • get. Element. By. ID()
get. Elements. By. Tag. Name() Restituisce una HTMLcollection che contiene tutti gli elementi che corrispondono ad uno specifico tag html. Proviamo ad eseguire questo comando: document. get. Elements. By. Tag. Name("li"); Osserviamo che ci viene restituta una HTMLcollection (un array) contenente 4 elementi li.
get. Elements. By. Tag. Name() Dato che il metodo ci restituisce un array, per accedere alle proprietà ed ai metodi degli oggetti presenti sugli array dobbiamo utilizzare la sintassi che abbiamo già visto per gli array. Ad esempio per fare riferimento al primo elemento dobbiamo utilizzare la sintassi seguente: document. get. Elements. By. Tag. Name("li")[0]. style. color = "red"; Per conoscere il numero di elementi restituito dal metodo dobbiamo utilizzare il seguente comando: document. get. Elements. By. Tag. Name("li"). length;
Aggiorniamo la nostra pagina html <!DOCTYPE html> <head> <title>Il mio sito web</title> <meta charset="utf-8" /> </head> <body> <h 1 id="titolo">Benvenuto</h 1> <input type="checkbox" name="selezione" id="selezione" /> <input type="button" name="pulsante" value="pulsante" /> <ul> <li class="item"><a href="https: //www. google. it/">Google</a></li> <li class="item">Seconda opzione</li> <li class="item">Terza opzione</li> <li class="item">Quarta opzione</li> </ul> </body> </html>
get. Elements. By. Class. Name() Nel codice della diapositiva precedente abbiamo aggiunto la classe item ad ogni elemento li. Osserviamo che eseguendo questa riga di codice: document. get. Elements. By. Class. Name("item") otteniamo lo stesso risultato ottenuto con la get. Elements. By. Tag. Name(). Ad esempio possiamo recuperare il codice html presente all’interno del primo elemento li utilizzando il codice seguente: document. get. Elements. By. Class. Name("item")[0]. inner. HTML;
get. Element. By. ID() Come sappiamo non possono esistere due elementi con il medesimo ID, per questo la funzione non restituirà un array ma un singolo elemento. Osserviamo che il nome del metodo utilizza la parola Element al singolare.
query. Selector() Torniamo al metodo query. Selector per approfondire il meccanismo di selezione che utilizza. Finora abbiamo usato il metodo passando il nome dell’elemento (h 1, input, etc), ma in realtà il metodo query. Selector utilizza come parametro un selettore. Abbiamo già visto i selettori quando abbiamo lavorato con i CSS. Ricordiamoci anche i selettori possono essere combinati tra loro.
query. Selector() Proviamo ad usare diversi selettori per recuperare l’elemento h 1. Osserviamo che query. Selector NON restituisce un array ma solo il primo elemento che soddisfa il filtro definito attraverso il selettore.
Combinare i selettori - Esercizio <!DOCTYPE html> <head> <title>Il mio sito web</title> <meta charset="utf-8" /> </head> <body> <h 1 id="titolo">Benvenuto</h 1> <p><a href="https: //www. repubblica. it">La Repubblica</a></p> <ul> <li class="item"><a href="https: //www. google. it/">Google</a></li> <li class="item">Seconda opzione</li> <li class="item">Terza opzione</li> <li class="item">Quarta opzione</li> </ul> </body> </html>
query. Selector - Esercizio Osserviamo che nella pagina sono presenti due diversi tag a. Uno all’interno di un tag p ed uno all’interno dei tag ul ed li. Sappiamo che quando usiamo i selettori nei nostri css, per identificare i due elementi in modo diverso dobbiamo combinare i selettori in questo modo: p a { proprietà; } ul li a { proprietà; }
query. Selector - Esercizio
query. Selector. All Invece di restituire un singolo elemento, restituisce un array di elementi (una Node. List in questo caso).
HTML DOM Style Object Quando abbiamo modificato gli stili abbiamo utilizzato la keyword style. Per esempio per modificare la dimensione del font possiamo usare questa istruzione: document. query. Selector("a"). style. font. Size = "10 em"; L’oggetto style consente di specificare lo stile di uno specifico elemento e contiene tutte le proprietà che abbiamo già avuto modo di vedere nei nostri css. Va notata però una importante differenza: nei css utilizzavamo una sintassi leggermente diversa per i nomi delle proprietà. Ad esempio font-style al posto di font. Style. Un’altra differenza è che tutti i valori vanno specificati come stringhe. L’elenco delle proprietà dell’oggetto style: https: //www. w 3 schools. com/jsref/dom_obj_style. asp
Manipolare gli attributi Proviamo a leggere e a cambiare l’attributo href presente nel primo tag del codice html che stiamo utilizzando al momento. Per leggere il valore dell’attributo possiamo usare una delle seguenti istruzioni: document. query. Selector("a"). attributes. href; document. query. Selector("a"). get. Attribute("href");
Manipolare gli attributi Per scrivere il valore dell’attributo possiamo usare il metodo set. Attribute: document. query. Selector("a"). set. Attribute( "href", "http: //www. bing. com/"); Il metodo set. Attribute richiede due parametri: il primo è il nome dell’attributo che vogliamo modificare, il secondo è il valore che vogliamo impostare all’attributo.
Aggiungere/rimuovere una classe Creiamo una nuova pagina html con il seguente codice: <!DOCTYPE html> <head> <title>Il mio sito web</title> <style> . Rosso{ color: red; } </style> </head> <body> <h 1 id="titolo">Benvenuto</h 1> </body> </html>
Aggiungere/rimuovere una classe Per aggiungere una classe in un elemento: document. query. Selector("h 1"). class. List. add("Rosso"); Per rimuovere una classe in un elemento: document. query. Selector("h 1"). class. List. remove("Rosso"); Per maggiore comodità possiamo utilizzare direttamente il metodo toggle che aggiunge la classe se non presente e la rimuove se è già presente. document. query. Selector("h 1"). class. List. toggle("Rosso");
inner. HTML vs text. Content • inner. HTML restituisce tutto il contenuto dell’elemento. Se l’elemento contiene dell’html, questo viene restituito. • text. Content restituisce solo il testo presente nell’elemento. Se l’elemento contiene dell’html, questo viene eliminato e non viene restituito. • Come esercizio osserviamo cosa accade quando cerchiamo di assegnare del codice html attraverso l’uso della text. Content.
inner. HTML, text. Content, inner. Text • inner. HTML restituisce il testo con tutti gli spazi aggiuntivi e con i tag html • inner. Content restituisce il testo con tutti gli spazi aggiuntivi ma senza i tag html • inner. Text restituisce il testo senza spazi aggiuntivi e senza tag html
Esercizio <!DOCTYPE html> <head> <title>Il mio sito web</title> </head> <body> <h 1><span>Test inner</span></h 1> </body> </html>
. add. Event. Listener Nelle lezioni precedenti abbiamo visto che potevamo associare una funzione ad uno specifico evento attraverso l’uso di alcuni attributi presenti su alcuni tag. Ad esempio: <button onclick="do. Something(this); ">OK</button> In questo esempio utilizziamo l’attributo onclick per associare l’esecuzione della funzione do. Something() nel momento in cui andiamo a cliccare sul bottone con il mouse.
. add. Event. Listener Il metodo add. Event. Listener consente l’associazione tra un evento ed una funzione direttamente da codice. Si aggiunge un «Listener» (ascoltatore) per uno specifico evento, che si occuperà di eseguire una specifica funzione nel momento in cui questo evento viene generato.
. add. Event. Listener Se abbiamo il seguente codice html: <button name="btn">OK</button> ed il seguente codice javascript associato alla pagina: var btn = document. query. Selector("button"); btn. add. Event. Listener("click", do. Something); function do. Something() { alert("Clic! ; -)") }
. add. Event. Listener Nel button non abbiamo alcun riferimento al codice javascript (ovviamente la pagina dovrà comunque includere il file. js esterno usando il tag <script />). Nel codice javascript abbiamo: • una prima istruzione che serve a «cercare» e a conservare nella variabile btn il riferimento al primo elemento button presente sulla pagina. • Una seconda istruzione che ci consente di aggiungere un listener per uno specifico evento (click). Il metodo. add. Event. Listener accetta infatti due parametri: il nome dell’evento (è una stringa) e la funzione che deve essere richiamata quando questo evento si verifica.
. add. Event. Listener Qui potete trovare l’elenco completo degli eventi: https: //developer. mozilla. org/en-US/docs/Web/Events https: //www. w 3 schools. com/jsref/dom_obj_event. asp
. add. Event. Listener Dobbiamo focalizzare la nostra attenzione su un particolare che potrebbe essere sfuggito. Solitamente chiamiamo le nostre funzioni utilizzando il nome della funzione e, a seguire, le parentesi aperta e chiusa (es. do. Something() ). Quando aggiungiamo un handler alla nostra funzione però abbiamo visto che non aggiungiamo le parentesi ma passiamo solo il nome della funzione. Perché facciamo così? Perché utilizzare le parentesi impone l’uso immediato della funzione, anche durante la configurazione del listener.
. add. Event. Listener Cosa accade se invece di scrivere: btn. add. Event. Listener("click", do. Something); scriviamo: btn. add. Event. Listener("click", do. Something()); La funzione verrà chiamata alla fine del caricamento della pagina e l’handler non verrà inizializzato correttamente.
Anonymous function • Una anonymous function è una funzione che non ha un nome. • Se presente nel «flow» di un file javascript viene direttamente eseguita (le funzioni «normali» non vengono eseguite se non vengono chiamate esplicitamente). • Consente di limitare l’ambito (lo «scope» ) delle variabili create esclusivamente al suo interno.
Anonymous function Quando si aggiungono dei listener può essere comodo usare le anonymous function, perché la funzione viene inserita direttamente all’interno della definizione del listener: var btn = document. query. Selector("button"); btn. add. Event. Listener("click", function () { alert("Clic! ; -)") });
Esercizio – Creiamo una drum machine <!DOCTYPE html> <head> <title>Batteria</title> <style> . drum{ padding: 20 px; text-align: center; width: 100 px; border: solid 3 px red; border-radius: 10 px; font-size: 3 em; color: red; } </style> </head> <body> <h 1>Batteria!</h 1> <div class="elementi"> <button class="w drum">w</button> <button class="a drum">a</button> <button class="s drum">s</button> <button class="d drum">d</button> <button class="j drum">j</button> <button class="k drum">k</button> <button class="l drum">l</button> </div> <script type="text/javascript" src="js/sound. js"></script> </body> </html>
Esercizio Per aggiungere un listener per ogni button utilizzando il query. Selector si dovrebbe selezionare ogni elemento utilizzando l’attributo class, dove troviamo un valore differente per ogni button (w, a, etc). Ricordiamoci però che esiste un altro metodo che ci consente di recuperare un array di elementi: il metodo query. Selector. All.
Esercizio Ma come facciamo ad utilizzare l’array per impostare un event. Listener per ogni elemento button? Dobbiamo ricordarci delle strutture iterative viste nei primi giorni di lezione ed, in particolare, del ciclo for che, quando si lavora con gli array, risulta particolarmente comodo.
Il ciclo per aggiungere i listener var btn. Count = document. query. Selector. All(". drum"). length; for (i = 0; i < btn. Count; i++) { var btn = document. query. Selector. All(". drum")[i]; btn. add. Event. Listener("click", function () { alert("Clic! ; -)"); } Sappiamo che ogni bottone ha una classe specifica (w, a, etc) ed una classe «generica» drum associata. Se vogliamo visualizzare il nome della prima classe (w, a, etc) è sufficiente modificare il codice della alert in questo modo: alert("Clic! ; -) | Class: " + this. class. List[0]);
Passare una funzione come parametro Possiamo passare una funzione come parametro di un’altra funzione. Osserviamo il seguente codice: function add(num 1, num 2) { return num 1 + num 2; } function multiply(num 1, num 2) { return num 1 * num 2; } function calculator(num 1, num 2, operator) { return operator(num 1, num 2); } console. log(calculator(3, 3, add)); console. log(calculator(3, 3, multiply));
Passare una funzione come parametro Osserviamo il comportamento del codice. La funzione calculator riceve i due valori numerici su cui operare e, come terzo parametro, una funzione che verrà «associata» alla variabile operator. Questa associazione ci consentirà di chiamare la funzione passata (sia questa add o multiply) all’interno del blocco di codice della funzione calculator. Queste funzioni vengono anche denominate Higher Order Function (funzioni di ordine superiore).
Debugger • Il debugger è un software che consente di analizzare il codice per consentirci di individuare eventuali bug (errori di programmazione). • Molti ambienti integrati di sviluppo (IDE), come ad esempio Visual Studio, integrano al loro interno un debugger. • Attivando il debugger è possibile verificare «step by step» il comportamento del nostro codice, alla ricerca di eventuali anomalie che determinano errori a runtime o errori logici.
Debugger della developer toolbar Una delle funzionalità più interessanti della developer toolbar di Google Chrome è il debugger integrato. Per avviare il debugger è sufficiente accedere alla Console della developer toolbar, scrivere «debugger; » e premere shift + invio. Una volta effettuata questa operazione è sufficiente provare ad inserire una istruzione (ad esempio la chiamata ad una funzione) per verificarne il comportamento «step by step» .
Proviamo il debugger Osserviamo il comportamento del debugger chiamando la funzione calculator vista in precedenza passando alternativamente le due funzioni add e multiply come parametro.
Riprodurre un suono in Javascript • Per riprodurre un suono in Javascript possiamo sfruttare le Audio API di HTML 5. • Il codice per la riproduzione dell’audio è estremamente semplice: var snd = new Audio("sounds/crash. mp 3"); snd. play(); • Qui trovate la documentazione delle Audio API: https: //developer. mozilla. org/en. US/docs/Web/API/HTMLAudio. Element
Esercizio – Drum Machine Aggiorniamo il nostro codice per eseguire un suono nel momento in cui l’utente clicca sul pulsante: var btn. Count = document. query. Selector. All(". drum"). length; for (i = 0; i < btn. Count; i++) { var btn = document. query. Selector. All(". drum")[i]; btn. add. Event. Listener("click", function () { var audio = new Audio("sounds/crash. mp 3"); audio. play(); } Osserviamo però che, a prescindere dal pulsante cliccato, il suono riprodotto è sempre lo stesso, abbiamo quindi bisogno di un meccanismo per riconoscere il tasto premuto ed emettere un suono diverso di conseguenza.
Identificare l’elemento - this Proviamo ad aggiungere il codice: console. log(this); nella funzione che associamo con l’add. Event. Listener. Osserviamo che this contiene un riferimento all’elemento che ha chiamato la funzione. Infatti una volta cliccato un qualsiasi bottone, la console visualizzerà il codice html dell’elemento:
Esercizio – Drum Machine Completiamo il nostro codice: var btn. Count = document. query. Selector. All(". drum"). length; for (i = 0; i < btn. Count; i++) { var btn = document. query. Selector. All(". drum")[i]; btn. add. Event. Listener("click", function () { var drum = this. class. List[0]; var sound = ""; switch (drum) { case "w": sound = "sounds/tom-1. mp 3"; break; case "a": sound = "sounds/tom-2. mp 3"; break; case "s": sound = "sounds/tom-3. mp 3"; break;
Esercizio – Drum Machine case "d": sound = "sounds/tom-4. mp 3"; break; case "j": sound = "sounds/crash. mp 3"; break; case "k": sound = "sounds/kick-bass. mp 3"; break; case "l": sound = "sounds/snare. mp 3"; break; } if (sound !== "") { var audio = new Audio(sound); audio. play(); } }); }
Gli oggetti in Javascript La sintassi più elementare per creare un nuovo oggetto in Javascript è la seguente: var auto = { colore: "rosso", numero. Posti: 5, velocita: 120 } var auto 2 = { colore: "verde", numero. Posti: 4, velocita: 110 } Questa sintassi però ci costringe a dover riscrivere questo codice qualora si volesse avere una seconda auto con altre caratteristiche (vedi auto 2).
Osserviamo che Una volta creato l’oggetto auto, possiamo interrogare l’oggetto usando la sintassi che abbiamo utilizzato in passato con gli oggetti già presenti su Javascript.
Constructor function È una funzione che consente di creare un nuovo oggetto. La prima lettera del nome della funzione deve essere maiuscola, per indicare che si tratta di un costruttore e non di una funzione «classica» . function Automobile(colore, numero. Posti, velocita) { this. colore = colore; this. numero. Posti = numero. Posti; this. velocita = velocita; }
Constructor function Ci consentono di evitare la riscrittura del codice ogni volta che vogliamo avere un secondo o un terzo elemento dello stesso tipo. La sintassi per creare un nuovo oggetto sarà la seguente: var auto = new Automobile("rosso", 2, 230); var auto 2 = new Automobile("verde", 5, 180); var auto 3 = new Automobile("grigio", 7, 150);
Metodi di un oggetto Come sappiamo un metodo è una funzione associata ad uno specifico oggetto. In Javascript i metodi possono essere definiti all’interno del constructor utilizzando questa sintassi: function Automobile(colore, numero. Posti, velocita) { this. colore = colore; this. numero. Posti = numero. Posti; this. velocita = velocita; this. accelera = function () { this. velocita += 5; } this. frena = function () { this. velocita -= 5; } }
Eventi della tastiera Possiamo aggiungere un listener che «ascolta» lo stato della pressione dei tasti della nostra tastiera: gli eventi che possiamo associare al listener sono: • Keydown (il tasto è stato premuto) • Keypress (il tasto viene tenuto premuto) • Keyup (il tasto è stato rilasciato) N. B. L’evento keypress risulta attualmente «deprecated» , significa che è stato rimosso dagli standard web e che potrebbe non essere supportato in futuro.
Aggiungiamo il listener In questo caso, l’oggetto a cui dobbiamo collegare il listener è l’intero documento. Proviamo a scrivere il seguente blocco di codice: document. add. Event. Listener("keydown", function () { alert("Hai premuto un tasto!"); });
Identificare il tasto premuto Se aggiungiamo un parametro alla funzione che gestisce l’evento, questo parametro andrà a ricevere un oggetto che conterrà informazioni sull’evento generato. Proviamo quindi a scrivere questa porzione di codice e a vedere cosa viene visualizzato nella console. document. add. Event. Listener("keydown", function (event) { console. log(event); });
funzione riproduci. Suono() A questo punto ci serve la possibilità di gestire la riproduzione del suono da due diversi ambiti: il clic su uno dei button nel codice html e la pressione di un tasto. Creiamo quindi una nuova funzione che ci consente di gestire da un solo posto la scelta del suono da riprodurre.
funzione riproduci. Suono() function riproduci. Suono(drum) { var sound = ""; switch (drum) { case "w": sound = "sounds/tom-1. mp 3"; break; [. . ] // COPIATE E INCOLLATE IL «VECCHIO» CODICE QUI case "l": sound = "sounds/snare. mp 3"; break; } if (sound !== "") { var audio = new Audio(sound); audio. play(); } }
Modifica delle add. Event. Listener() // Button var btn. Count = document. query. Selector. All(". drum"). length; for (i = 0; i < btn. Count; i++) { var btn = document. query. Selector. All(". drum")[i]; btn. add. Event. Listener("click", function () { var drum = this. class. List[0]; riproduci. Suono(drum); } // Key. Down document. add. Event. Listener("keydown", function (event) { riproduci. Suono(event. key. to. Lower. Case()); });
Aggiungiamo una semplice animazione Aggiungiamo questo stile nel nostro codice html: . drum. Pressed{ background-color: red; color: #fff; } Aggiungiamo questa funzione al nostro Javascript: function anima. Bottone(drum) { document. query. Selector(". " + drum). class. List. add("drum. Pressed"); }
anima. Bottone() Chiamiamo la funzione anima. Bottone() dalle funzioni dei due listener. // Button var btn. Count = document. query. Selector. All(". drum"). length; for (i = 0; i < btn. Count; i++) { var btn = document. query. Selector. All(". drum")[i]; btn. add. Event. Listener("click", function () { var drum = this. class. List[0]; riproduci. Suono(drum); anima. Bottone(drum); } // Key. Down document. add. Event. Listener("keydown", function (event) { riproduci. Suono(event. key. to. Lower. Case()); anima. Bottone(event. key. to. Lower. Case()); });
Funziona… quasi! Se proviamo a visualizzare la nostra «drum machine» osserviamo che l’animazione funziona, ma una volta rilasciato il bottone ci troviamo ancora con il button nello stato di premuto (sfondo rosso). Per ovviare a questo problema possiamo utilizzare diversi meccanismi. Uno di questi potrebbe essere quello di utilizzare l’evento onkeyup per rimuovere la classe drum. Pressed.
set. Timeout() Un altro modo per risolvere il problema è sfruttare il metodo set. Timeout() che consente di eseguire una funzione dopo un certo intervallo di tempo. Correggiamo quindi la funzione anima. Bottone() per utilizzare questo metodo. function anima. Bottone(drum) { var btn = document. query. Selector(". " + drum) if (btn !== null) { btn. class. List. add("drum. Pressed"); set. Timeout(function () { btn. class. List. remove("drum. Pressed"); }, 300); } }
Callback Function In precedenza avevamo introdotto le Higher Order Function. Con l’esempio del Calcolatore abbiamo visto che sono tutte quelle funzioni che accettano tra i parametri almeno una funzione. Le funzioni che vengono passate alle Higher Order Function vengono invece denominate Callback Function.
FINE
- Slides: 137