CoffeeScript: perchè amarlo!

Ne avevo già sentito parlare al codemotion di Roma e avevo visto qualcosa in maniera superficiale ma, ora che è incluso in rails 3.1, mi sono deciso a studiarlo per bene.

Per iniziare cominciamo con dire che CoffeeScript è essenzialmente una riscrittura sintattica di JavaScript. La sintassi è figlia di papà Ruby e mamma Python.

Qualche alias

Uno degli obbiettivi di coffeescript è rendere il codice più leggibile (e quindi più mantenibile).

Per prima cosa vediamo gli alias per gli operatori di comparazione

  • is è mappato su ===
  • isnt è mappato su !==
  • == e != sono mappati rispettivamente su === e !==

Per chi avesse dei dubbi === significa che è esattamente uguale (valore e tipo).

Vediamo un primo esempio coffeescript:

if thisPost is good
    comment()

if thisBlog isnt boring
    share()

Che viene compilata in codice javascript e nel particolare:

if (thisPost === good){
  comment();
}

if (thisBlog !== boring){
  share();
}

Altri alias interessanti sono quelli sugli operatori logici:

  • and è mappato su &&
  • or è mappato su ||
  • ! è mappato su !

un esempio veloce:

if thisPost is good and not tooLong
  comment()

if thisBlog isnt boring or loveMe
  share()

che viene tradotto in:

if (thisPost === good && !tooLong){
  comment()
}

if (thisBlog !== boring || loveMe){
  share();
}

If statement

Come abbiamo già visto l’if statement è simile a javascript tradizionale, unica differenza non vengono usate ne le tonde ne le graffe, un esempio di codice che si spiega da solo è:

if booleanValue
  firstOperation()
  secondOperation()
else
  thirdOperation()

Che viene tradotto in:

if (booleanValue){
  firstOperation();
  secondOperation();
}else{
  thirdOperation();
}

Ovviamente c’è anche la versione contratta:

activity = if day then wakeUp else sleep

che viene tradotto con

activity = day ? wakeUp : sleep;

Un’altra figata è l’unless

stayHungry() unless false

tradotto in

if (!false){
  stayHungry();
}

Switch-Case

Come tutto quello che abbiamo visto fin’ora anche lo switch è un pò più intuitivo rispetto a javascript e soprattutto non c’è bisogno di aggiungere una istruzione break al termine di ogni istruzione case: CoffeeScript lo fa automaticamente per voi.

switch name
  when "Michele"
    askForComment()
  when "Francio" then askForLayout()
  when "Stefano" then askJob
  when "Andrea"
    askToRead()
    askToBeAuthor()
  when "Chiara"
    askDate();
  else doNothing()

tradotto in:

switch (name) {
  case "Michele":
    askForComment();
    break;
  case "Francio":
    askForLayout();
    break;
  case "Stefano":
    askJob;
    break;
  case "Andrea":
    askToRead();
    askToBeAuthor();
    break;
  case "Chiara":
    askDate();
    break;
  default:
    doNothing();
}

Basic Loop

È abbastanza prevedibile come funzioni il loop in coffeescript, la sintassi è molto simile a quella dell’if statement, eccola:

while work > time then freakOut()

while time > work
  relax()
  mozyAround()

Che viene tradotta in:

while (work > time) {
  freakOut();
}
while (time > work) {
  relax();
  mozyAround();
}

C’è anche l’untill che è:

workOut() until energy < exhaustion

Che viene tradotto come un ciclo while con condizione preceduta dal not

while (!(energy < exhaustion)) {
  workOut();
}

Loop di un array o di una collection

Questa parte è secondo me l’evoluzione semantica più interessante, vediamo subito un esempio:

spectacularfoo = ['Superman', 'Spiderman', 'Batman', 'Tiger man', 'you']
for superHero in spectacularfoo
 alert superHero

Che viene tradotto in questo un sacco di codice:

