Condividi tramite


Il presente articolo è stato tradotto automaticamente.

Approfondimenti sul client

Utilizzo di JsRender con JavaScript e HTML

John Papa

Scaricare il codice di esempio

John PapaPiattaforme di sviluppo molti modelli utilizzano per ridurre il codice e semplificare la manutenzione e HTML5 e JavaScript non sono fa eccezione.JsRender è una libreria JavaScript che consente di definire una struttura di testo standard in una sola volta e il riutilizzo per generare codice HTML in modo dinamico.JsRender porta una nuova libreria di templating allo sviluppo di HTML5 che ha una sintassi del tag codeless e ad alte prestazioni, non ha alcuna dipendenza su jQuery né sul modello DOM (Document Object), supporta la creazione di funzioni personalizzate e utilizza il rendering basato sulla stringa puro.Questa colonna vengono illustrati scenari in cui JsRender è ideale e viene illustrato come utilizzare le sue caratteristiche diverse.Tutti gli esempi di codice che possono essere scaricati da archive.msdn.microsoft.com/mag201204ClientInsight, e JsRender può essere scaricato da bit.ly/ywSoNu.

Secondo la Boris Moore e il blog del team di jQuery UI, in aprile 2011 il team ha deciso di mettere tutti i modelli di jQuery tenere a favore della creazione di una libreria di rendering senza logica e basati su stringa.Questo portò Moore (una delle forze trainanti dietro jQuery modelli) per creare JsRender e JsViews.Queste due biblioteche sono effettivamente le sostituzioni per i modelli di jQuery.Potete leggere di più sulla storia della creazione modelli e come JsRender si è evoluto il post di Moore sui modelli di jQuery e JsRender tabella di marcia (bit.ly/AdKeDk) e post del team di jQuery (bit.ly/fhnk8A).Cliente Insight esplorerà JsRender e JsViews nei prossimi mesi.

Perché i modelli?

Utilizzo di modelli con JavaScript riduce e semplifica il codice.Senza modelli, aggiungendo una serie di elementi dell'elenco e gli altri elementi HTML di un set di dati potrebbe richiedere manipolazione del DOM del browserQuesto è dove ai modelli utilizzando un plug-in come JsRender possono essere molto utili per fare il sollevamento di carichi pesanti.Ad esempio, supponiamo che recuperare un set di film e si desidera visualizzarli.Si potrebbe scrivere JavaScript e manipolare il DOM, ma il codice seguente mostra che anche questo compito semplice può diventare difficile da leggere, anche con l'aiuto di jQuery:

// Without a template
var i = 1;
$(my.vm.movies).each(function () {
  var movie = this;
  $("#movieContainer1").append(
    "<div>" + i++ + ": " + movie.
name + " ("
    + movie.releaseYear + ")</div>");
});

Il codice è stato scritto interamente con JavaScript e jQuery, ma può essere difficile discernere l'HTML dai dati da JavaScript. Utilizza un modello, possiamo più facilmente separare la struttura ed eliminare la maggior parte del codice JavaScript. Il modello seguente (01-with-and-without-templates-with-jquery.html del download codice) illustra questo concetto:

<script id="myMovieTemplate" type="text/x-jsrender ">
  <div>{{:#index+1}}: {{:name}} ({{:releaseYear}})</div>
</script>

Notare che il modello è avvolto in un tag script, il tipo è impostare di conseguenza e ha dato un id modo può essere identificato in seguito. Un modello di rendering richiede tre aspetti: un modello, i dati e un contenitore. Il modello definisce la modalità di rendering dei dati e il contenitore dove la rendono. Il codice riportato di seguito viene illustrato come eseguire il rendering di un elenco di film utilizzando il modello denominato myMovieTemplate per un elemento con l'id del movieContainer:

$("#movieContainer").html($("#myMovieTemplate").render(my.vm.movies));

Questo esempio utilizza jQuery per semplificare la sintassi. È importante notare che il JsRender non è dipendente da jQuery. Il codice da utilizzare JsRender per eseguire il rendering dei dati utilizzando il modello potrebbe essere scritto anche come illustrato di seguito (02-jsrender-no-jquery.html nel download del codice):

my.vm = {
  movies: my.getMovies()
};
jsviews.templates({
  movieTemplate: document.getElementById("myMovieTemplate").innerHTML
});
document.getElementById("movieContainerNojQuery").innerHTML
  = jsviews.render.movieTemplate(my.vm.movies);

Modelli di rendering

Si possono eseguire il rendering di modelli utilizzando JavaScript in diversi modi. Prima ti consigliamo di definire il modello come stringa o in una <script> Tag. <script> opzione etichetta è bello quando si desidera definire i modelli nel codice HTML, dare loro un id e riutilizzarli. È inoltre possibile creare modelli da stringhe, che vi dà la possibilità di crearle al volo nel codice o anche tirare loro da un archivio dati.

Il metodo render viene utilizzato per il rendering del contenuto HTML dai dati utilizzando un modello. Un set di dati può essere resi con un modello dichiarato in un <script> etichetta usando la sintassi $("# myTmpl").render(data). Ad esempio, si potrebbe rendere un elenco di film con un modello utilizzando il seguente codice:

// #1: Render the my.vm data using the scriptTmpl from a script tag
var htmlString = $("#scriptTmpl").render(my.vm);
// Insert the htmlString into the DOM
$("#div1").html(htmlString);

Potete anche compilare un modello da una stringa utilizzando la funzione $.templates(tmplString) e impostarla su una variabile. Si può quindi il rendering del modello compilato, come illustrato di seguito:

// #2: Compile a template from a string, return a compiled template
var tmpl2 = $.templates(tmplString);
htmlString = tmpl2.render(my.vm);
$("#div2").html(htmlString);

È anche possibile compilare un modello da una stringa utilizzando la sintassi di $.templates (name, modello), come illustrato di seguito:

// #3: Compile a template, name and register it
$.templates("myTmpl3", tmplString);
var htmlString = $.render.myTmpl3(my.vm);
$("#div3").html(htmlString);

In questo esempio, la funzione .templates $ compila un modello utilizzando la stringa tmplString e registra come modello denominato. Il modello può essere letta con il nome e il rendering utilizzando il .render $. sintassi name.

La funzione .templates $ è simile a jQuery metodi come CSS, o .attrib, in quanto essa fornisce una sintassi alternativa per la registrazione e la compilazione di più modelli in una sola chiamata. Invece di passare due parametri (nome e templateString), è possibile passare solo un parametro costituito da un oggetto di mapping con coppie chiave/valore per ogni modello che deve essere registrato:

// #4: Compile multiple templates, register them and render
var tmplString2 = "<div>*** {{:movies.length}} Total Movies ***</div>";
$.templates({
  tmpl4a: tmplString,
  tmpl4b: tmplString2
});
htmlString = $.render.tmpl4a(my.vm);
htmlString += $.render.tmpl4b(my.vm);
$("#div4").html(htmlString);

Ogni proprietà nell'oggetto diventa un modello denominato e registrato che può essere sottoposto a rendering. Il valore della proprietà è la stringa che diventerà il modello.

Avete molte opzioni per creare, registrare ed eseguire il rendering di modelli. Definizione di modelli in tag script è un approccio comune per la maggior parte degli scenari. Tuttavia, la creazione di modelli da stringhe offre un sacco di flessibilità. La sintassi precedente espansa fornisce ancora più flessibilità per l'associazione di altre caratteristiche con i modelli denominati (ad esempio dichiarare le funzioni di supporto specifico per il modello). Tutti questi esempi si trovano nel rendering-03-templates.html nel download del codice.

Fondamenti di JsRender

JsRender modelli consistono di markup HTML plus JsRender tag, come ad esempio il {{per …}} tag o il {{: …}} tag. Figura 1 illustrata la sintassi per la maggior parte basic di tag JsRender: {:} e {{> Tag}}. Tutti i tag di modello JsRender avvolti con doppie parentesi graffe. Il nome del tag (in questo caso il ":" o ">" carattere) può essere seguito da uno o più parametri o espressioni. (Nel caso del tag {:}, il risultato dell'espressione sarebbe poi essere renderizzato.) Una volta che è stato definito un modello e non ci sono dati per eseguire il rendering in tale modello, può essere reso.

Figura 1 sintassi di JsRender base

Descrizione Esempio Output
Valore della proprietà firstName dell'elemento di dati con alcuna codifica {{: firstName}} Madelyn
Percorso semplice oggetto alla proprietà nidificate, con nessuna codifica {{: movie.releaseYear}} 1987
Confronto semplice {{: movie.releaseYear < 2000}} vero
Valore con alcuna codifica {{: film. Nome}} Star Wars IV: Ritorno dello Jedi
Valore codificata in formato HTML {{> film. Nome}} Star Wars: Episodio VI: < span style = "color: purple; font-style: corsivo;'> Return of the Jedi </span>
Valore codificata in formato HTML {{html:movie. Nome}} Star Wars: Episodio VI: < span style = "color: purple; font-style: corsivo;'> Return of the Jedi </span>

Il codice seguente contiene un elemento HTML denominato film­contenitore (questo è dove il modello verrà eseguito il rendering):

<div id="movieContainer" class="resultsPanel movieListItemMedium"></div>
<script id="movieTemplate" type="text/x-jsrender">
  <div class="caption">{{:name}}</div>
  <div class="caption">{{>name}}</div>
  <img src="{{:boxArt.smallUrl}}"/>
  <div class="text">Year Released: {{:releaseYear}}</div>
  <div class="text">Rating: {{:rating}}</div>
</script>

Il codice contiene anche il modello denominato film­modello, che definisce un div per visualizzare il nome del filmato non usando alcuna codifica HTML utilizzando la sintassi {{: name}}. Il titolo nei dati di esempio può contenere elementi HTML, quindi eseguire il rendering di elementi contenenti HTML è importante non fare uso di codifica. Tuttavia, se si desidera eseguire il rendering HTML codificati, è possibile utilizzare la sintassi con il > il carattere o usare HTML (come mostrato nella Figura 1).

Il valore della proprietà name contiene gli elementi HTML, così solo per scopo dimostrativo, codice precedente viene visualizzato il nome del valore della proprietà con alcuna codifica ({{: name}}) e poi mostra il valore codificata in formato HTML ({{> nome}}). In values.html-04-rendering nel download del codice, è possibile eseguire l'esempio completo.

I dati di esempio film passati al modello dispone di una proprietà per boxArt, che a sua volta ha una proprietà per la smallUrl dell'immagine. Il tag img src è impostata per immersioni nella gerarchia del grafico di un oggetto utilizzando il puntino sintassi boxArt.smallUrl. Percorsi può essere attraversato anche utilizzando le parentesi quadre, così invece di scrivere boxArt.smallUrl, lo stesso risultato codice essere raggiunto utilizzando boxArt ['smallUrl'].

È importante notare che JsRender sintassi possono essere utilizzata anche per eseguire il rendering altri valori, come ad esempio i nomi delle classi o ID per gli elementi HTML.

Rendering del modello JsRender rileva se il parametro di dati è una matrice o no. Se è una matrice, il valore restituito è la concatenazione delle stringhe che deriverebbe da ciascuno degli elementi singoli matrice passando al metodo render. Così il modello verrà eseguito il rendering una volta per ogni elemento e il risultato sarà la stringa concatenata.

Il codice riportato di seguito viene illustrato come un oggetto unico filmato dalla matrice viene eseguito il rendering per il movieTemplate (il codice sorgente completo è disponibile nel campione 04-rendering-values.html):

my.vm = { movies: getMovies() };
$("#movieContainer").html($("#movieTemplate").render(my.vm.movies[1]));

La sezione successiva dimostrerà come il modello potrebbe essere scritto per scorrere una matrice, pure.

Dati gerarchici

I modelli sono spesso utilizzati per eseguire il rendering di una serie di elementi, che spesso può contenere dati nidificati e gerarchici (oggetti grafici). Figura2 etichetta spettacoli come JsRender possibile scorrere una serie di dati utilizzando il {{di}}. Il parametro per il {{di}} tag può essere una matrice o una serie di matrici, che sarà essere iterato.

Figura 2 Iterating Basics

Descrizione Esempio Output
Scorrere in ogni elemento di una matrice, utilizzando "per"

{{per cast}}

<div> {{: Night}} </div>

{{/ per}}

Landon Papa

Ella Papa

Accedere al contesto di dati utilizzando #data {{per telefono}} <div> {{: #data}} </div> {{/ per}}

555-555-1212

555-555-1212

I dati del filmato di esempio definisce che ogni film ha una matrice di valutazione stelle chiamati RatingStars. La proprietà contiene la classe CSS per visualizzare una star rating per il film. Il seguente codice (dal 05 per data.html nel codice di esempio) viene illustrato come scorrere ogni elemento della matrice RatingStars e rendere il nome di classe CSS tramite il {{: #data}} sintassi:

<ul>
  {{for ratingStars}}
  <li class="rating {{:#data}}"/>
  {{/for}}
</ul>

Il token #data è una parola chiave JsRender che rappresenta l'oggetto sta iterato. In questo caso, la matrice RatingStars contiene una matrice di stringhe, in modo #data rappresenterà una stringa. L'output per questo esempio è mostrato in Figura 3, dove il rating stelle vengono visualizzate accanto a immagine del film.

Rendering an Object with and Without Encoding
Figura 3 Rendering di un oggetto con e senza codifica

Matrici a modelli

Quando una matrice viene passata a un modello, il modello viene eseguito il rendering una volta per ogni elemento della matrice. Esegue il rendering di un modello contro un elemento unico data, ma se include un {{di}} template tag con un parametro di matrice, poi la sezione del modello tra l'apertura e la chiusura tag {{di}} e {{/ per}} verrà ulteriormente essere iterato. Il codice seguente passa un oggetto my.vm che contiene una matrice di film per la funzione di rendering per visualizzare una voce di elenco per ogni film (il sorgente completo può essere trovata nel campione 06-se-else.html):

$("#movieList").html($("#movieTemplateMedium").render(my.vm));

Il modello verrà eseguito il rendering come contenuto di <ul> elemento con l'id movieList:

 

<ul id="movieList"></ul>

Figura 4 mostra il film modello­TemplateMedium inizia eseguendo il rendering <li>. Per ogni film nella matrice, un <li> verranno resi sotto il contenitore <ul>.

Il modello in Figura 4 riceve l'oggetto my.vm come suo contesto e poi scorre la proprietà di matrice film a causa del {{per i film}} codice. Se il modello ricevuto la matrice my.vm.movies invece di my.vm, il {{di}} {{/ per}} poteva essere rimosso il blocco, come il modello sarebbe quindi eseguire per ogni elemento della matrice.

Figura 4 un elenco di elementi di Rendering e utilizzando istruzioni condizionali

{{for movies}}
  <li class="movieListItemMedium">
  <div class="caption">{{:name}}</div>
  {{if boxArt.smallUrl}}
    <img src="{{:boxArt.smallUrl}}"/>
  {{else}}
    <img src="../images/icon-nocover.png"/>
  {{/if}}
  <br/>
  <div class="text">Year Released: {{:releaseYear}}</div>
  <div class="text">rating: {{:rating}}</div>
  <ul>
    {{for ratingStars}}
      <li class="rating {{:#data}}"/>
      {{/for}}
  </ul>
  <br/>
  <div class="text">${{:salePrice}}</div>
  {{if fullPrice !== salePrice}}
    <div class="text highlightText">PRICED TO SELL!</div>
  {{/if}}
  </li>
{{/for}}

Attraversamento dei percorsi

Come abbiamo visto in precedenza, possono essere attraversati percorsi utilizzando la sintassi del punto o le parentesi quadre. Tuttavia, potete anche risalire una gerarchia di oggetti utilizzando #parent o identificare un elemento di matrice utilizzando le parentesi quadre. Ad esempio, si potrebbe sostituire il codice che visualizza il tag img nel modello con seguente:

<img src="{{:#parent.parent.data[2].boxArt.smallUrl}}"/>

Il contesto per il modello è un elemento della matrice my.vm.movies. Così navigando su due volte attraverso il genitore, il contesto diventerà l'oggetto my.vm. Poi si può afferrare il film con indice 2 e utilizzare la proprietà boxArt.smallUrl per l'immagine. Il risultato di questo sarebbe da visualizzare lo stesso film (il terzo film) per ogni film nella matrice (come mostrato nella Figura 5). Non esattamente ideale in questa situazione, ma serve al punto di mostrando come attraversare oggetti su e giù per la gerarchia.

Traversing Paths to Display the Same Movie Image for Every Movie
Figura 5 attraversamento percorsi per visualizzare la stessa immagine di film per ogni film

Istruzioni condizionali

La sintassi JsRender supportano anche condizionali utilizzando il tag {{if}} e {{altro}} (mostrato in Figura 6). Il {{if}} tag può essere seguita da zero, uno o più tag {{altro}} e poi una chiusura {{/ se}} tag. Il contenuto del blocco tra {{if}} tag e il {{/ se}} (o fino al primo tag {{altro}} se ne esiste uno) verrà eseguito il rendering nell'output solo se il valore dell'espressione nella {{if}} è "truthy".

Figura 6 istruzioni condizionali, espressioni e operatori

Descrizione Esempio Output
Creazione di un if blocco valutata su un confronto

{{Se fullPrice! = = salePrice}}

< div class = "testo highlightText" >

Un prezzo per vendere! </div>

{{/ Se}}

UN PREZZO DI VENDITA!
Un blocco if/else

{{Se qtyInStock > = 10}}

In Stock

{{altro qtyInStock}}

Solo {{: qtyInStock}} sinistra!

{{altro}}

Non disponibile.

{{/ Se}}

Solo 5 a sinistra!

Il tag {{altro}} può agire come un ifelse quando esso include un'espressione della propria. Si noti il secondo esempio nella Figura 6, che dimostra un'istruzione condizionale con due altro tag. Questo codice consente di valutare tre condizioni in sequenza.

Il blocco che segue un tag {{someCondition altro}} sarà uscita se la condizione restituisce true (o, più precisamente, truthy). Questa sintassi può essere efficacemente utilizzata come un'istruzione switch/case per valutare il numero n di condizioni.

Le espressioni nei tag JsRender può essere espressioni complesse utilizzando gli operatori tra cui percorsi, stringhe, numeri, funzionano chiamate e gli operatori di confronto, come valutazione = = =,! = = e < =. Questo è il caso, sia per le espressioni valutate e resi dal tag {:} e, qui, per le espressioni condizionali utilizzate nella {{if}} e {{altra}} tag.

Utilizzando i contatori e le espressioni condizionali complesse

A volte è necessario visualizzare o utilizzare una variabile contatore in un modello. Un tale scenario è quando si desidera visualizzare un numero di riga nel modello. Un altro tale scenario potrebbe essere che si desidera assegnare un id univoco a ogni elemento in un modello in modo potete riferirli più tardi. Ad esempio, scorrere un elenco di film e li avvolgono tutto all'interno di un <div> Tag. È possibile assegnare l'id del tag div per essere movieDiv1, movieDiv2 e così via. Allora si potrebbe trovare l'elemento ID quando necessario, forse per associarlo a un gestore eventi utilizzando la funzione di delegato di jQuery. Per entrambi questi scenari, è possibile utilizzare la JsRender parola chiave #index (che inizia a 0). Come illustrato nella Figura 7, #index possono essere visualizzati in un modello abbastanza facilmente.

Figura 7 contatori e condizionali in più espressioni

Descrizione Esempio Output
Utilizzando un indice a contare all'interno di un modello

{{per i film}}

< div class = "didascalia" >

{{: #index}}: {{: name}}

</div>

{{/ per}}

3: La principessa sposa
Utilizzando gli operatori logici

{{Se stars.length | | cast.length}}

< div class = "text" > Cast completo: </div>

{{/ Se}}

Cast completo:

Spesso una sola espressione non può essere sufficiente. JsRender supporta più espressioni utilizzando operatori logici quali | | e & & ("o" e "e" rispettivamente). Ciò rende più semplice combinare più espressioni quando si desidera valutare uno di loro per essere vero.

Iterare matrici Multiple insieme

Il {{di}} tag può anche scorrere più matrici in una sola volta. Questo è utile quando sono presenti due matrici che hanno bisogno di essere attraversato insieme. Ad esempio, il codice seguente illustra come il per etichetta eseguirà un'iterazione sia attraverso le stelle e le matrici Cast insieme:

{{for stars cast}}
  <div class="text">{{:name}}</div>
{{/for}}

Se ci sono due elementi della matrice di stelle e tre nella matrice Cast, contenuto in tutti i cinque elementi verrà eseguito il rendering.

Questa è una buona situazione di usare la parola #data chiave, anche, se gli elementi nelle matrici non sono oggetti (con proprietà), ma i valori stringa semplice. Ad esempio, le matrici potrebbero essere matrici di stringhe di cellulari e HomePhones, e si potrebbe desiderare di elencarli in un unico elenco.

Modelli nidificati

Le applicazioni spesso recuperare oggetti grafici, dove gli oggetti hanno proprietà i cui valori sono matrici di oggetti che possono contenere anche altre matrici di oggetti. Questi scenari possono diventare rapidamente difficili da gestire quando multiple {{di}} dichiarazioni di nidificazione. Si consideri che un oggetto customer possa avere ordini, che hanno gli elementi di ordine, che hanno un prodotto, che sono i magazzini. Questo dati gerarchici potrebbero essere resa utilizzando multiple {{di}} tag. Questa è una situazione di grande dove il contenuto di un {{di}} blocco può essere confezionato come un modello separato e il rendering come modello nidificato. Ciò può ridurre il codice e renderlo più facilmente leggibile e mantenibile e fornire per il riutilizzo e la modularità dei modelli.

È possibile utilizzare un modello nidificato con un {{di}} tag rimuovendo il contenuto di blocco (rendendola chiusura) e specificando un modello esterno utilizzando il parametro tmpl. Ad esempio, è possibile impostare il parametro tmpl sia il nome di un modello denominato (registrato utilizzando $.templates), oppure è possibile utilizzare un selettore di jQuery per un modello dichiarato in un blocco di script. La sintassi seguente utilizza il modello denominato myTmpl per ogni elemento della matrice denominato myArray:

{{for myArray tmpl="myTmpl"/}}

Il seguente frammento di codice utilizzeranno il modello con l'id del movieTemplateMedium per ogni elemento della matrice di filmati (dal campione 04-tmpl-combinata-iterators.html):

<ul>
  {{for movies
    tmpl="#movieTemplateMedium"/}}
</ul>

Puoi scorrere le matrici multiple e applicare un modello a loro, pure. Ad esempio, il seguente frammento di codice utilizzerà il castTemplate per ogni elemento in stelle e Cast proprietà (che sono entrambi matrici da campione 07-tmpl-combinata-iterators.html):

<ul>
  {{for stars cast tmpl="#castTemplate"/}}
</ul>

Si noti che in ciascuna delle precedenti frammenti di codice il {{di}} tag è un tag di chiusura automatica anziché un tag di blocco che contiene il contenuto. Invece di iterare sul suo contenuto blocco, esso è differire l'iterazione al modello nidificato indicato dalla proprietà tmpl e il rendering di quel modello una volta per ogni elemento della matrice.

Il {{if}} template tag può essere utilizzato anche come un tag di chiusura automatica che fa riferimento a un altro modello per il suo contenuto, proprio come il {{di}} tag. Ad esempio, il codice seguente renderebbe il modello denominato myAddressTmpl se l'indirizzo è truthy:

{{if address tmpl="myAddressTmpl"/}}

I campioni disponibili per il download di dimostrare tutte le caratteristiche descritte in questo articolo. Figura 8 mostra la lista dei film il rendering utilizzando tutte queste caratteristiche dal campione 07-tmpl -­file iterators.html combinata.

Putting It All Together
Figura 8 mettere tutto insieme

Più sotto le coperte

Questa colonna vengono illustrate le funzionalità di base di JsRender, ma c'è molto più sotto le coperte. Ad esempio, anche se il tag condizionali può contenere più {{di}} tag con condizioni (ad esempio un'istruzione switch/case), ci potrebbe essere più puliti modi per gestire questa situazione, come l'utilizzo di tag personalizzati. JsRender supporta tag personalizzati per logica complessa, funzioni di supporto, navigare fino l'oggetto grafico utilizzando percorsi, funzioni di convertitore customer, consentendo il codice JavaScript all'interno di modelli, l'incapsulamento dei modelli e molto altro. Sarà a scoprire alcune di queste tecniche nel prossimo numero.

John Papa è un ex evangelist di Microsoft su Silverlight e Windows 8 squadre, dove ha ospitato il popolare show televisivo di Silverlight. Egli ha presentato a livello globale al keynote e sessioni per costruire, MIX, PDC, TechEd, Visual Studio Live! ed eventi DevConnections. Papa è anche Microsoft Regional Director, un editorialista forVisual Studio Magazine (di Papa Perspective) e autore di video di formazione con Pluralsight. Seguirlo su Twitter a twitter.com/john_papa.

Grazie all'esperto tecnica seguente per la revisione di questo articolo: Boris Moore