JavaScript


JavaScript

La pagina fin qui creata è statica, ovvero i dati degli eventi sono scritti in maniera fissa, non modificabile, all’interno del file HTML. Chiaramente non è quello che vogliamo, perché il nostro obiettivo è che ogni volta che l’utente apre la pagina, gli mostri gli eventi aggiornati in quel momento: vogliamo una pagina dinamica. Per fare questo ci serve l’ultimo componente di HTML5: JavaScript.

Un po’ di storia

Bernard Eich

JavaScript è nato all’interno della Netscape, la società americana che sviluppò nel 1993 il primo web browser grafico di larga diffusione (ricordiamo che il web è nato nel 1989 in Europa). Nel 1995 cercavano una tecnologia per rendere dinamiche le pagine web e diedero l’incarico al neo-assunto Bernard Eich di creare un linguaggio di programmazione per competere con i rivali (Java e Microsoft). Gli diedero 10 giorni di tempo, nel maggio 1995.

Eich riuscì nell’impresa e creò il linguaggio JavaScript, definito nel suo annuncio ufficiale come “open, cross-platform object scripting language” che avrebbe dovuto “complementare il linguaggio Java”.

Sembra che il prefisso Java sia stato scelto intenzionalmente per creare confusione e per scherzo. In ogni caso la Sun Microsystem, che deteneva i diritti di Java a quel tempo, non protestò, e cosi è rimasto questo nome.

JavaScript logo

Da allora il linguaggio è cresciuto in funzionalità e diffusione, fino ad arrivare nel 2019 ad essere tra i 10 linguaggi più usati al mondo, in continua crescita. La sua vitalità è testimoniata dagli standard in continuo aggiornamento. Le funzionalità di JavaScript sono infatti definite e standardizzate dalla ECMA (European Computer Manufacturers Association), con sede a Ginevra. L’ultima versione dello standard JavaScript si chiama ES2017 (anche detto ES8, giusto per creare un po’ più di confusione).

La nascita un po’ casuale di questo linguaggio è uno dei motivi per cui molte cose in JavaScript non hanno una ragione particolare, almeno nella versione classica (fino allo standard ES5 del 2009).

Inoltre, JavaScript lascia molta libertà agli sviluppatori di decidere il loro stile di programmazione. Questo fa sì che, senza delle linee guida condivise tra sviluppatori, il codice scritto da persone diverse finisce per essere incompatibile o incomprensibile. Per evitare il problema, è necessario scegliere una linea guida comune. Ne esistono molte, per semplicità possiamo usare quella ufficiale di w3school.

Per una guida più completa potete consultare questa pagina con le linee guida di Douglas Crockford.

Agganciare HTML e JS

Nel nostro editor preferito, creiamo un file index.html. Se usate VSCode, potete generare lo scheletro della pagina premendo ! quandoil file è ancora vuoto.

Creando un file nella stessa cartella dell’index.html e lo chiamiamo script.js. Per fare una prova, per ora mettiamo solo la visualizzazione di un pop-up, che in JavaScript si ottiene con la funzione alert().

alert("JS test");

Se proviamo ora ad aggiornare la nostra pagina, non succede niente. Perché?

Come abbiamo detto, tutto parte sempre dall’HTML. Il nostro browser comincia a leggere il file HTML che abbiamo indicato con l’URL nella barra di navigazione e riga dopo riga interpreta quello che c’è scritto. Dobbiamo quindi mettere nel nostro index.html l’istruzione per dirgli di andare a leggere il file.

Il tag necessario per questa operazione è <script>, a cui bisogna specificare come attributo il nome del file che vogliamo caricare. Ecco il codice che ci serve:

<script src="script.js"></script>

Dove mettiamo questa riga di codice? Nei testi a volte viene suggerito di mettere il tag <script> all’interno del tag <head>, ma noi non seguiremo questo suggerimento. Il motivo è di efficienza: di default il browser eseguirà tutto il codice dentro il nostro script e solo dopo continuerà ad interpretare la pagina, con la conseguenza l’utente potrebbe avvertire una fastidiosa sensazione di lentezza.

Come sempre in VSCode, digitando script:src si avvia l’auto-completamento.

Avviando la pagina otteniamo la seguente cosa.