var spectacularfoos, superHero, _i, _len;
spectacularfoo = ['Superman', 'Spiderman', 'Batman', 'Tiger man', 'you'];
for (_i = 0, _len = spectacularfoo.length; _i < _len; _i++) {
  superHero = spectacularfoo[_i];
  alert(superHero);
}

Anche gli array associativi sono ben gestiti dalla sintassi di coffeescript:

spectacularfoo = 'Superman' : "Luthor", 'Spiderman' : 'Doctor Octopus', 'Batman' : 'Joker', 'Tiger man' : 'Black Tiger', 'you' : 'ouy'

for superHero, evil of spectacularfoo
  alert superHero + " vs " + evil

Tradotto in:

var evil, spectacularfoo, superHero;
spectacularfoo = {
  'Superman': "Luthor",
  'Spiderman': 'Doctor Octopus',
  'Batman': 'Joker',
  'Tiger man': 'Black Tiger',
  'you': 'ouy'
};
for (superHero in spectacularfoo) {
  evil = spectacularfoo[superHero];
  alert(superHero + " vs " + evil);
}

Le funzioni

Definire una funzione in coffeescript è supereasy, prima si mette il nome della funzione seguita dai parametri e poi il corpo della funzione. Vediamo la sintassi con un esempio per chiarire:

vs = (good, evil = "Sith") ->
  alert "#{good} vs #{evil}."

vs 'Luke Skywalker', 'Darth Vader'

Questa è la sintassi di base dietro la creazione e l’utilizzo di una funzioni.
CoffeeScript genera il codice per controllare se un valore è stato passato o no.
Invocare una funzione è altrettanto facile. Non c’è bisogno di parentesi: basta passare i parametri di uno dopo l’altro.

var vs;
vs = function(good, evil) {
  if (evil == null) {
    evil = "Sith";
  }
  return alert("" + good + " vs " + evil + ".");
};
vs('Luke Skywalker', 'Darth Vader');

Buttare un pò di javascript così com’è nel codice coffeescript

