Forti scossoni fanno rinvenire i due eroi. Si ritrovano imbavagliati e legati all’interno di un carro che si sta muovendo con velocità e in maniera spericolata.
Liberati dagli impedimenti a malapena riescono a stare in piedi all’interno del carro con le teste ancora confuse di cosa fosse successo. Attraverso le sbarre posteriori del carro intravedono verdi colline e boscaglia sparsa ma non riescono a capire assolutamente dove si trovino.
Ad un tratto delle urla provenienti dal fronte del carro vengono seguite da dei violenti sobbalzi e il nitrire impazzito de cavalli non promette nulla di buono.
Con un ben assestato calcione i due sfondano la porta del carro e riescono a sollevarsi sul traballante tettuccio e assistono ad uno spettacolo terrificante: dinnanzi a loro un intero villaggio viene messo a ferro e fuoco.
Colonne di fumo nero si elevano fino al cielo e i cittadini in preda al panico urlano e fuggono ogni dove. La battaglia è intensa e sanguinosa e gli invasori non sempre sono interessati a fare prigionieri. Il clangore delle armi è risuona costante come un fabbro nella sua fucina.
I due eroi assistono attoniti a tale spettacolo e non si accorgono di una gigantesca ombra alle loro spalle che incombe su di loro dall’alto: un enorme drago dalle sfumature azzurre con i suoi potenti battiti di ali travolge e scaraventa in mille pezzi la carrozza.
I due giovani riescono a malapena a resistere all’urto della caduta ma sono costretti a recuperare in fretta e furia il loro equipaggiamento ed allontanarsi dal campo aperto.
Raggiungono le soglie del villaggio e si imbattono in una famiglia che è inseguita da un drappello di coboldi. Quindi con le armi sfoderate riescono a mettere al sicuro almeno la madre e la figlia.
I sopravvissuti che incontrano, tutti paesani in preda al terrore e feriti gravemente, sono di poco aiuto per chiarire la situazione e i due sfruttando il caos della battaglia e le fiamme che avvolgono il villaggio decidono di raggiungere la fortezza centrale e trovare soccorso.
Il fumo, il clangore delle armi e le urla coprono bene i loro movimenti ma per evitare numerose pattuglie di razziatori sono costretti a piombare improvvisamente in un edificio e a trovarsi di fronte un gruppo di misteriosi cultisti.
Nella piccola stanza c’è poco spazio di manovra e i nemici cadono non senza lasciare il segno: infatti i misteriosi uomini incappucciati padroneggiano sia le armi che la magia e riescono a ferire gravemente il paladino avvolgendolo per un momento nelle fiamme.
Il ranger, si trova costretto ad invocare il potere dei suoi antenati draghi e uccidere i cultisti in una nube tossica di veleno.
L’assedio al villaggio ha raggiunto il culmine e l’esercito invasore sembra aver preso il sopravvento di tutto ma non della fortezza che fortunatamente resiste ancora agli attacchi.
I due eroi, pur feriti, riescono a sfuggire alle frecce degli assassini e vengono accolti e soccorsi nella fortezza dal Lord e i suoi fedeli sudditi.
Il reggente del luogo è un vecchio nano di nome Tarbaw Nighthill che è riuscito a raccimolare una buona fortuna come commerciante e poi comprandosi titoli nobiliari. E’ felice di accogliere i due nuovi arrivati vendendo che loro abilità in combattimento sono superiori alla media e offre subito delle ricompense in cambio di protezione dall’assedio.
La fortezza di presenta come una larga torre a 4 piani alti 5 o 6 metri l’uno con spesse mura in muratura. Gli alloggi dei soldati a pian terreno sono stati trasformati in infermerie alla buona dove i monaci e chierici possono soccorre i popolani sfuggiti all’assalto. Al primo piano la sala da pranzo è stata risistemata come sala tattica da dove controllare l’avanzamento della battaglia e coordinare la distribuzione delle truppe per sostenere il minor numero di perdite.
Ci sono segnati sulla mappa alcuni punti cruciali che devono essere assolutamente controllati per permettere al villaggio di sopravvivere all’assalto: i magazzini delle scorte, il tempio dove parte della popolazione si è rifugiata e il mulino con granaio.
Le scorte di cibo e altre risorse è l’obiettivo primario ma il Lord non può offrire truppe di supporto nell’immediato e inoltre un piccolo gruppo di uomini esperti potrebbe avvicinarsi e sgomberare l’area molto più facilmente di uno numeroso.
Uscire dalla fortezza dall’entrata principale sarebbe un probabile suicidio e il Lord propone di sfruttare un antico passaggio sotterraneo costruito come principalmente come fogna della fortezza ma poi abbandonato e usato anche come deposito.
Si unisce al gruppo un giovane monaco Leosin Erlanthar che sembra interessato ad approfondire i motivi dell’assalto e spera di poter catturare e interrogare uno dei cultisti umani.
Il tunnel come previsto si presenta umide e buio e ormai popolato da ratti e insetti. I ratti in particolare si rivelano particolarmente aggressivi e spaventati visti i rumori della battaglia in superficie e le fiamme che divampano nel villaggio e assaltano il gruppo che si ritrova quindi nel piccolo spazio a liberarsi di queste creature.
Le inferriate in fondo al tunnel non sono un ostacolo vista la ruggine ma poi i gruppo deve sbarazzarsi velocemente di tutte le guardie di razziatori di pattuglia nella zona, altrimenti il piano di muoversi silenziosamente tra le file nemiche si complicherebbe notevolmente.