Bene, il file JavaScript è collegato correttamente! 🥳

Prima di andare avanti, vogliamo semplificarci un po’ le cose usando una libreria molto diffusa che permette di ridurre drasticamente il codice da scrivere per eseguire operazioni comuni: jQuery.

Un’altra libreria molto usata è Lodash, che semplifica la manipolazione di array, stringhe e oggetti.

Importare jQuery

jQuery (pronuncia jeiquiri) è una delle librerie più diffuse per JavaScript, perché permette di semplificare e velocizzare operazioni che altrimenti richiederebbero un bel po’ di linee di codice. Per scaricare l’ultima versione, andate sul sito ufficiale, sezione Download, e selezionate la versione “Download the compressed, production jQuery”. Se volete scaricare il file, vi conviene premere con il tasto destro sul link e selezionare “Salva destinazione con nome…” o l’equivalente nel vostro browser.

Come al solito, salvate il file nella stessa cartella dove si trova il file html.

Se usate repl.it, potete anche cliccare sulla sinistra nella gestione dei packages, cercare JQuery e premere sul + per aggiungerlo al progetto.

Attenzione: la semplificazione offerta da jQuery non è gratis. Questa libreria è piuttosto pesante ed il browser ci metterà un po’ di tempo a caricarla, con il rischio di inficiare l’esperienza utente. Quando diventerete sviluppatori front-end professionisti, dovrete fare attenzione anche a queste cose. Il codice JavaScript “puro”, senza l’uso di nessuna libreria, è anche detto VanillaJS; qui trovate un sito scherzoso sull’argomento.

Colleghiamo il file nel nostro progetto, mettendo il tag script prima dell’inclusione del nostro file JavaScript. Questo è fondamentale perché, come abbiamo detto, il browser interpreta le linee in ordine, quindi è necessario prima importare jQuery e dopo il nostro codice che dipende da questa libreria.

<script src="jquery-3.5.1.min.js"></script>
<script src="script.js"></script>

È interessante notare come non sia possibile importare una dipendenza direttamente all’interno del file JavaScript, ma bisogna passare per il file HTML.

Per risolvere questo problema, sono nati vari framework più o meno complessi che permettono di gestire le dipendenze in maniera efficente ed efficace. Chi è interessato, può ad esempio studiarsi Webpack.

Primi passi con jQuery

Per cominciare ad usare jQuery, dobbiamo inizializzare la libreria. Andiamo sul nostro file JavaScript e aggiungiamo il seguente snippet di codice.

var init = function() {
  alert("JS test with Jquery");
}

$(document).ready(init);

Vediamo in dettaglio cosa abbiamo fatto. Partiamo dall’ultima riga.

$(document).ready(init);

Il simbolo $ è il nome della variabile oggetto messa a disposizione dalla libreria jQuery. In JavaScript infatti, il dollaro è un carattere valido per l’inizio di una nome di una variabile o funzione.

jQuery mette a disposizione solo la variabile $. Pubblicare una sola variabile è una cosa molto comune in JavaScript, come vedremo.

La variabile document è invece messa a disposizione dal browser e contiene tutte le informazioni che riguarda la pagina html e i relativi fogli di stile CSS. È il nostro punto di contatto tra l’html e gli script JavaScript.

L’espressione $(document) serve a inizializzare la libreria jQuery con il documento corrente. In questo modo inoltre jQuery prende il controllo del documento e noi non andremo mai più ad usare la variabile document direttamente, ma passeremo sempre attraverso l’oggetto $().

Immediatamente dopo l’inizializzazione viene chiamato il metodo .ready(), che richiede come parametro una funzione. Passare come parametri funzioni è una cosa estremamente comune in JavaScript e anche noi la useremo estensivamente. Il metodo ready invocherà la funzione passatagli come parametro, nel nostro caso init, quando il caricamento della pagina sarà completo e quindi saremo pronti per il processamento del documento.

Vediamo ora come abbiamo dichiarato la funzione init.

var init = function() {
  alert("JS test with Jquery");
}

Facciamo particolare attenzione a questa sintassi. Abbiamo dichiarato la variabile init ed abbiamo usato l’operatore di assegnazione (il simbolo =) per assegnarli come valore una funzione. In questo modo abbiamo di fatto creato una variabile che può essere invocata come una funzione (ovvero con le parentesi tonde, init()).

