Skillbook Logo
foto profilo

Skill Factory

Lista post > Impariamo a programmare con JavaScript - Lezione 15

Impariamo a programmare con JavaScript - Lezione 15

Gino Visciano | Skill Factory - 06/12/2017 22:32:47 | in Tutorials

Benvenuti alla quindicesima lezione, in questa lezione impareremo a fare chiamate AJAX (Asynchronous JavaScript and XML) per creare applicazioni Web interattive.
Per capire che cos'è la tecnica AJAX  dobbiamo comprendere il significato del termine Asincrono  e le caratteristiche fondamentali del linguaggio XML.


Sincrono e Asincrono
Un'applicazione, una funzione oppure un task applicativo si dicono sincroni quando durante la loro esecuzione non è possibile fare altre operazioni.
Ad esempio un'applicazione Web che utilizza le classiche pagine Html è sincrona, perché durante l'invio di una richiesta, l'utente resta in attesa delle risposta del server e fin quando non viene caricata la nuova pagina Html non può fare altro.
Di base anche i metodi di applicazioni Java oppure C# vengono eseguiti in modalità sincrona; il metodo chiamante resta in attesa fino a quando il metodo chiamato non termina.
Naturalmente questo comportamento può creare dei colli di bottiglia nelle applicazioni, per migliorare la risposta generale delle applicazioni bisogna utilizzare la programmazione multithreading o asincrona.