Prima di continuare l’avventura il druido si dice costretto ad abbandonare il gruppo per tornare nella foresta. Durante gli attimi di riposo infatti ha avvertito misteriose energie scuotere la calma della foresta e ritiene necessario dover indagare l’accaduto.
Una volta ringraziato il druido per la guida i tre giovani avventurieri si inoltrano nei cunicoli della caverna.
Le fiaccole appese ormai quasi consumate riescono a malapena ad illuminare il pavimento che però diventa sempre più curato e liscio. Le pareti rocciose sono ruvide e taglienti lasciano il posto ad una muratura ben fatta e solida anche se la costante umidità a fato crescere rigogliosi muschi e radici lungo gli spazi delle pietre intagliate.
Il corridoio lascia finalmente spazio ad ampio salone dal soffitto che quasi si perde nell’oscurità.
Delle enormi colonne cinte di fiaccole ne illuminano la base e creano numerosi giochi di ombre danzanti tutt’intorno.
Il coboldo fuggito al precedente assalto è andato ad allertare le guardie e si sentono echi sopraggiungere di voci e suoni metallici che sbattono.
Subito il gruppo si fionda nella piccola stanza alla sua sinistra per sfuggire agli abitanti della caverna che si stanno organizzando per pattugliare la caverna.
Nella stanzetta dove si ritrovano c’è un enorme pagliericcio con una piccola recinzione e una ciotola con scritto “Bob”.
Nonostante il fetore di cibo avariato ed escrementi il ranger e la piccola maga trovano il coraggio di nascondersi nel pagliericcio, mentre il paladino chiaramente impossibilitato visto lo scintillante equipaggiamento prova a fingersi una guardia cercando di nascondere la preoccupazione agli imminenti cercatori.
Dopo pochi secondi infatti entrano un paio di guardie e rimangono quasi spiazzate di trovarsi di fronte un uomo in armatura fiero e immobile proprio come se fosse una delle guardie addette alla sorveglianza.
Quell’attimo però è sufficiente per far scattare l’imboscata e con balzo il ranger sfodera le spade mentre il paladino sferra colpi di martello.
Per le guardie non c’è scampo e soccombono velocemente ma il frastuono attira la pattuglia nella sala centrale e il gruppo si prepara all’assalto diretto.
Con una carica a testa bassa il paladino si scaglia contro la prima guardia mentre dalle retrovie piovono frecce e dardi di fuoco.
Sembrano avere la meglio ma i nuovi rinforzi sopraggiunti costringono il gruppo a separarsi per difendersi e la povera maga, rimasta a corto di energia, viene catturata e portata via.
Il ranger e il paladino riescono a sopraffare le guardie e mettere in fuga il resto dei coboldi sopravvissuti ma scoprono troppo tardi la cattura della maga e si mettono in cerca di indizi di dove l’hanno portata.
Con cautela i due giovani decidono di proseguire il cammino imboccando un corridoio ben illuminato e adornato di tappeti.
Il silenzio dell’atmosfera è quasi surreale, i soffici tappeti attutiscono benissimo i passi degli eroi e le fiamme delle fiaccole sembrano bruciare quasi immobili.
La tensione degli avventurieri è talmente alta che quasi non si accorgono in incappare in una trappola nel pavimento: alcune pietre sono instabili ma nascoste sotto il tappeto e pronte a far cadere i malcapitati in una fossa profonda.
Proprio quando i loro piedi stanno per cadere in fallo, lontano nel corridoio si apre un portale sulla parete e si vede sbucare il vecchietto bisbetico che sta continuando la ricerca del suo libro.
L’apertura del portale fa scuotere il corridoio e scattare anticipatamente la trappola rivelando ai due giovani il pericolo imminente e quindi riesco con un bel balzo a superare l’ostacolo.
Prima che possano raggiungere il vecchio e chiedere spiegazioni di quale libro si tratta e come fa a conoscere e manipolare incantesimi così potenti, questo attraversa velocemente un altro portale verso delle lande verdeggianti e scompare senza lasciare tracce.
I due si guardano perplessi ma decidono di proseguire e non pensarci più di tanto ma fatti pochi passi si trovano davanti ad un’altra insolita situazione: il corridoio cosparso di fiaccole e ben illuminato termina in una stanza completamente oscura e la luce sembra essere divorata da questa innaturale oscurità.
Una torcia lanciata all’interno non riesce ad illuminare nulla se non la mattonella dove è caduta ma questo non intimorisce il paladino che si appresta a concentrarsi ed incalanare energia: la sua visione della sua mente si espande e riesce a vedere una creatura esile e oblunga.
Il ranger segue con qualche timore il paladino che non invece non si lascia per nulla intimorire dall’oscurità e i due si lasciano avvolgere la buio più completo.
In pochi istanti vengono toccati e strattonati diverse volte; cercano di reagire ma le loro armi sono vane contro l’oscurità.
Il buio li avvolge definitivamente e perdono i sensi.