La funzione dichiarata in questo modo non ha un nome suo, infatti non c’è nessun identificativo fra la keyword function e le parentesi tonde che seguono. Questo tipo di funzioni si chiamano anonime, in inglese anonymous-functions. Chi vuole approfondire può leggere questo articolo.

Se ora ricarichiamo la pagina, otteniamo un comportamento molto simile al procedente.

Scope di funzione

Prima di andare avanti, è bene impostare correttamente il file JavaScript. Questo linguaggio infatti lascia moltissima libertà ai programmatori nell’organizzazione del codice, e questa è una buona cosa perché è possibile creare librerie e framework molto potenti, ma senza un po’ di disciplina si finisce con lo scrivere del codice che è completamente non mantenibile e soggetto ad infiniti tipi di bug. Rimandiamo al link all’inizio di questa pagina per una style-guide.

Fate particolare attenzione quando copiate-incollate codice da Internet. Assicuratevi che sia scritto bene e che segua le vostre convenzioni. Alcune stime non ufficiali dicono che l’80% del codice JavaScript reperibile su Internet è monnezza, quindi state in guardia.

Per cominciare, bisogna sapere che le variabili in JavaScript dichiarate con var hanno uno scope di funzione, ovvero sono visibili in tutta la funzione in cui sono state dichiarate, indipendentemente dal blocco in cui si trovano.

Cosa significa in pratica? Significa che i seguenti due snippet di codice sono equivalenti, provate ad implementarli:

var init = function() {
	var myName = "Harry";
	if (myName == "Harry") {
		var myFriend = "Ron";
	}
	alert("myFriend name is "+ myFriend);
}
var init = function() {
	var myName = "Harry";
	var myFriend;
	if (myName == "Harry") {
		myFriend = "Ron";
	}
	alert("myFriend name is "+ myFriend);
}

Come vedete, la dichiarazione della variabile myFriend è salita fino in cima alla funzione, uscendo dallo scope dell’if. Questo è un comportamento inusuale, rispetto ad altri linguaggi, e potenzialmente rischioso! Infatti si rischia un conflitto di nomi tra variabili dichiarate anche lontano fra loro.

Questo comportamento si chiama hoisting. Vedi la JavaScript Hoisting su w3schools per dettagli.

La cosa è particolarmente pericolosa se si dichiarano variabili al di fuori di tutte le funzioni. Cosa succede in questo caso? Le variabili vanno a finire nella funzione globale del browser, che si chiama window(). Come sappiamo, le variabili globali sono estremamente pericolose perché potrebbero andare in conflitto in qualsiasi momento e in modo imprevedibile con altre variabili dichiarate chissà dove, da noi o da altre librerie.

Uso di let e const

Per mitigare il problema, possiamo dichiarare le variabili con le keyword let o const:

var init = function() {
	var myName = "Harry";
	if (myName == "Harry") {
		let myFriend = "Ron";
	}
	alert("myFriend name is "+ myFriend); // errore
}

Con let o const, le variabili hanno una visibilità di ambito (scope), ovvero sono visibili solo all’interno del blocco racchiuso in parentesi graffe in cui si trovano e non sono utilizzabili all’esterno.

In particolare:

  • let dichiara una variabile mutabile, che può quindi essere riassegnata
  • const dichiara una variabile immutabile, che non può essere riassegnata.

Questo è un comportamento più simile a quello che ci si aspetta e più sicuro.

Originariamente esisteva solo la parola chiave var. Le parole chiave let e const sono state standardizzate ufficialmente solo nel 2015, è per questo che la maggior parte di codice scritto prima di quella data non li usa e che alcuni sviluppatori veterani usino var semplicemente per abitudine.

Precisazione sul significato delle keyword

Per memorizzare, può essere utile precisare cosa significano le keyword che usiamo:

  • var è l’abbreviazione di variabile
  • let lo possiamo tradurre in questo caso con “permetti” (sottinteso: l’uso della variabile nel mio codice), è una delle prime keyword della storia, risalente a Lisp (1958)
  • const è l’abbreviazione di “constant” che significa costante!

Cosa devo usare quindi?

Per farla breve:

  • se la variabile è costante, usate const
  • in tutti gli altri casi, usate let