Attenti a non fare confusione tra programmazione multithreading  e asincrona, nel primo caso intendiamo metodi (gruppi d'istruzioni) che girano contemporaneamente in memoria ciascuno all'interno di un thread, come se fossero tanti programmini in esecuzione allo stesso tempo, nel secondo caso si tratta di funzioni (gruppi d'istruzioni) registrate in una coda (streaming) che vengono eseguite, indipendentemente dal programma principale, all'interno dello stesso thread.

La programmazione asincrona è più performante di quella multithread perchè utilizza un solo thread, senza creare sovracarico (overhead), in termini di risorse,

Linguaggi come Java e C# possono sia usare la programmazione multithreading, associando i task o i metodi a più thread, sia usare la programmazione asincrona, se fanno uso di code.
Javascript non può gestire la programmazione multithreading perché è single-thread,  quindi per migliorare le performance delle applicazioni usa la programmazione asincrona.

Fondamentali per gestire la programmazione asincrona con JavaScript sono le funzioni di callback.

Che cos'è una funzione di callback
Le funzioni di callback sono degli ascoltatori che rilevano la fine di un task asincrono oppure di un evento.
In JavaScript le funzioni di callback possono essere passate come argomenti ad altre funzioni, come se fossero variabili ed essere eseguite quando è richiesto.

Nell'esempio seguente la funzione mandaMessaggioAsincrona  riceve come argomento una funzione di callback anonima; quando arriva la risposta, la funzione di callback visualizza il messaggio di risposta.

messaggio = preparaRichiesta();  
mandaRichiestaAsincrona(messaggio, function (risposta) {  
visualizza(risposta);}
);  
visualizza("Siamo in attesa di risposta dal server ...");  

Il programma JavaScript seguente mostra il comportamento di una funzione sincrona ed una asincrona.

console.log("Inizio processo ...");
// Task Sincrono
var messaggio = preparaMessaggio("Azione 1: Messaggio inviato ...");
var risposta = mandaMessaggioSincrona(messaggio);
console.log(risposta);
console.log("Sono di nuovo disponibile ...");
// Task Asincrono
messaggio = preparaMessaggio("Azione 3: Messaggio inviato ...");
mandaMessaggioAsincrona(messaggio);
console.log("Sono di nuovo disponibile ...");
messaggio = preparaMessaggio("Fine processo ...");
attendiCallBack(15,messaggio);
// Fine Task
//Area Funzioni
// Funzione che prepara il messaggio da inviare

function preparaMessaggio(messaggio){
return messaggio;
}
// Funzione che invia il messaggio ed attende la risposta in modo sincrono
function mandaMessaggioSincrona(messaggio){
console.log(messaggio);
console.log("Attendo risposta ...");
//Attende 10 secondi poi invia il messaggio di risposta
attendi(10);
return "Azione 2: Risposta ricevuta ...";
}
// Funzione che invia il messaggio ed attende la risposta in modo asincrono
function mandaMessaggioAsincrona(messaggio){
console.log(messaggio);
console.log("Attendo risposta ...");
messaggio=preparaMessaggio("Azione 4: Risposta ricevuta ...");
attendiCallBack(10,messaggio);
}
// Funzione creata per simulare l'attesa del messaggio function
attendi(secondi){
var millisecondi=secondi*1000;
var dataInizio = new Date();
var dataCorrente = null;
do {dataCorrente = new Date();
} while(dataCorrente-dataInizio < millisecondi);
}
// Funzione di callback
function attendiCallBack(secondi,messaggio){
var millisecondi=secondi*1000;
setTimeout(function (){
console.log(messaggio);
},millisecondi);
};

 

Che cos'è l'XML
L'XML (eXtensible Markup Language) è un metalinguaggio che si usa per descrivere strutture di dati.
Qualunque documento, modello o tabella si può rappresentare attraverso una struttura ad albero che inizia sempre con una radice, può avere uno o più rami (nodi), che possono contenere una o più foglie, che contengo dati.

Con linguaggio XML, attraverso l'uso di tag personalizzati, si possono creare gli alberi che descrivono una stuttura di dati, come mostra l'esempio successivo.

Immaginate di avere un curriculum così strutturato:

CURRICULUM
- Anagrafica
   Franco Rossi
   20/04/1989
   Roma
   Maturità Scientifica
- Hobby
   Calcio
   Jazz
- Competenze
   Programmazione Javascript
   Customer Care
- Esperienze
-- Esprienza

     Skill Factory
     2010
     Sviluppo sito Web
-- Esprienza
     Major Bit Consulting
     2011
     Sviluppo App


L'albero seguente descrive la struttura del curriculum:



Il documento seguente descrivere il curriculum in linguaggio XML, i Tag personalizzati sono stati creati facendo riferimento agli elementi dell'albero:

<!--?xml version="1.0" encoding="UTF-8"?-->
<curriculum>
<anagrafica>
<nome>Franco</nome>
<cognome>Rossi</cognome>
<data_nascita>  20/04/1989</data_nascita>
<luogo_nascita>Roma</luogo_nascita>
<titolo_studio>Maturita' Scientifica</titolo_studio>
</anagrafica>
<hobby>
<sport>Calcio</sport>
<musica>Jazz</musica>
</hobby>
<competenze>
<competenze_tecniche>Programmazione Javascript</competenze_ tecniche>
<competenze_relazionali>Customer Care</competenze_ relazionali>
</competenze>
<esperienze>
<esperienza>
<azienda>Skill Factory</azienda>
<anno>2010</anno>
<descrizione> Sviluppo sito Web</descrizione>
</esperienza>
<esperienza>
<azienda>Major Bit Consulting</azienda>
<anno>2011</anno>
<descrizione>Sviluppo App</descrizione>
</esperienza>
</esperienze>
</curriculum>

Un documento XML si dice ben formato se i tag sono tutti aperti a chiusi <tag>...</tag>, i nomi dei tag non devono contenere spazi e in nessun caso si crea la condizione seguente:  <tag>...<tag1></tag>...</tag1>.

La potenzialità dei documenti XML è quella di essere interpretati dai principali software per la gestione e la visualizzazione dei dati. Ad esempio guardate cosa accade se salviamo il nostro documento XML con il nome curriculum.xml e successivamente lo apriamo con un brawser qualunque:

Il browser interpreta la struttura del documento XML curriculum.xml e con le frecce a sinistra ci permette di chiudere ed aprire i nodi per leggere le informazioni contenute nelle foglie.

Anche JavaScript può interpretare il contenuto di un documento XML, il programma seguente trasforma il file curriculum.xml in un oggetto JavaScript e ne visualizza il contenuto.

// Modulo per leggere file
var fs = require('fs');
// Modulo per eseguire ricerche in un documento XML
var xpath = require('xpath');
// Modulo che permette di creare un documento XML partendo da una stringa XML
var dom = require('xmldom').DOMParser;
// Leggo il curriculum
fs.readFile('curriculum.xml','utf8', function (err, data) {
if (err) throw err;
// Converto il file letto in stringa ed elimino i return ed i line feed
var sdata=data.toString();
sdata=sdata.replace(/\r|\n/g,'');
// Creo l'oggetto XML usando la stringa XML creata precedentemente
var doc = new dom().parseFromString(sdata);
// Leggo i nodi del curriculum e ne visualizzo il contenuto
var nodi = xpath.select("//anagrafica", doc);
var foglie=nodi[0].childNodes;
for(var x=0;x<foglie.length;x++ ){
console.log(foglie[x].childNodes[0].toString().trim());
}
var nodi = xpath.select("//hobby", doc);
var foglie=nodi[0].childNodes;
for(var x=0;x<foglie.length;x++ ){
console.log(foglie[x].childNodes[0].toString().trim());
}
var nodi = xpath.select("//competenze", doc);
var foglie=nodi[0].childNodes;
for(var x=0;x<foglie.length;x++ ){
console.log(foglie[x].childNodes[0].toString().trim());
}
var nodi = xpath.select("//esperienze/esperienza", doc);
var foglie=nodi[0].childNodes;
for(var x=0;x<foglie.length;x++ ){
console.log(foglie[x].childNodes[0].toString().trim());
}
var foglie=nodi[1].childNodes;
for(var x=0;x<foglie.length;x++ ){
console.log(foglie[x].childNodes[0].toString().trim());
}
});

 

Che cosa sono gli schemi XML
Gli schemi sono documenti che servono per descrivere la struttura di un documento XML.
Principalmente si usano due tipi di schemi i DTD e gli XML Schema (XSD).
Inizialmente gli schemi più diffusi erano i DTD (Document Type Definition), documenti di tipo testo che attraverso l'uso di un metalinguaggio permettevano d'impostare le regole fondamentali da rispettare per la formattazione del documento XML, un contratto da rispettare durante la sua composizione, altrimenti non è valido.
In presenza di uno schema un documento XML oltre ad essere ben formato, deve essere anche valido.
Un programma che interpreta un documento XML e lo schema associato si chiama Parser.

Il DTD seguente descrive lo schema da rispettare per comporre il nostro curriculum.

<!ELEMENT curriculum (anagrafica,hobby, competenze, esperienze)>
<!ELEMENT anagrafica (nome,cognome,data_nascita, luogo_nascita,titolo_studio+)>
<!ELEMENT nome (#PCDATA)>
<!ELEMENT cognome (#PCDATA)>
<!ELEMENT data_nascita (#PCDATA)>
<!ELEMENT luogo_nascita (#PCDATA)>
<!ELEMENT titolo_studio (#PCDATA)>
<!ELEMENT hobby (sport,musica)>
<!ELEMENT sport (#PCDATA)>
<!ELEMENT musica(#PCDATA)>
<!ELEMENT competenze (competenze_tecniche*,competenze_relazionali*)>
<!ELEMENT competenze_tecniche (#PCDATA)>
<!ELEMENT competenze_relazionali (#PCDATA)>
<!ELEMENT esperienze (esperienza*)>
<!ELEMENT esperienza (azienda,anno,descrizione)>
<!ELEMENT azienda (#PCDATA)>
<!ELEMENT anno (#PCDATA)>
<!ELEMENT descrizione (#PCDATA)>

!ELEMENT permette di definire i nomi dei tag usati per indicare i nodi e le foglie all'interno del documento XML
Le foglie si distinguono dai nodi perché finiscono con la parola chiave #PCDATA.

Se nell'impostazione della struttura del documento travate i somboli seguenti: ?, + ed * hanno il significato seguente:

?=L'elemento può essere indicato 0 oppure 1 volta;
+=L'elemento può essere indicato 1 oppure più volte;
*=L'elemento può essere indicato 0 oppure più volte.

Per associare il DTD appena creato al nostro curriculum, bisogna aggiungere al documento XML la riga seguente:

<!DOCTYPE curriculum SYSTEM "curriculum.dtd"> 

dove

<!DOCTYPE elemento-radice SYSTEM "nome-file-dtd">

L'esempio seguente mostra dove inserire la riga con l'indicazione del DTD:

<!--?xml version="1.0" encoding="UTF-8"?-->
<!DOCTYPE curriculum SYSTEM "curriculum.dtd">
<curriculum>
<anagrafica>
<nome>Franco</nome>
...

Gli XML schema sono anch'essi documenti XML, non sono sostitutivi dei DTD, ma prevedono la possibilità di creare dei modelli dati fortemente tipati e sono molto usati in ambienti di sviluppo dove si usano linguaggi di programmazione tipo C, Java o linguaggi di specifica tipo SQL.

L'esempio seguente mostra uno XML schema complesso:

<?xml version="1.0"?>
<xsd:schema xmlns:xsd="https://www.w3.org/2001/XMLSchema">
    <xsd:element name="DIPENDENTE" type="TipoDipendente"/>
    <xsd:complexType name="TipoDipendente">
        <xsd:sequence>
            <xsd:element name="NOME" type="xsd:string"/>
            <xsd:element name="COGNOME" type="xsd:string"/>
            <xsd:element name="MATRICOLA" type="xsd:string"/>
            <xsd:element name="DATA_NASCITA" type="xsd:date"/>
            <xsd:element name="LUOGO_NASCITA" type="xsd:string"/>
            <xsd:element name="STIPENDIO" type="xsd:double"/>
            <xsd:element name="AZIENDA" type="xsd:string"/>
            <xsd:element name="TITOLO_STUDIO" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

La tabella seguente descrive i tipi dati disponibili per creare XML Schema:

Tipo di dato         Descrizione
xs:string                 Stringa di caratteri
xs:integer              Numero intero
xs:decimal             Numero decimale
xs:boolean            Valore booleano
xs:date                  Data
xs:time                  Ora
xs:uriReference   URI

Che cos'è AJAX
AJAX non è un linguaggio di programmazione, ma una tecnica che impiega JavaScript ed XML in modo Asincrono per creare applicazioni Web Interattive, l'acronimo è:

AJAX = Asynchronous JavaScript And XML

Quando l'utente che usa una pagina HTML genera un evento predefinito, la funzione JavaScript associata, crea un oggetto di tipo XMLhttpsRequest() con i dati da inviare al Server in modo asincrono.

In Microsoft Internet Explorer, l'oggetto XMLhttpsRequest viene istanziato come ActiveX.

Nell'esempio seguente valutiamo la tipologia di browser utilizzato per selezionare il tipo di oggetto da creare:

if (window.XMLhttpsRequest) {
xmlhttpsReq = new XMLhttpsRequest();
}
else if (window.ActiveXObject) {
xmlhttpsReq = new ActiveXObject("Microsoft.XMLhttps");
}

Per inviare la richiesta si utilizza la funzione open, come mostra l'esempio seguente:

xmlhttpsReq.open('POST', strURL, true);

Dopo l'invio della richiesta viene attivata una funzione di callback allo scopo di gestire la risposta del server.

xmlhttpsReq.onreadystatechange = function() {
//Se lo stato è completo
if (this.readyState == 4 && this.status == 200) {
/* Aggiorno la pagina con la risposta ricevuta dalla precendete richiesta dal web server.
Quando la richiesta termina il risultato è disponibie come responseText.*/
aggiornaPagina(this.xmlhttpsReq.responseText);
}
}

La proprietà readystate della richiesta, permette di controllare gli stati della richiesta, di seguito gli stati possibili:

  • 0 (UNINITIALIZED), la richiesta è stata inizializzata (prima di chiamare open());
  • 1 (LOADING), la richiesta è in stato di caricamento, non è ancora stata inviata (prima di chiamare send());
  • 2 (LOADED), la richiesta è stata inviata e sarà processata(solitamente a questo punto si può prendere il content headers dalla risposta);
  • 3 (INTERACTIVE), la richiesta è processata, il server non ha ancora inviato tutta la risposta, ma ne possono essere disponibili alcune parti;
  • 4 (COMPLETE), la risposta è completa, può essere presa e utilizzata.

La proprietà status della richiesta, permette di controllare se si sono verificati errori, di seguito i valori possibili:

  • 200 Risposta ottenuta con successo
  • 404 Pagina non trovata
  • 500 S'è verificato un errore sul Server

Laboratorio
Per svolgere questo Laboratorio serve Visual Studio Code oppure un IDE equivalente e node.js.
Inoltre si devono installare nella cartella /node/app-autocompletamento, dove sono stati salvati i file scheda.htmlAppAutoCompletamento.js, i moduli express e body-parser, con i comandi seguenti:

  1. npm install express --save
  2. npm install body-parser

 

L'obiettivo del Laboratorio è quello di creare una scheda dove inserire un nome e visualizzarlo.

L'applicazione utilizza AJAX per suggerire all'utente dei nomi. L'utente per scegliere il primo nome della lista, può premere la freccia giù, come mostra l'immagine seguente;

Creiamo la scheda (scheda.html):

<html>
<head>
<meta charset="UTF-8" />
<script type="application/javascript">
function loadNominativi(event) {
//Controllo se ho insrito un numero: numero=true se vero false se falso
var numero=String.fromCharCode(event.keyCode).match(/[0-9]/) ? true : false;
//Imposto la variabile nome con il valore inserito nel campo di input chiamato nome
var nome=document.getElementById("nome").value;
//Accedo al controllo se non ho inserito un numero
if(!numero){
//falg è true se il codice inserito è diverso dalla freccia giù altrimenti è false
var flag=event.keyCode!=40 ? true : false;
var xhttps = new XMLhttpsRequest();
xhttps.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//Eseguo il controllo se non ho premuto la freccia giù
if (flag){
document.getElementById("nominativi").innerHTML = this.responseText;
}
//Eseguo il controllo se ho premuto la freccia giù
else {
document.getElementById("input").innerHTML = this.responseText;
document.getElementById("nominativi").innerHTML = "<div id='nominativi'></div>";
document.getElementById("nome").focus();
}
}
};
if (flag){
xhttps.open("POST", "/app-autocompletamento/rest/load", true);
} else{
xhttps.open("POST", "/app-autocompletamento/rest/auto", true);
}
xhttps.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
xhttps.send("nome="+nome);
}
//Accedo se ho inserito un numero e lo elimino dal campo nome
else {
//Sostituisco il numero inserito con niente, perché voglio solo caratteri
nome=nome.replace(String.fromCharCode(event.keyCode),"");
document.getElementById("nome").value=nome;
 
}
}
//Gestisco il reset personalizzato della scheda
function resetta(){
var htmlNominativi="<div id='input'>";
htmlNominativi+="Nome: <input type='text' name='nome' id='nome' value='' autocomplete='off' onkeyup='loadNominativi(event);'>";
htmlNominativi+="<input type='submit' value='SALVA'><input type='button' value='RESET' onclick='resetta();'><br><br>";
htmlNominativi+="</div>";
document.getElementById("input").innerHTML = htmlNominativi;
htmlNominativi="<div id='nominativi'></div>";
document.getElementById("nominativi").innerHTML = htmlNominativi;
document.getElementById("nome").focus();
}
</script>
</head>
<body>
<div style="padding:10px;left:50px;top:50px;width:350px;border:2px solid #000000;border-radius:6px">
<form name="scheda_ins" method="POST" action="nominativi">
<div id="input">
Nome: <input type="text" name="nome" id="nome" value="" autocomplete="off" onkeyup="loadNominativi(event);">
<input type="submit" value="SALVA"><input type="button" value="RESET" onclick='resetta();'><br><br>
</div>
<div id="nominativi"></div>
<p style="color:red">[Freccia giù per completare]</p>
</form>
</div>
</body>
</html>

 

Creiamo l'applicazione (AppAutoCompletamento.js):

//Includo il framework express per semplificare la scrittura di app con node.js
var express = require('express');
var app = express();
//Imposto il parser per leggere i dati dalle richieste inviate dal Browser
var bodyParser = require('body-parser');
app.use(bodyParser.text({ type: 'text/html' }))
app.use(bodyParser.urlencoded({ extended: false }))
//Gestisco la richiesta iniziale di tipo GET per scaricare il file scheda.html
//localhost:8090/app-autocompletamento/rest/scheda.html link avvio applicazione
app.get('/app-autocompletamento/rest/scheda.html', function (req, res) {
//Imposto il protocollo MIME per la risposta
res.contentType("text/html");
//Invio al Brouser il file scheda.html
res.sendFile("c:\\node\\app-autocompletamento\\scheda.html");
});
//Gestisco tutte le richieste di tipo post inviate dal Browser
app.post('/app-autocompletamento/rest/*', function (req, res) {
//Imposto il path per decidere che tipo di azione eseguire
//Il comando esclude dall'url /app-autocompletamento/rest/
var path=req.path.substr(28);
//Imposto il nome tutto maiuscolo per evitare differenze tra maiuscolo minuscolo nei controlli
var nome=req.body.nome.toUpperCase();
//Imposto la lunghezza del nome passato
var lnome=nome.length;
//Imposto vettore dei nomi
var nominativi=[];
//Imposto variabile che contiene codice Html da sostiture nella pagina Html sul Browser
var htmlNominativi="";
switch(path){
case "load":
//Carico il vettore con i nomi ordinato
nominativi=getNominativi();
//Contiene il codice Html da sostiture nella pagina Html sul Browser
var htmlNominativi="<div id='nominativi'>";
if(lnome>0){
for (var i in nominativi) {
if (nome==nominativi[i].substr(0,lnome).toUpperCase()){
//Aggiungo alla pagina tutti i nomi che iniziano con il nome passato
htmlNominativi+=nominativi[i]+"<br>"
};
}
}
htmlNominativi+="</div>";
//Imposto il protocollo MIME per la risposta
res.contentType("text/xml");
//Invio il codice Html al Browser
res.send(htmlNominativi);
break;
case "auto":
//Carico il vettore con i nomi ordinato
nominativi=getNominativi();
//Imposto il Vettore con tutti i nomi che iniziano con il nome passato
var appNominativi=[];
//Imposto il nome completo se il nome passato contiene carratteri
if(lnome>0){
for (var i in nominativi) {
if (nome==nominativi[i].substr(0,lnome).toUpperCase()){
appNominativi.push(nominativi[i]);
};
}
htmlNominativi="<div id='input'>";
htmlNominativi+="Nome: <input type='text' name='nome' id='nome' value='"+appNominativi[0]+"' autocomplete='off' onkeyup='loadNominativi(event);'>";
htmlNominativi+="<input type='submit' value='SALVA'><input type='button' value='RESET' onclick='resetta();'><br><br>";
htmlNominativi+="</div>";
}
//Reimposto il campo di input di defult se il nome passato non contiene caratteri
else{
htmlNominativi="<div id='input'>";
htmlNominativi+="Nome: <input type='text' name='nome' id='nome' value='' autocomplete='off' onkeyup='loadNominativi(event);'>";
htmlNominativi+="<input type='submit' value='SALVA'><input type='button' value='RESET' onclick='resetta();'><br><br>";
htmlNominativi+="</div>";
}
//Imposto il protocollo MIME per la risposta
res.contentType("text/xml");
//Invio il codice Html al Browser
res.send(htmlNominativi);
break;
case "nominativi":
nome=req.body.nome;
lnome=nome.length;
if(lnome>0){
//Imposto il codice per visualizzare il nome scelto con l'autocompletamento
htmlNominativo="<html><head></head><body><H3>Il nome scelto è:"+nome+"</H3></body></html>";
}
//Imposto il codice per visualizzare che non è stato scelto un nome
else {
htmlNominativo="<html><head></head><body><H3>Non è stato scelto nessun nome ...</H3></body></html>";
}
//Imposto il protocollo MIME per la risposta
res.contentType("text/html");
//Invio il codice Html al Browser
res.send(htmlNominativo);
break;
}
});
//Imposta il Server node sulla porta 8090
app.listen(8090, function () {
console.log('listening on port 8090.');
});
// Restituisce un vettore con nomi ordinati
function getNominativi(){
let nominativi = ["Abelardo","Andrea","Aniello","Antonio","Antimo","Amilcare","Aida",
"Baldassarre","Beatrice","Benedetta","Benito","Berto","Bruno",
"Caio","Calimero","Calliope","Callimaco","Dafne","Dante","Danilo",
"Davide","Denis","Domenico","Emilio","Ernesto","Evaristo","Fabio",
"Francesco","Federico","Ferruccio","Giacomo","Gianni","Gianluca","Giuseppe","Giulio","Gianfranco",
"Gigi","Geronimo","Luigi","Libero","Laura","Loretta","Luca","Mario",
"Michele","Mauro","Mattia","Nicola","Nino","Nivea","Oreste","Olga",
"Olimpia","Oscar","Osvaldo","Omar","Pippo","Peppino","Pasquale",
"Patrizia","Piero","Quarto","Quirino","Roberta","Roberto","Romeo",
"Remigio","Rosanna","Raffaele","Sabina","Saverio","Silvano","Silvio",
"Simone","Sempronio","Tizio","Tiziano","Tullio","Ubaldo","Ugo","Umberto",
"Ulisse","Veronica","Vinicio","Valentina","Valentino","Virgilio",
"Vladimiro","Walter","Wanda","Wilma","Zenone","Zaccaria"];
return nominativi.sort();
}

 

Per avviare l'applicazione, procedete come indicato di seguito:

  1. portatevi nella cartella: /node/app-autocompletamento;
  2. avviate l'applicazione con il comando: node appautocompletamento;
  3. avviate il Browser;
  4. inserite l'url seguente: https://localhost:8090/app-autocompletamento/rest/scheda.html.

Arrivederci alla prossima lezione

 


<< Lezione precedente


T U T O R I A L S    S U G G E R I T I


Share Button
TOP