Le campane della cattedrale risuonano gioiose in festa.
Dopo le ultime piogge intense finalmente il cielo è sereno e le temperature cominciano a scaldarsi.
La città è tutta in fermento per il giorno della promozione dei cadetti paladini.
Il duro addestramento durato numerosi anni sta finalmente per giungere al termine e i più meritevoli allievi dell’ordine della Sacra Fiamma vengono proclamati di fronte a tutta la popolazione.
L’emozione è palpabile e la gente si accalca per applaudire i suoi futuri eroi.
Ogni anziano paladino presenta il suo discepolo sul palco montato per l’occasione nella piazza centrale e gli offre le vestigia e i decori del primo rango.
Tutti i neo promossi, a cerimonia terminata, ricevono poi dal proprio mentore un ultimo compito personale da portare a termine e così Tormund riceve l’incarico di entrare nella Foresta dei Sussurri e comprendere i segreti della sacra pergamena che dovrà portare con se.
Il giovane paladino è eccitatissimo e non vede l’ora di intraprendere l’avventura e si precipita a raccogliere le sue cose.
Uscendo dalla città si imbatte in suo vecchio amico ranger al quale racconta il felice evento e lo invita a partecipare alla nuova avventura.
L’amico di numerose scampate ma simpatiche disavventure è all’inizio dubbioso perchè conosce anche solo alcuni dei pericoli della foresta e dei suoi sentieri che più volte a battuto ma accetta comunque di accompagnarlo e mostrargli la via.
La Foresta dei Sussurri è un fitto bosco che si estende per numerosi ettari, i cui alberi sono così da oscurare quasi del tutto la luce del sole.
Una volta addentrati nel cuore della foresta i due giovani avventurieri si imbattono in uno strano abitante della foresta, un druido, che li accoglie amichevolmente nonostante lo stupore di vedere dei viandanti dal quelle parti.
Si presenta come un druido custode della foresta e dei suoi segreti e decide di unirsi al gruppo per capire meglio le loro intenzioni e il vero motivo della loro presenza in quel posto.
Proprio quando la tensione si stava rilassando viste le ore di cammino nelle profondità della foresta e la tranquillità del paesaggio, ciò che prima sembrava a prima vista semplice rugiada e umidità del sottobosco, lentamente si trasforma in una nebbiolina densa e bassa quasi ad impedire dove mettere i piedi.
Le chiome degli alberi sembrano incurvarsi per oscurare i raggi del sole quasi del tutto e i variopinti colori di funghi e fiori diventano sempre più spenti quasi a lasciare posto ad un colore piatto dalle sfumature bluastre.
Si sentono di tanto in tanto delle voci, sottili e distanti ma come se parlassero tutte intorno e la tensione dei tre eroi diventa palpabile.
Cominciano a camminare molto più guardinghi, mano sull’elsa e freccia in corda, pronti a scattare al primo sentore di pericolo.
In una piccola radura, si imbattono un figura di eterea di una bambina, che seduta su una roccia gioca con il suo vestitino e una piccola bambola.
Ad un certo punto sembra notare gli sguardi attoniti e un po’ impauriti su di lei e si rivolge ai viandanti con una voce delicata e gioiosa dicendo “volete giocare con me?” e sorridendo e saltellando si inoltra nella foresta.
Un bagliore intorno sembra quasi illuminarla mentre si allontana dal gruppo e ombre vengono proiettate danzanti sui tronchi.
I tre avventurieri prendono coraggio e decidono di seguirla.
Tormund con in un attimo di concentrazione apre gli occhi e una piccola fiammella azzurra esce dai suoi occhi.
Nella sua mente tutto intorno a se diventa chiaro e nitido e la realtà tutto intorno a se si deforma e piega lo spazio al suo volere: è in grado di vedere lontano e vicino allo stesso tempo, avvertire le presenze intorno a se e percepire le energie magiche che li circondano.
Flussi di potere come folate di vento avvolgono e attraversano la foresta, ma nulla che indichi malefici o incantesimi pronti a scattare.
Il paladino tornato in se rassicura il gruppo e procede dove lo spirito li aveva invitati.
La bambina si gira più volte, incalzandoli a tenere il passo e li guida fino all’ingresso di una caverna ma una volta arrivata, quasi sorpresa o spaventata da qualcosa ne fugge all’interno.
Il ranger silenziosamente ispeziona i dintorni della grotta e nota poco a lato altre due sagome questa volta adulte che distrattamente parlano tra loro di come la loro bambina non obbedisca mai e faccia sempre come vuole.
Come se l’accaduto avesse del tutto spezzato la tensione, i tre si addentrano nella caverna con un nuovo e rinvigorato coraggio.
La luce pallida della foresta illumina malamente l’antro, ma funghi e muschi fluorescenti permettono comunque una certa visibilità.
C’è molta umidità e
Si avvicinano ad uno specchio d’acqua sotterraneo e notano che su un piccolo scoglio che affiora c’è uno strano oggetto che riflette la fioca luce.
Tormund si sveste e si tuffa nelle scure acque per raggiungere la roccia affiorante e mentre raccoglie il misterioso oggetto dall’acqua emergono dei giganteschi granchi destati dal loro sonno.
Con rapidità fulminea li ranger scocca frecce per proteggere la ritirata del paladino che si rituffa in acqua, mentre il druido con il suo bastone cerca di tenere lontani altri due granchi che si erano avvicinati.
Lo scontro è breve ma comunque rischioso data la sorpresa dell’assalto ma i tre granchi vengono uccisi a colpi di giavellotto e spade.
L’oggetto raccolto si rivela essere un pezzo di runa ma purtroppo troppo piccolo per poterne decifrare il significato, quindi messo da parte nello zaino i tre eroi continuano ad addentrarsi nella caverna.
Proprio all’imbocco di lungo corridoio naturale incontrano uno strano vecchietto bisbetico che dichiara di essere alla ricerca del suo libro.
Nonostante l’offerta di aiuto però si rifiuta di dare altre spiegazioni e continua il suo girovagare per la caverna fino a scomparire nell’oscurità.
Con gli sguardi perplessi riprendono il cammino nel corridoio e oltre alla nuda roccia naturale cominciano ad apparire delle modeste e improvvisate impalcature di sostegno e qualche fiaccola per illuminare il cammino.
Ad un certo punto si sentono degli strani versi di grugniti e stridii e il gruppo si imbatte in un piccolo drappello di Coboldi che intorno al fuoco danzano e si spingono tra di loro.
Stanno evidentemente festeggiando la cattura di un piccolo halfling imprigionato in una gabbia.
L’attacco è veloce, Tormund trafigge con un giavellotto inaspettato uno dei coboldi e una freccia ne colpisce alla testa un altro.
Quelli che rimangono vengono reagiscono ma come se venissero distratti costantemente da una voce nella testa.
Alla fine vengono eliminati ma uno di loro riesce a fuggire tra le frecce che saettano e quindi gli eroi sono costretti e liberare velocemente il malcapitato e preparasi ad una seconda ondata.
L’halfling si presenta in stracci e con qualche segno di percossa; rivela di essere una maga e mostrando uno strano cubo racconta che era alla ricerca di questo suo oggetto sottrattole proprio da alcuni Coboldi ma le sue energie non sono state sufficienti ed era stata sopraffatta.

Supponiamo di voler realizzare un widget per la ricerca che sia composto da un campo di testo con validazione e un bottone. L’utente dovrà avere la possibilità di inserire del testo ma questo non deve contenere alcun numero all’interno.