Ci sono delle volte in cui viene comodo poter scrivere del codice javascript direttamente senza che venga interpretato da coffeescript (per esempio le animazioni).
È molto semplice, basta usare ` :

rawJS = `function() {
  return someSuperComplexThingie;
}`

Conclusione

Ok, come introduzione credo sia abbastanza! Ci sono un sacco di altra roba veramente interessante in coffeescript (come per esempio che tutto è un’espressione), per approfondire l’argomento passate ancora da questo blog oppure se non potete aspettare:


Alcune novità di rails 3.1

Assets Pipelining

Le 3 importanti features della asset pipeline sono:

  1. concatenare gli asset
  2. minifizzare o comprimere gli asset
  3. codificare gli asset usando un altro linguaggio come SASS per i CSS e CoffeeScript per i javascript e ERB per entrmbi.

Un’altra novità è che ora la cartella di default per gli asset è app/assets e i file presenti in questa cartella vengono serviti dal middleware Sprocket (che ora è nelle dipendenze di ActionPack).

Gli assets possono essere messi in:

  • app/assets : la cartella di default, sono gli asset dell’applicazione come images, javascripts o stylesheets
  • lib/assets : sono gli asset per le librerie che sono condivise da tutta l’applicazione
  • vendor/assets : sono gli asset per entità esterne come per esempio plugin Javascript

In rails 3.1 l’assets pipeline è di default, ad ogni modo possiamo disattivarla aggiungendo in application.rb

config.assets.enabled = false

Per approfondire: Rails Guides – Asset Pipeline

HTTP Streaming

Ora i fogli di stile e i JavaScript vengono inviati al browser mentre il server sta ancora costruendo la risposta. In sostanza in questo modo le applicazioni Rails possono iniziare a restituire il layout prima che la vista e le azioni dello specifico controller siano caricate completamente. Richiede Ruby 1.9.2 e richiede il supporto dal web server. La combinazione nginx e Unicorn è perfetta per sfruttare questa nuova feature.

Ora JQuery è il framework javascript di default

E direi che era anche ora🙂. Ad ogni modo per i “pazzi” che sono affezionati a prototype è possibile usare

rails new myapp -j prototype

Reversible Migrations

Rails 3.1 ha aggiunto un pò di magia alle migration. Attualmente quando creiamo una migration siamo abituati a specificare due metodi di classe: up e down. up viene chiamato quando eseguiamo la migration mentre down quando facciamo il rollback.

In rails 3.1 viene introdotto un nuovo metodo di classe: change. Tramite change noi specifichiamo solo l’up e poi sarà rails che si occuperà del down.

class CreatePosts < ActiveRecord::Migration
  def change
    create_table :posts do |t|
      t.string :title
      t.text :body

      t.timestamps
    end
  end
end

In questo esempio stiamo creando una tabella posts che ha un titolo (string) e un body (text). Se dovessimo definire il down scriveremmo qualcosa come

def self.down
  drop_table :posts
end

Specificando change questo non serve, infatti se noi lanciamo rake db:migrate seguito da rake db:rollback abbiamo:

rake db:migrate
  (in /home/svarione/dev/test)
  ==  CreatePosts: migrating ====================================================
  -- create_table(:posts)
     -> 0.0012s
  ==  CreatePosts: migrated (0.0013s) ===========================================

rake db:rollback
  (in /home/svarione/dev/test)
  ==  CreatePosts: reverting ====================================================
  -- drop_table("posts")
     -> 0.0007s
  ==  CreatePosts: reverted (0.0008s) ===========================================

Attenzione non possiamo usare sempre change, a volte dovremo specificare up e down, mi riferisco per esempio al remove_column che ovviamente non ha tutte le informazioni necessarie per fare il suo contrario (manca il type)


Web App Theme

Web App Theme è una gemma creata da Andrea Franz che serve per generare velocemente il layout dell’amministrazione di un sito internet.

Installazione

Per la versione 3 di rails bisogna usare la versione di web-app-theme uguale o superiore alla 0.6.2 (‘web-app-theme’, ‘>= 0.6.2’).

Per la versione 2 di rails consiglio di usare la versione 0.5.3 (‘web-app-theme’, ‘0.5.3’).

Specifica la gemma web-app-theme nel tuo Gemfile, solo per :developer e :test

group :development, :test do gem 'web-app-theme', '>= 0.6.2' end

Utilizzo

web_app_theme:theme

È il generatore di layout.

Chiamandolo senza parametri, genera un layout di nome application.html.erb usando il tema di default

rails g web_app_theme:theme

Puoi specificare il nome del layout

rails g web_app_theme:theme admin # genera il layout "admin.html.erb"

Specificando l’opzione –theme si pò specificare un determinato tema

rails g web_app_theme:theme admin --theme="drastic-dark"

Per modificare i css di un layout già creato, basterà passare al generatore l’opzione –no-layout

rails g web_app_theme:theme --theme=bec --no-layout

Questa gemma supporta sia il template engine erb (default) che haml, per specificarlo basta valorizzare l’opzinone –engine

rails g web_app_theme:theme --engine=haml

Puoi specificare il nome dell’applicazione per far si che venga direttamente settato sia nell’header che nel footer utilizzando l’opzione –app-name

rails g web_app_theme:theme --app-name="My New Application"

Oltre al layout per l’amministrazione (default) c’è anche il layout per il login. Basta settare l’opzione –type che accetta come valori administration (amministrazione) e sign (login)

rails g web_app_theme:theme sign --layout-type=sign

web_app_theme:assets

Usata per copiare un tema a scelta dalla gemma alla propria applicazione, senza parametri copierà il tema ‘default’

rails g web_app_theme:assets --theme=red

Questo copierà i css del tema su app_name/assets/stylesheets/web-app-theme e le immagini su app_name/assets/images/web-app-theme path

web_app_theme:themed

Se hai un controller chiamato come il plurale del modello, puoi specificare solo il controller

rails g web_app_theme:themed posts # c'è un modello di nome Post e un controller di nome PostsController
rails g web_app_theme:themed admin/gallery_pictures # c'è un modello di nome GalleryPicture e un controller Admin::GalleryPicturesController (nel namespace admin)

Usando l’opzione –layout si può specificare il layout precedentemente creato, con questa opzione si aggiunge un link nell’header in automatico

rails g web_app_theme:themed posts --layout=admin # aggiunge un link nell'header

Se il controller ha un nome diverso dal modello al plurale è sufficiente specificarlo come secondo parametro

rails g web_app_theme:themed items post # c'è un modello di nome Post e un controller di nome PostsController
rails g web_app_theme:themed admin/items post # c'è un modello di nome Post e un controller di nome Admin::PostsController

Se usi will_paginate usa l’opzione --will-paginate:

rails g web_app_theme:themed items post --will-paginate

Anche questo generator supporta sia l’engine erb che l’engine haml

rails g web_app_theme:themed posts --engine=haml

Per generare una view con solo testo (quindi hai qualcosa come map.resource :dashboard in routes.rb), puoi usare –themed-type=text

rails g web_app_theme:themed dashboards --themed-type=text

Per visualizzare i messaggi di errore nei form generati dovrai modificare enviroment.rb e agguingere

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
if html_tag =~ /<label/
%|<div>#{html_tag} <span>#{[instance.error_message].join(', ')}</span></div>|.html_safe
else
html_tag
end
end


Introduzione ai CANVAS

Il modo migliore per fare un’introduzione ai canvas è quello di vedere un semplice esempio.

Inserire l’elemento <canvas> nella nostra pagina

Prima di tutto inseriamo l’elemento canvas all’interno della nostra pagina html5:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas Hello World</title>
</head>
<body>
<h1>Canvas Hello World</h1>
<canvas></canvas>
<p>After Canvas</p>
</body>
</html>

Inizialmente l’oggetto canvas è vuoto e completamente trasparente. Se non è diversamente specificato l’oggetto è un rettangolo di 300×150 pixels. Una volta specificato il canvas dobbiamo farci fornire il contesto 2d, inoltre modifichiamo la grandezza per avere più spazio per disegnare:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas Hello World</title>
<script type="application/javascript">
function disegna(){
var myCanvas = document.getElementById("canvas");
var context = myCanvas.getContext('2d');
}
window.onload=disegna();
</script>
</head>
<body>
<h1>Canvas Hello World</h1>
<canvas id="canvas" width="800" height="600"></canvas>
<p>After Canvas</p>
</body>
</html>

La funzione “disegna()” definita nell’head (code not-intrusive) viene lanciata all’onload del nostro documento per essere sicuro che il DOM sia completamente caricato. Questa funzione acquisisce dall’elemento canvas (specificato tramite il getElementById) il contesto 2d necessario, come vedremo successivamente, per disegnare. Ci sono diversi modi per specificare la misura del canvas, quello che ho scelto è di valorizzare gli attributi height e width del tag.

Disegnare un rettangolo e colorarlo

Per disegnare sarà sufficiente richiamare le funzioni della varia- bile context che abbiamo appena creato. La prima funzione che vediamo è strokeRectche accetta 4 parametri:

  1. cordinata x dell’angolo in alto a sinistra
  2. cordinata y dell’angolo in alto a sinistra
  3. lunghezza
  4. larghezza

strokeRect delinea il bordo di un rettangolo. Un’altra funzione che useremo spesso è fillRect che richiede gli stessi parametri di strokeRect e che a differenza crea un rettangolo pieno. Il colore di default degli oggetti che creiamo è nero. Per cambiare colore possiamo utilizzare fillStyle. fillStyle è una proprietà (non una funzione!) di context che permette di decidere il colore con cui colorare. La sintassi è semplice:

context.fillStyle = '#000000';

come valore di fillStyle possiamo dare codice colori usati anche nei css, quindi codici esadecimali (es. “#000000”), rgb (es. “rgb (255,255,255)”), RGBa (es. “rgba(200, 54, 54, 0.5)”) e anche HSLa (es “hsla(170, 50%, 45%, 1)”) . Modifichiamo la nostra funzione disegna() per farle scrivere un rettangolo largo e alto come il nostro canvas, che parta dalla co- ordinata 0, 0 e che sia di colore rosso:

<script type="application/javascript">
function disegna(){
var myCanvas = document.getElementById("canvas");
var context = myCanvas.getContext('2d');
context.fillStyle = 'rgb(255, 0, 0)';
context.fillRect(0, 0, 800, 600);
}
</script>

Rettangoli e linee: un tributo a Mondrian

Mondrian con i canvas

Per finire vi propongo qualcosa di leggermente più complesso, un tributo a Mondrian. In questo esempio ho utilizzato oltre a le funzioni che ho appena descritto anche:

  • lineWidth: questa proprietà deve avere un valore numerico e descrive la larghezza delle linee
  • moveTo: questa funzione richiede 2 coordinate e sposta il nostro puntatore di disegno nelle coordinate che gli passiamo
  • lineTo: questa funzione richiede 2 coordinate e disegna una linea dalla posizione del puntatore di disegno in cui siamo fino al punto che gli passiamo
Ecco i file sorgenti: esempio canvas mondrian HTML5

Conclusione

Come abbiamo già detto le API per usare i canvas richiederebbero una guida a se stante, per ora abbiamo visto come disegnare una figura particolarmente semplice (il rettangolo) e le linee dritte però i canvas permettono molto di più!


WHATWG non è l’acronimo di una bestemmia!

The Web Hypertext Applications Technology Working Group is a loose, unofficial, and open collaboration of Web browser manufacturers and interested parties. The group aims to develop specifications based on HTML and related technologies to ease the deployment of interoperable Web Applications, with the intention of submitting the results to a standards organisation. This submission would then form the basis of work on formally extending HTML in the standards track.

The creation of this forum follows from several months of work by private e-mail on specifications for such technologies. The main focus up to this point has been extending HTML4 Forms to support features requested by authors, without breaking backwards compatibility with existing content. This group was created to ensure that future development of these specifications will be completely open, through a publicly-archived, open mailing list. Working drafts of the specifications will be continuously available on the WHATWG Web site. As the drafts reach stable milestones, the group will publish snapshots for extensive review by the community.

Tratto da http://www.whatwg.org/news/start

Il gruppo Nasce ne 2004 quando gli standard web sono ancora lontani e i produttori di browser sono quelli che fanno da padroni in un iper-universo farcito di tag semanticamente scorretti (di dubbia interpretazione da parte dei browser) e da siti web formattati con l’uso di tabelle ed immagini gif trasparenti.

L’obbiettivo del WHATWG fondato dai membri di Apple, Opera, Mozilla e diretto da Ian Hickson (Google) è quello di favorire gli standard sul web per poi consentire lo sviluppo di applicazioni che possano funzionare senza tecnologie proprietarie e quindi plug in di terze parti (standalone web applications).

L’interesse per gli standard consiste anche nella creazione un algoritmo unico per il parsing corretto dell’HTML in modo da non tollerare più gli errori di codice mostrandoli agli utenti finali; ciò invoglierebbe i designers e i web developers a prestare maggiore attenzione al proprio codice evitando ore infinite ed inutili di lavoro agli sviluppatori dei browser attualmente costretti fornire soluzioni non standard per garantire la visualizzazione dei contenuti.

Attualmente lo sviluppo dell’HTML5 è nelle mani del W3C e del WHATWG che lavorano in combinazione per definire delle specifiche che possano soddisfare sia la retrocompatibilità dei siti in HTML4 che le esigenze della nuova generazione delle web application.

La presenza di sviluppatori web all’interno del WHATWG ci garantisce che il supporto tecnologico e le esigenze che abbiamo sempre ambito possono essere finalmente soddisfatte con un linguaggio di formattazione orientato non solo ai contenuti ma anche alla presentazione degli stessi. Quindi non ci resta che aspettare che le specifiche vengano rilasciate e nel frattempo stupirci con ciò che già ci consente di fare l’HTML5!


HTML5 panoramica

È giunto finalmente il momento di vedere quali sono le rivoluzioni (sempre che di rivoluzioni in senso stretto si possa parlare) introdotte dall’HTML5; in pratica, il presente articolo è una specie di bigino di quello che verrà trattato nei prossimi post

Uno sviluppo del codice developer-oriented

Prima di tutto, HTML5 permette una stesura del DOCTYPE e del charset developer-oriented: questo ci consentirà di smettere di copiare e incollare parti di codice che la maggior parte di noi -compreso il sottoscritto- sa sommariamente a cosa servono e come vengono interpretate dai browser. Questa caratteristica è molto interessante perchè permette di avere piena consapevolezza di quello che stiamo facendo.

Semantica e HTML5

I nuovi elementi strutturali introdotti da HTML5, la ridefinizione di alcuni già esistenti e la loro importanza nella stesura di un codice semantico sono un argomento centrale della specifica. Sebbene HTML5 sia ancora un draft, questi nuovi tag possono essere già utilizzati, ma alcuni semplici accorgimenti saranno necessari perchè siano interpretati correttamente da tutti i browser. Inoltre, vedremo quanto il loro utilizzo migliori sensibilmente la comprensione e il mantenimento del codice.

I forms

I forms sono da sempre un problema, attualmente siamo abituati ad inzepparli di javascript, per aumentarne l’usabilità e le potenzialità. Anche in questo caso, il nostro amico HTML5 ci viene incontro, proponendoci nuovi type per gli input e nuovi attributi: con pochi comandi riusciremo a fare ciò che normalmente otteniamo con diverse righe di codice javascript. Non sto parlando solo di validatori (comunque, particolarmente potenti), ma anche di vere e proprie accortezze per i sistemi mobile (come, ad esempio, presentare tastiere diverse a seconda del tipo di dato che desideriamo che l’utente inserisca). Tutto questo sarà visto in un’ottica cross-browser e gracefully-degrading.

<video> e <audio>

La multimedialità è un tema sempre in voga: attualmente il web non è più costituito solo da testo, ma sempre più spesso abbiamo video, musica e immagini come elementi imprescindibili di un messaggio sempre più complesso e completo. Probabilmente la caratteristica più conosciuta e attesa di HTML5 è proprio la possibilità di gestire i diversi contenuti multimediali senza la necessità di plugin di terze parti. E’ quindi doveroso e interessante illustrare i tag video e audio e come “degradarli” su tutti i browser. Tuttavia esistono – ed occorre metterli in luce – alcuni problemi sui codec e il loro funzionamento.

<canvas>

Questo tag è forse uno degli elementi che personalmente mi hanno maggiormente colpito di HTML5: ci consente, infatti, di disegnare forme geometriche e, quindi, “giocare” con il nostro utente, senza la necessità di plugin di terze parti.

Offline con il cache manifest

Queste funzionalità permettono nuovi approcci alle problematiche/potenzialità della comunicazione sul web. Nel dettaglio, vedremo il Cache Manifest e come manipolarlo a nostro piacere.

HTML5 e oltre…

Parleremo anche di drag and drop, geolocalizzazione (aprendo anche il relativo vaso di pandora), sistemi di messaging, thread e socket!!!