Usate var se e solo se sapete esattamente cosa state facendo

Gestione del click del mouse

Per gestire il click del mouse, ci sono varie strategie, noi useremo quella idiomatica di JQuery, attraverso la funzione on().

Per cominciare, nella nostra pagina HTML aggiungiamo un bottone.

<button  id="moveUp">move UP</button>

Per associare il click del mouse, nella nostra funzione di init mettiamo la seguente riga di codice:

$("#moveUp").on("click",moveUp);

Vediamo cosa abbiamo fatto:

  • con $("#moveUp") ho selezionato l’elemento con id #moveUp#
  • con on("click",moveUp) sto dicendo che quando si clicca con il mouse, dovrò richiamare la funzione moveUp (che ancora non abbiamo dichiarato, lo faremo dopo).

Altri eventi che possono essere gestiti

Esistono tanti tipi di eventi, come ad esempio:

  • mouseenter: l’utente passa il mouse sopra l’elemento (senza cliccarlo)
  • mouseleave: l’utente toglie il mouse da sopra l’elemento
  • dblclick: doppio click sull’elemento
  • keypress: è stato premuto un tasto
  • scroll: l’utente sta scorrendo la pagina

La lista è lunghissima, l’elenco completo lo trovate qui.

Modifica dello stile da JavaScript

Immaginiamo di avere una immagine e volerla muovere con dei tasti.

Questo è il wireframe della pagina:

Il nostro codice sarà, prendendo ad esempio l’immagine di un lama:

<button  id="moveUp">Move UP</button>
<img  id="lamaImage"  src="./lama.jpeg"  alt="Immagine del lama">
#lamaImage {
	position:absolute;
	left:50%;
	top:50%;
	width:  12%;
}

Per leggere il valore di una proprietà, ad esempio il valore di top dell’elemento con id “moveUp”, possiamo scrivere:

let topValue = $("#lamaImage").css("top");

Da notare che il valore delle posizioni vengono sempre ritornate in pixels, con la desinenza px. Per poter leggere il valore intero, possiamo fare il parsing:

let topValue = parseInt($("#lamaImage").css("top"));

Se vogliamo invece scrivere una proprietà, dobbiamo chiamare la stessa funzione .css() con due argomenti:

$("#lamaImage").css("top", topValue);

Nel complesso il nostro file JavaScript sarà come segue:

let moveUp = function () {
	let topValue = parseInt($("#lamaImage").css("top"));
	let newTopValue = topValue-10;
	console.log(`Sposto il lama in alto (top value: ${topValue} -> ${newTopValue})`);
		$("#lamaImage").css("top", newTopValue);
};

let init = function () {
	$("#moveUp").on("click", moveUp);
};
  
$(document).ready(init);

In questo modo spostiamo di 10px in su l’immagine ad ogni click.

Modifica dello stile con JavaScript+CSS

Come abbiamo visto, modificare lo stile da JavaScript è possibile, ed in alcuni casi non è possibile evitarlo: ad esempio se dobbiamo cambiare ad ogni pressione del tasto il valore di top di un valore diverso..

In linea generale perì è meglio evitare di modificare lo stile da JavaScript, perché dobbiamo ricordarci che tutto quello che riguarda l’aspetto visivo è competenza del foglio di stile .css. Come faccio quindi a rendere dinamico l’aspetto della pagina, mantenendo tutte le regole nel foglio di stile?

La soluzione è quella di creare delle classi dedicate allo stile, scrivere le regole relative nel foglio di stile, ed aggiungere e togliere le classi in modo dinamico in JavaScript.

Facciamo un esempio: aggiungiamo un bottone che mi ingrandisce l’immagine.

<button  id="enlargeButton">enlarge</button>

Quando si preme questo pulsante, l’immagine dovrà ingrandirsi. Scrivo una regola CSS per questo.

.enlarged {
	transform:  scale(1.25);
	transition:  transform  0.25s  ease;
}

Collego il bottone ad una funzione che mi aggiunge la classe:

function enlarge() {
	$("#lamaImg").addClass("enlarged");
}
let init = function() {
	$("#enlargeButton").on("click",enlarge);
}

Se volessi togliere una classe, posso usare analogamente .removeClass().

Written with StackEdit.