Gli elementi HTML di cui avremo bisogno saranno un input per inserire il testo, un button per eseguire il controllo sui numeri e uno spazio che dovrà essere di default invisibile da dedicare ai messaggi di avviso.

Cominciamo quindi a mettere i tre elementi dentro un div contenitore per tenerli raggruppati e poter piazzare il nostro widget ovunque all’interno della pagina senza perderne il controllo.

<div class="search-widget">
  <input type="text"/>
  <button>Check</button>
</div>

Per quanto riguarda il JavaScript definiamo una classe che SearchComponent che accetti in input il dom del nostro widget e definisca quindi i comportamenti agli elementi interni.

function SearchComponent (widgetDom) {
  var input = widgetDom.querySelector("input"),
      button = widgetDom.querySelector("button");
  button.onclick = function () {};
  input.onkeypress = function () {};
}

Al click del bottone usiamo una semplice regex per controllare se ci sono presenti numeri all’interno del testo inserito e nel caso aggiungere una classe CSS al widget per gestire l’errore.

function SearchComponent (widgetDom) {
  var errorClass = " error", // we have to use some space to concat CSS classes
      input = widgetDom.querySelector("input"),
      button = widgetDom.querySelector("button");
  button.onclick = function () {
    widgetDom.className = widgetDom.className.replace(errorClass); // remove previous validation
    if (input.value.match(/[0-9]/)) {
      widgetDom.className += errorClass;
    }
  };
  input.onkeypress = fucntion () {};
}

Aggiungiamo anche un controllo sul campo di testo nel caso in cui l’utente voglia premere invio anzichè usare il bottone. In questo caso possiamo sfruttare la definizione dell’evento sul bottone per invocarlo senza riscriverlo. Ciò ci permette facilmente di gestire la validazione in un unico punto soltanto.

function WidgetSearch (widgetDom) {
  var errorClass = "error", // setting up some default classes for validation
      successClass = "success",
      input = widgetDom.querySelector("input"), // find elements inside the current widget
      button = widgetDom.querySelector("button");
  button.onclick = function () {
    widgetDom.className = widgetDom.className.replace(errorClass, "").replace(successClass, ""); // remove previous validation classes
    if (input.value.length === 0) {
      return; // don't perform validation if there is no text to validate
    }
    if (input.value.match(/[0-9]/)) { // regex validation
      widgetDom.className += " " + errorClass; // add a css class to handle error
    } else {
      widgetDom.className += " " + successClass;
    }
  };
  input.onkeypress = function (event) {
    if (event.keyCode === 13) { // 13 is the key code for return button
      var click = new Event("click"); // define the click event programmatically
      button.dispatchEvent(click) // fire the event on the button simulating the user click
    }
  }
}

Le funzionalità del nostro widget sono ora pronte e rimane da gestire la messaggistica della validazione.

<div class="widget-search">
  <div class="input">
    <input type="text"/>
    <button>Check</button>
  </div>
  <div class="message">
    <div class="message-error">There are numbers in the text.</div>
    <div class="message-success">The text is clear.</div>
  </div>
</div>

Impacchettando gli elementi HTML possiamo meglio gestirne gli stili usando dei selettori CSS parlanti.

Definiamo un set di regole semplici per avere una base di grafica che possa rispecchiare le specifiche dell’esercizio.

Mettiamo il campo di testo e il bottone allineati uno vicino all’altro e i messaggi sotto.

.input * {margin-right: -5px;}  // stick the inputs together
.input input {border-radius: 10px 0 0 10px;}  // add some cool style
.input button {border-radius: 0 10px 10px 0;}
.message * {display: none;}  // the messages
.message-error {color: red;}
.message-success {color: green;}
.error .message-error {display: block;} // show relative message to validation result
.success .message-success {display: block;}

Il nostro widget è finalmente completato nella sua struttura. Per poterlo usare nella nostra applicazione ora dobbiamo solo invocarlo al caricamento della pagina istanziando un nuovo widget di tipo WidgetSearch.

window.onload = function () {
  var widget = document.querySelector(".widget-search");
  new WidgetSearch(widget)
}

Ci sono ora un paio di regole che devono essere tenute a mente usando un componente così definito con CSS e JavaScript.

Gli stili che abbiamo creato potrebbero essere troppo generici all’interno della nostra applicazione, quindi il consiglio è quello di usare, per tutto ciò che non vogliamo sia condiviso con altri elementi HTML in pagina, una root riferita al contenitore per limitare il più possibile overrides.

.widget-search .input * {margin-right: -5px;}
.widget-search .input input {border-radius: 10px 0 0 10px;}
.widget-search .input button {border-radius: 0 10px 10px 0;}
.widget-search .message * {display: none;}
.widget-search .message-error {color: red;}
.widget-search .message-success {color: green;}
.widget-search .error .message-error {display: block;}
.widget-search .success .message-success {display: block;}

Inoltre se volessimo usare più volte nella stessa pagina questo componente dobbiamo tenere presente che va istanziato un nuovo WidgetSarch per ogni elemento. Quindi dovremo aggiungere un ciclo per scorrere tutti i widget in pagina e inizializzarli.

window.onload = function () {
  var widgets = document.querySelectorAll(".widget-search");
  widgets.forEach(function(widget) {
    new WidgetSearch(widget)
  })
}

Infine potremmo creare un sistema automatizzato di inizializzazione di tutti i possibili widget in pagina passando per i data attribute.

Aggiungiamo un data-widget al nostro componente in modo da passargli il valore della classe JavaScript da istanziare e cambiamo il ciclo dentro window.onload per leggere tutti i data-widget in pagina.

<div class="widget-search" data-widget="WigetSearch">
  ...
</div>

window.onload = function () {
  var widgets = document.querySelectorAll("[data-widget]");  // get all elements with that data attribute
  widgets.forEach(function (widget) {
    var className = widget.dataset.widget;  // read the data attribute value
    new window[className](widget);  // get the class from the container of all of them, from window if it's defined at global level, otherwhise other variables
  })
}

In JavaScript qualunque oggetto ha una struttura che lo definisce con proprietà e metodi nativi che non possiamo ne sovrascrivere ne modificare. Sebbene i valori nativi siano disponibili in sola lettura, possiamo aggiungerne di nuovi e manipolarli a piacimento.

Vediamo ora come applicare questo alla programmazione ad oggetti e scoprire quali vantaggi può offrirci.

Definiamo una semplice classe Person che costruiremo man mano ampliandone il suo prototype.

function Person () {};

Person.prototype // {constructor: function(){...}, ...}

Il suo prototype nativo conterrà solo il metodo constructor che viene invocato quando generiamo una nuova istanza e va ad eseguire il codice della classe stessa, e altri metodi ereditati dalla super classe Object.

Aggiungiamo due nuovi metodi per scrivere e leggere il nome della persona

Person.prototype.setName = function (value) { this.name = value };
Person.prototype.getName = function () { this.name = value };

var p = new Person();
p.setName("John");
p.getName(); // "John"

I metodi appena definiti sono diventati nativi per la funzione Person e quindi disponibili alle sue istanze e a ciascuna di queste andranno a rispettivamente a creare e leggere la proprietà name.

Possiamo migliorare l’efficienza di questi due metodi fondendoli in uno solo.

Person.prototype.name = function (value) {
  if (value) {
    this._name = value
  } else {
    return this._name
  }
}

In questa maniera ora avremo un solo metodo name al quale se passiamo un parametro setterà la proprietà altrimenti la leggerà.

var p = new Person();
p.name("John");
p.name(); // "John"

Importante. Abbiamo dovuto però rinominare this.name in this._name per evitare di fare confusione tra metodo e proprietà, altrimenti, una volta invocato il metodo name con un parametro in input andiamo a ridefinire cosa sia name stesso, trasformandolo in un valore e quindi non potendolo più usare successivamente come funzione, ottenendo in console un errore come il seguente.

var p = new Person();
p.name("John");
p.name(); // "Uncaught TypeError: p.name is not a function(…)"
p.name; // "John"
p.name("Smith"); // "Uncaught TypeError: p.name is not a function(…)"
p.name = "Smith";
p.name; // "Smith"

I vantaggi di aggiungere metodi al prototype di una function riguardano soprattutto l’aspetto computazione e occupazione di risorse di memoria. Infatti questi metodi, visti allo stesso livello di quelli nativi, vengono allocati una sola volta e associati ad ogni istanza successiva pur mantenendo il contesto indipendente l’una dall’altra.

In altre parole non viene allocato uno spazio di memoria per ogni metodo name di ogni eventuale var p1, p2, …, ma ne viene allocato uno solo al momento della definizione di Person e poi ereditato dalle istanze e su grandi numeri sia di metodi che di istanze è sicuramente da tenere a conto per le performance.

D’altro canto però per scambiare informazioni tra due metodi diversi o uno con condizioni all’interno come l’esempio precedente di name, dobbiamo per forza definire delle variabili di classe con il rischio innanzitutto di name overriding e in secondo luogo di rendere visibili delle proprietà che preferiremmo rimanessero nascoste all’utente.

Nell’esempio precedente infatti abbiamo voluto mettere a disposizione dell’utente un semplice metodo per manipolare la proprietà name ma per fare ciò abbiamo dovuto creare una proprietà _name di supporto per salvare e leggere il valore, rendendo a questo punto superfluo il metodo stesso.

Per situazioni del genere sicuramente una soluzione migliore potrebbe essere quella di definire all’interno della funzione Person stessa metodi e variabili di supporto nascoste, a patto di accettare un uso maggiore di memoria.

function Person () {
  var name;
  this.name = function (value) {
    if (value) name = value;
    else return name;
  }
}

var p = new Person();
p.name("John");
p.name(); // "John"
p.name; // function ...

 

 

La programmazione ad oggetti ci offre la possibilità di definire un set di classi “base” da estendere di volta in volta per creare oggetti più complessi senza dover riscrivere ogni volta l’inizializzazione di proprietà condivise.

Riprendiamo le classi di esempio definite nell’articolo Programmazione ad oggetti con Function – Introduzione.

function Employee (params) {
  var params = params || {};
  this.id = params.id;
  this.name = params.name;
  this.company = params.company;
  this.role = params.role;
  this.manager = params.manager;
}
function Manager (params) {
  var params = params || {};
  this.id = params.id;
  this.name = params.name;
  this.company = params.company;
  this.employees = params.employees;
  this.project = params.project;
}

Nelle due classe così definite ci sono delle inizializzazioni che abbiamo dovuto riscrivere ma avremmo potuto evitare. Per questo motivo creiamo ora la classe Person che poi estenderemo all’interno di Employee e Manager.

function Person (params) {
  var params = params || {};
  this.id = params.id;
  this.name = params.name;
  this.company = params.company;
}

Per estendere questa classe per esempio dentro Employee potremo istanziare una variabile Person al suo interno, aggiungerci altre proprietà e metodi, infine ritornare l’istanza così estesa.

function Employee (params) {
  var params = params || {};
  var person = new Person(params);
  person.role = params.role;
  person.manager = params.manager;
  return person;
}

In questa maniera però pur ottenendo all’atto pratico ciò che vogliamo, cioè una istanza completa con le proprietà definite in Person e Employee, non stiamo definendo correttamente un’istanza di Employee.

var e = new Employee();
e instanceof Employee // false
e instanceof Person // true

Definire correttamente una variabile d’istanza può non sembrare importante perchè tutto sommato la variabile e comunque ha tutto quello di cui si ha bisogno, ma diventa cruciale se volessimo creare ad esempio una funzione che a seconda del tipo dell’istanza passata in input esegue va ad eseguire operazioni differenti.

function classFactory (input) {
  if (input instanceof Person) {
    ...
  } else if (input instanceof Employee) {
    ...
  }
  ...
}

Per risolvere questo problema, la classe nativa Function di JavaScript ci offre due metodi: callapply. Entrambi servono allo scopo di applicare al contesto specificato i valori passati in input senza cambiarne la natura, ma mentre il primo accetta singoli parametri, il secondo si aspetta di leggerli da un array.

function Employee (params) {
  var params = params || {};
  Person.call(this, params); // Person.apply(this, [params])
  this.role = params.role;
  this.manager = params.manager;
}

Come possiamo notare non abbiamo più bisogno di definire una variabile interna di appoggio da ritornare come abbiamo fatto prima, in quanto la funzione call (o apply) si occuperà prendere i valori contenuti dentro params, applicarli alla classe Person e mantenere this legata al contesto dell’istanza di Employee.

var e = new Employee();
e instanceof Employee // true
e instanceof Person // false

Il processo di estensione di oggetti può essere concatenato liberamente: è possible estendere classi che a loro volta estendono altre classi. Ad esempio se ridefinissimo la classe Manager con le stesse proprietà di Employee e in più quelle di project e employees, allora avremo questa situazione

function Manager (params) {
  ...
  Employee.call(this, params);
  ...
}
function Employee (params) {
  ...
  Person.call(this, params);
  ...
}
function Person (params) {
  ...
}

Inoltre possiamo estendere più classi contemporaneamente all’interno di una sola.

Supponiamo di avere a disposizione una classe per gestire le credenziali di un utente.

function UserCredential (params) {
  var params = params || {};
  this.user = params.user;
  this.password = this.password;
  this.resetUser = function () {...};
  this.resetPassword = function () {...};
}

Potremmo aggiornare la nostra classe Employee in questo modo

function Employee (params) {
  ...
  Person.call(this, params);
  UserCredential(this, params);
  ...
}

Da tenere bene a mente che se le classi che andiamo ad estendere offrono delle stesse proprietà allora l’ultima in ordine di linea di codice va a sovrascrivere le precedenti. Nel nostro caso UserCredential potrebbe sovrascrivere eventuali proprietà di Person.


Estendere una classe non significa che abbiamo solo la possibilità di sfruttarne variabili e metodi, ma si ha la possibilità anche di sovrascriverne il comportamento a piacimento. Possiamo infatti vedere la classe estesa come un insieme di valori di default, in modo che non sia sempre necessario passare tutte le informazioni per valorizzare le proprietà di una classe.

Ad esempio la classe Employee potrebbe sovrascrivere l’inizializzazione della proprietà id rispetto a Person

function Employee (params) {
  var params = params || {};
  Person.call(this, params); // Person.apply(this, [params]);
  this.id = Math.random();
  this.role = params.role;
  this.manager = params.manager;
}

In questo modo i nostri dipendenti avranno sempre un id valorizzato random pur passandone il valore.

var e1 = new Employee();
var e2 = new Employee({id: 0});

e1.id // Math.random()
e2.id // Math.random();

 

Le funzioni in JavaScript offrono la possibilità di definire ed eseguire operazioni che variano dalla semplice esecuzione di una sequenza di algoritmi, alla gestione di chiamate AJAX o eventi del DOM.

Vediamo ora come poterle applicare alla metodologia della programmazione orientata ad oggetti.

Il cuore del ragionamento ruota intorno alla parola chiave di istanza di una funzione, che ne rappresenta l’esecuzione contestualizzata a particolari valori. Se ad esempio generassimo due istanze di una funzione (o classe) Persona, ognuna di loro avrà la sua proprietà nome, cognome, ecc… indipendentemente valorizzato.


Supponiamo ora di voler gestire una lista di semplici aziende e per ognuna specificare le informazioni sulla sede, dipendenti, manager e quant’altro. Definiremo quindi delle funzioni, che prenderanno il nome più appropriato di classi, che ci daranno gli strumenti per stabilire cosa è un dipendente, un manager, ecc… e quali operazioni si possono fare su di loro.

Scriveremo le funzioni in maiuscolo per far capire che sono la definizione di classi e non metodi da usare con un particolare oggetto o evento.

function Employee (params) {
  var params = params || {};
  this.id = params.id;
  this.name = params.name;
  this.company = params.company;
  this.role = params.role;
  this.manager = params.manager;
}
function Manager (params) {
  var params = params || {};
  this.id = params.id;
  this.name = params.name;
  this.company = params.company;
  this.employees = params.employees;
  this.project = params.project;
}

La prima cosa che si può notare è l’uso della parola chiave this, che serve a specificare che quella variabile di seguito al punto è legata all’istanza della funzione che poi genereremo, e della variabile params che ci serve solo come appoggio per definire un valore di default.

Per poter ora usare queste funzioni come classi e quindi istanziarne oggetti, abbiamo a disosizione la parola chiave new.

var e1 = new Employee({
  name: "John",
  role: "developer",
  company: "Blu Note"
});
var e2 = new Employee();
var m1 = new Manager({
  name: "Riccardo",
  employees: [e1],
  project: "Awesome site"
});

Per poter leggere e scrivere poi le proprietà di ogni istanza basterà usare la notazione puntuale come se fossero dei JSON

e1.name // "John"
e1.role // "developer"

e2.name // undefined

m1.project // "Awesome site"

Possiamo inoltre controllare se una certa variabile sia una istanza di una determinata classe in questa maniera

e1 instanceof Employee // true
e2 instanceof Employee // true
m1 instanceof Employee // false

Proviamo ora ad aggiungere alla classe Employee la gestione del salario, aggiungendo una nuova proprietà salary e un metodo per aggiungere gli aumenti.

function Employee (params) {
  var params = params || {};
  this.id = params.id;
  this.name = params.name;
  this.company = params.company;
  this.role = params.role;
  this.manager = params.manager;
  this.salary = params.salary;
  this.addToSalary = function (value) {
    this.salary = this.salary? this.salary + value: value;
    return this.salary
  }
}

All’interno della funzione addToSalary possiamo accedere ai valori delle proprietà di classe, in questo caso a salary, dato che non varia il contesto del chiamante della funzione add rispetto all’istanza.


 

Gli oggetti JSON offrono un ottimo strumento per organizzare e mappare dati. Li usiamo per inviare informazioni al server con le chiamate AJAX, per rappresentare strutture dati, o anche semplicemente per rendere il codice più chiaro e leggibile. Grazie alla loro flessibilità e facilità di manipolazione possiamo inoltre introdurli all’interno del paradigma di programmazione orientata agli oggetti.

Supponiamo di voler gestire una lista di semplici aziende e per ognuna specificare le informazioni sulla sede, dipendenti, manager e quant’altro. Abbiamo quindi bisogno di definire degli oggetti, che prenderanno il nome più appropriato di classi, che ci daranno gli strumenti per stabilire cosa è un dipendente, un manager, ecc… e quali operazioni si possono fare su di loro.


Cominciamo con il modellare quindi le strutture dati per rappresentare i vari elementi tramite oggetti JSON con valori vuoti di default.

Identificheremo un dipendente come una persona con un ID identificativo, un nome, un ruolo lavorativo, chi è il suo capo e il nome dell’azienda per cui lavora.

Scriveremo le variabili in maiuscolo per far capire che servono a definire classi e proprietà degli elementi e non tanto per manipolare le informazioni.

var Employee = {
  id: 0,
  name: "",
  company: "",
  role: "",
  manager: ""
}

Il modello dati del manager sarà simile a quello del dipendente ma invece che definire un ruolo e chi è il suo manager di riferimento avrà le informazioni su quali siano i suoi dipendenti e quale progetto coordina.

var Manager = {
  id: 0,
  name: "",
  company: "",
  employees: [],
  project: ""
}

Ora potremmo creare il nostro primo dipendente e il nostro primo manager dell’azienda.

var firstEm = Employee;
firstEm.name = "John";
firstEm.role = "developer";
firstEm.company = "Blu Note";
...

var firstMa = Manager;
firstMa.name = "Riccardo";
firstMa.project = "Awesome Site";
....

Purtroppo in questa maniera quando andremo a definire nuove variabili con diversi valori, andremo anche a sovrascrivere quelle precedentemente create. Per evitare questo problema dovremo modificare le classi Person e Manager aggiungendo un metodo da invocare alla creazione di un nuovo elemento e che ci restituisca ogni volta un nuovo oggetto con cui lavorare.

var Employee = {
  create: function (params) {
    var params = params || {};
    return {
      id: params.id,
      name: params.name,
      company: params.company,
      role: params.role,
      manager: params.manager
    }
  }
}
var Manager = {
  create: function (params) {
    var params = params || {};
    return {
      id: 0,
      name: "",
      company: "",
      employees: [],
      project: ""
    }
  }
}

Ora siamo sicuri che invocando il metodo create delle rispettive classi otterremo un nuovo oggetto valorizzato con i parametri passati in input oppure un oggetto JSON vuoto.

var e1 = Employee.create({
  name: "John",
  role: "developer",
  company: "Blu Note"
});

var m1 = Manager.create({
  name: "Riccardo",
  employees: [e1],
  project: "Awesome site"
});

Potremo migliorare ulteriormente l’esempio incapsulando le informazioni condivise tra Employee e Manager in un oggetto più generico che estenderemo per evitare di dover riscrivere inutilmente le proprietà.

Possiamo definire una classe Person che useremo come classe di supporto per inizializzare le informazioni di base sia dei dipendenti che manager con un suo metodo create.

var Person = {
  create: function (params) {
    params = params || {};
    return {
      id: params.id,
      name: params.name,
      company: params.company
    }
  }
}

La classe Employee  estenderà la classe Person ereditandone tutte le caratteristiche e in più setterà valori aggiuntivi necessari a specificare le caratteristiche di un dipendente.

var Employee = {
 create: function (params) {
    var person = Person.create(params);
    person.role = params.role;
    person.manager = params.manager;
    return person;
  }
}

La classe Manager, come la classe Employee, estenderà Person e setterà i suoi valori aggiuntivi.

var Manager = {
  create: function (params) {
    var person = Person.create(params);
    person.project = params.project;
    person.eployees = params.employees;
    return person;
  }
}

In questa maniera potremo creare dipendenti e manager semplicemente invocando il metodo create relativamente di Employee e Manager.

var e1 = Employee.create({
  name: "John",
  role: "developer",
  company: "Blu Note"
});

var e2 = Employee.create({
  name: "Smith",
  role: "designer",
  manager: "Riccardo"
});

var e3 = Employee.create();

var m1 = Manager.create({
  name: "Riccardo",
  employees: [e1, e2],
  project: "Awesome site"
});

Importante da tenere in considerazione che con questa struttura al momento della creazione di un elemento non è necessario passare tutti i valori perchè la classe Person comunque ha il compito di ritornare un oggetto JSON che potrà essere manipolato successivamente.


Supponiamo ora di voler avere a disposizione un metodo copy per facilitare le operazioni di creazione di elementi.

Basterà modificare opportunamente la classe Person per ereditarne “gratis” la funzionalità sia in Employee che in Manager.

var Person = {
  create: function (params) {
    params = params || {};
    return {
      id: params.id,
      name: params.name,
      company: params.company,
      copy: function(opt){
        var opt = opt || {};
        var person = this;
        var clone = {};
        for (var prop in person) {
          if (opt[prop]) {
            clone[prop] = opt[prop]
          } else if (person.hasOwnProperty(prop)) {
            clone[prop] = person[prop]
          }
        }
        return clone
      }
    }
  }
}

In questa maniera potremo invocare il metodo copy direttamente dalla variabile creata per ottenere un nuovo oggetto con gli stessi valori, a meno di quelli che gli passiamo in input.

var e4 = e1.copy();
var e5 = e1.copy({name: "Karl"})

e1.name // "John"
e4.name // "John"
e5.name // "Karl"

La porola chiave this ci permette infatti di contestualizzare la lettura dei valori all’oggetto dal quale invochiamo il metodo copy.

In alternativa avremmo potuto definire il metodo copy a livello di classe e quindi ad esempio dentro Manager, in modo che vada a copiare le chiavi di un primo oggetto passato in input e al più sovrascriverle con un secondo parametro.

var m2 = Manager.copy(m1);
var m3 = Manager.copy(m1, {name: "Smith"})

m1.name // "Riccardo"
m2.name // "Riccardo"
m3.name // "Smith"

Le variabili

Quando le informazioni che dobbiamo salvare, modificare o anche semplicemente leggere non sono solo semplici valori fini a se stessi (come un contatore, il risultato di una somma o un elemento HTML magari da inserire nel DOM), ma valori che per qualche logica rappresentano varie proprietà di un unico elemento, non possiamo affidarci solo alla definizione di singole variabili.

Infatti in questa maniera saremo costretti ad usare nomi i più parlanti possibile per differenziarli e mantenere una buona leggibilità del codice, ma che così facendo rischieremo di dover inventare variabili lunghe e fantasiose anche solo per evitare di avere errori di sovrascrittura.

var mySquareBase = 5;
var mySquarePerimeter = mySquareBase * 4;
var mySquareArea = mySquareBase * mySquareBase;

var yourSquareSide = 8;
var yourSquarePerim = yourSquareSide * 4;
var yourSquareArea = yourSquareSide * yourSquareSide;

In questo esempio sopra riportato (ovviamente enfatizzato ma comunque da una buona idea del problema) si può vedere come abbiamo dovuto definire tre variabili per rappresentare tre semplici proprietà di un quadrato e che per differenziarle da una figura all’altra abbiamo dovuto riscriverle tutte. Inoltre le variabili in questo modo sono legate ad una singola geometria solo perchè il nome ce lo suggerisce e non per qualche regola JavaScript particolare.

Per unire le informazioni sia concettualmente che programmaticamente possiamo usare un oggetto JSON che ci permetterà di definire un modello dati condiviso e una sorta di dizionario unico. Ad esempio i quadrati descritti sopra potranno essere riscritti nel seguente modo

var mySquare = { base: 5, perimeter: function(){ return this.base * 4}, area: function(){ return this.base * this.base} }
var yourSquare = { base: 8, perimeter: function(){ return this.base * 4}, area: function(){ return this.base * this.base} }

mySquare.base // 5
mySquare.perimeter() // 20

yourSquare.base // 8
yourSquare.perimeter() // 20

Questa nuovo modo di definire le due variabili potrebbe sembrare uno step complesso e macchinoso, ma in questa maniera ora le informazioni di base, perimetro ed area possono essere considerati a tutti gli effetti proprietà di un quadrato e che in pochi semplici passaggi possono essere astratte e generalizzate.

Supponiamo infatti di avere nelle nostre librerie un metodo copia del tipo

function clone (obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

potremo anche migliorare la fase di inizializzazione delle figure in questa maniera

var square = { base: 0, perimetro: function(){ return this.base * 4}, area: function(){ return this.base * this.base} };

var mySquare = clone(square);
mySquare.base = 5;

var yourSquare = clone(square);
yourSquare.base = 8;

 

 


L’uso di oggetti JSON per definire un modello dati semplice o complesso che sia, ci porta una serie di vantaggi

  • legare diverse informazioni sia logicamente che via codice sotto un unico contenitore per avere una migliore rappresentazione del dato
  • definire una nomenclatura chiara e indipendente dal nome della variabile a cui associamo il JSON riducendo molto il rischio di sovrascrittura
  • condividere una struttura dati il più astratta possibile che definita una volta sola e beneficiare automaticamente di eventuali modifiche alla stessa in tutte le sue implementazioni

Le funzioni

Un’altro importante impiego dei JSON per migliore la leggibilità e qualità del codice riguarda la definizione delle funzioni.

Man mano che i nostri progetti crescono e vengono aggiunte funzionalità dobbiamo splittare la nostra libreria JavaScript dovrà essere suddivisa in più file per evitare di avere un’unica grande lista di funzioni anche nelle pagine in qui non è necessario (con un conseguente spreco di banda e ritardo nel caricamento della pagina).

Inoltre, come per le variabili, il rischio di definire delle funzioni con lo stesso nome è molto alto e sarebbe un vero spreco di tempo se ogni volta che definiamo una funzione dovessimo andare a controllare se nei vari file del progetto ci sia già  definita un metodo con lo stesso nome.

Come per le variabili, “impacchettando” i metodi dentro vari JSON e usando dei nomi generici potremo quindi definire una nomenclatura condivisibile e più semplice pur mantenendola parlante.

Ad esempio supponiamo di voler definire dei widget html da poter riusare a piacimento all’interno delle nostre pagine web. Ogni componente avrà sicuramente delle specifiche ben distinte l’une dalle altre, ma potremmo comunque definire due componenti in questa maniera:

var firstComponent = {
  initialize: function () {
    // Intialize component data
    this.initGlobals(); // Initialize global variables for this current component
    this.loadImages();  // Load images of this current component
    ...
  },
  initGlobals: function () {
    // Define some variables to use them around the component
    ...
  }
  loadImages: function () {
    // If there are lazy images load them
    ...
  }
  // Other methods
  ...
}

var secondComponent = {
  initialize: function () {...},
  this.initGlobals: function () {...},
  this.loadImages: function () {...}
  ...
}

Andando a chiamare le funzioni dei rispettivi componenti sarà molto semplice capire cosa stiamo andando ad invocare.

firstComponent.initialize();
secondComponent.initialize();

Potremo ora sfruttare questa nomenclatura condivisa per creare dei metodi che automaticamente avviano i componenti a partire da una lista di quelli che vogliamo.

var components = [firstComponent, secondComponent, ...];
...
function initComponents (list) {
  for (var index in list) {
    var component = list[index];
    component.initialize();
  }
}
...
initComponents(components);

 


Imparare a scrivere codice secondo queste regole ci faciliterà infine la comprensione e il passaggio ad una programmazione orientata ad oggetti in JavaScript, determinate per la realizzazione di librerie più chiare e mantenibili nel tempo.