In questo articolo ci concentreremo sui nuovi metodi nella versione 1.6 della libreria jQuery JavaScript, così come i cambiamenti ai metodi già esistenti. Le informazioni fornite sono solo un riassunto veloce, raccomando un salto sulla documentazione jQuery per ulteriori informazioni, quando si usa uno dei nuovi metodi.

Mi piacerebbe anche consigliare di imparare velocemente come funzionano e familiarizzare con loro in fretta: non passerà molto tempo prima jQuery 1.7 sia rilasciato.
Cambiamenti ai metodi già esistenti

jQuery è una libreria JavaScript attiva sviluppata con un ciclo di rilascio piuttosto rapido. Oltre a miglioramenti generali, modifiche delle prestazioni e correzioni di bug, nuovi metodi sono spesso aggiunti alla libreria.
In questo articolo daremo uno sguardo alle nuove metodologie che sono state aggiunte alla versione 1.6 + e alcuni dei miglioramenti.
Ritardare l'evento ready con il metodo holdReady()
Il metodo holdReady() viene utilizzato per ritardare il lancio dell’evento ready di jQuery, la pietra angolare che è comunemente usato per eseguire codice personalizzato una volta che il DOM è pronto per essere manipolato. Con jQuery 1.6 possiamo rimandare l’attivazione di questo evento per un periodo di tempo arbitrario in modo da attendere che le altre condizioni siano soddisfatte, come ad esempio il caricamento di un plugin.
Si tratta di un metodo a scopo duale e può essere utilizzato sia per ritardare l’evento che per rilasciare l’evento con la stessa firma. Il metodo accetta un argomento booleano che specifica se l’evento deve essere tenuto o rilasciato.
Uno svantaggio di questo metodo è che dovrebbe essere chiamato nel documento il più presto possibile, nel della pagina, e può ovviamente essere chiamato solo dopo che jQuery stesso sia stato caricato. Come sappiamo, per motivi di prestazioni, gli script di solito dovrebbero essere collocati il più vicino possibile alla fine del documento e spostare jQuery nello del documento deve essere considerato solo quando assolutamente necessario.
Utilizzando holdReady() è super facile; nelle prime fasi del caricamento del documento è possibile chiamare il metodo con il valore vero come argomento:
Copia codice

#
jQuery.holdReady(true);
#
Poi, una volta completato il caricamento del file aggiuntivo che desideriamo, chiamare di nuovo il metodo con il valore false:
Copia codice

#
jQuery.holdReady(true);
jQuery.getScript("myplugin.js", function() {
     jQuery.holdReady(false);
});
#
Aggiunta e rimozione di proprietà degli elementi
Il metodo prop() è un via per recuperare esplicitamente i valori delle proprietà degli elementi. C’è pero una sottile differenza tra le proprietà e gli attributi e questa differenza nel suo uso può causare occasionalmente dei problemi quando si cerca di ottenere o impostare i valori delle proprietà utilizzando i metodo jQuery attr().
L’esempio classico si verifica con gli elementi casella di controllo; a volte ci sono stati dei problemi quando si cerca di impostare dinamicamente la proprietà Checked utilizzando il metodo attr(). Da quando il metodo prop() è stato rilasciato, nella versione 1.6, il metodo attr() è stato, anche esso, modificato in modo che restituisca solo lo stato iniziale della proprietà, tuttavia questo è stato cambiato nella release 1.6.1 per far sì che restituisca anche lo stato attuale quando si usa il metodo attr(). Per utilizzare il metodo prop() si usa la stessa sintassi di quella usata con il metodo attr():
Copia codice

#
$("input[type='checkbox']").prop("checked");
#
Il metodo con questo formato restituisce il valore corrente. Per utilizzare il metodo in modalità setter dobbiamo solo fornire un secondo argomento specificando che cosa vorremmo che il valore debba essere.
Copia codice

#
$("input[type='checkbox']").prop('checked', true);
#
Può essere usato per ottenere il Valore calcolato tramite funzione di callback
Copia codice

#
$("input[type='checkbox']").prop('checked', function( i, val ) {
  return !val;
});
#
Il metodo prop() può anche essere usato per impostare le proprietà personalizzate sugli elementi, e si dovrebbe notare che il metodo restituisce solo il valore della proprietà per il primo elemento in una collezione e non ciascun elemento della collezione.
Per rimuovere le proprietà personalizzate, si può usare il nuovo metodo removeProp(), disponibile dalla versione jQuery 1.6. Questo metodo deve essere utilizzato solo per rimuovere le proprietà personalizzate; se le proprietà native vengono rimosse con questo metodo non sarà più possibile per loro essere nuovamente aggiunte. Le proprietà personalizzate dovrebbero sempre essere rimosse prima che gli elementi siano stati aggiunti per rimuoverlo dal DOM, al fine di prevenire perdite di memoria nelle vecchie versioni di IE.
Un nuovo selettore
Ora possiamo utilizzare lo pseudo-selettore :focus per selezionare un elemento focalizzato, o per determinare se un elemento ha il focus, una grande nuova aggiunta che potrebbe contribuire a salvare tempo nell’intorno del lavoro.
Metodi aggiornati
In aggiunta ai metodi di totalmente nuovi che abbiamo visto finora, alcuni degli attuali metodi di jQuery sono state modificate, tra cui:

  • attr() metodo che restituisce ora “undefined” durante il recupero di un attributo che non è stato impostato
  • closest() metodo che accetta ora elementi jQuery e nodi DOM come filtro
  • find() metodo che accetta ora elementi jQuery e nodi DOM come filtro
  • Is() metodo che accetta ora elementi jQuery e nodi DOM come filtro
  • map() metodo che può iterare oggetti e array
  • nextUntil() metodo che accetta ora elementi jQuery e nodi DOM come filtro
  • parentsUntil() metodo che accetta ora elementi jQuery e nodi DOM come filtro
  • prevUntil() metodo che accetta ora elementi jQuery e nodi DOM come filtro
  • Undelegate() metodo che può sciogliere tutti i gestori di eventi da uno (namespace) spazio di nomi
[nextpage title=”Comprensione di jQuery.Deferred e Promise”] In questo post ci sono molti esempi eseguibili in Javascript, ma potrebbe non funzionare su un lettore RSS.
JQuery 1.5 aveva introdotto il concetto di “azioni differite“. Trovo questo concetto molto potente quando si lavora con Javascript e AJAX, e penso che sia un punto di svolta per il modo in cui siamo abituati a scrivere il codice asincrono in js.
Di solito, il modo in cui siamo abituati a trattare con codice asincrono in Javascript è passando un callback come argomento alla funzione:
Copia codice

#
jQuery.ajax({
    url: "/echo/json/",
    data: {
    json: JSON.stringify({
       firstName: "Pippo",
       lastName: "Cani"})} ,
    type: "POST",
    success: function(person){
        alert(person.firstName + " salvata.");
    },
    error: function(){
        alert("error!");
    }
});
#
Come potete vedere qui stiamo passando due callback (success ed error

) al metodo jQuery.Ajax utilizzando la sintassi dell’oggetto-letterale supportato dal metodo.
Questo lavoro, che non è un’interfaccia standard, richiede una modifica all’interno del metodo post e non si può registrare dei callback multipli.

Presentazione di jQuery.Deferred
jQuery 1.6 apporta due nuovi metodi per l’uso degli oggetti differiti:
il primo è il metodo always()che può essere utilizzato per eseguire una funzione indipendentemente dal fatto che l’oggetto differito sia risolto o rifiutato;
il secondo è il nuovo metodo pipe(), che può essere utilizzato per filtrare gli oggetti passivi sia quando si risolvono o quando falliscono.

Il metodo restituisce un valore filtrato che può essere passato al metodo done() o fail() dell’oggetto differito o al nuovo oggetto promise.
L’oggetto differito è abbastanza facile da capire ma potente. Ha due metodi importanti:

  • resolve
  • reject

E ha tre importanti “eventi” o modi di allegare una retrorichiamata:

  • done
  • fail
  • always

così, in un esempio fondamentalmente stupido sarà qualcosa del genere:

Copia codice

#
var deferred = jQuery.Deferred();
deferred.done(function(value) {
   alert(value);
});
deferred.resolve("Ciao Mondo");;
#
Se si chiama il metodo “reject“, i falliti callback collegati verranno eseguite, la richiamata viene sempre eseguita a prescindere se l’azione differita sia risolta o rifiutata.
Un altro punto interessante è che se si allega una richiamata ad una differita già risolta, si ottiene che viene eseguito immediatamente:
Copia codice

#
var deferred = jQuery.Deferred();
deferred.resolve("Ciao Mondo");
deferred.done(function(value) {
    alert(value);
});
#
Il metodo Promise()
Il nuovo metodo promise() restituisce l’oggetto promise che può essere utilizzato per eseguire del codice arbitrario una volta che tutte le azioni di ogni elemento della collezione, collegate al metodo, siano state completate. Per impostazione predefinita l’oggetto promise monitora le code fx; ma le code personalizzate possono essere specificate fornendo un parametro opzionale al metodo. Un oggetto con il metodo promise() collegato, può essere specificato usando un secondo argomento opzionale per evitare di creare un nuovo oggetto.
Il metodo può essere usato in congiunzione con metodi come done() per eseguire una funzione, quando tutte le animazioni su un elemento sono state completate:
Copia codice

#
$("#animated").promise().done(function () {
    //fai qualcosa
});
#
L’oggetto Deferred ha un altro metodo importante di nome Promise(). Questo metodo restituisce un oggetto con quasi la stessa interfaccia che il Deferred, ma solo ha i metodi da attaccare ai callback e non ha i metodi per “resolve” e “reject“.
Questo è utile quando si vuole fare una chiamata a una API per trarre uso, ma non ha la capacità di risolvere o rifiutare il differito. Questo codice non riuscirà perché la promise non ha un metodo “resolve“:
Copia codice

#
function getPromise(){
    return jQuery.Deferred().promise();
}
try{
    getPromise().resolve("a");
}
catch(err){
    alert(err);
}
#
Il metodo jQuery.ajax in JQuery restituisce una Promise, in modo da poter fare:
Copia codice

#
var post = jQuery.ajax({
    url: "/echo/json/",
    data: {
        json: JSON.stringify({
            firstName: "Pippo",
            lastName: "Cani"
    })} ,
    type: "POST"
});
post.done(function(p){
    alert(p.firstName +  " salvato.");
});
post.fail(function(){
    alert("error!");
});
#
Questo codice fa lo stesso che il frammento di prima con la sola differenza che è possibile aggiungere i callback che si vuole, la sintassi è chiara perché non abbiamo bisogno di un parametro in più nel metodo. D’altra parte è possibile utilizzare la promessa come valore di ritorno di altra funzione, e una delle cose più interessanti è che si possono fare delle operazioni con le promesse.
Il metodo Pipe()
Il metodo Pipe è molto potente e utile, permette di “progettare” una promessa.
Seguendo l’esempio precedente, possiamo fare qualcosa del genere:
Copia codice

#
var post = jQuery.post(
    "/echo/json/",
    {json: JSON.stringify({
            firstName: "Pippo",
            lastName: "Cani"
        })
    }).pipe(function(p){
        return "Salvato " + p.firstName;
});
post.done(function(r){
    alert(r);
})
#
Qui stiamo facendo una proiezione dei risultati che sarebbe un oggetto “person“. Così, invece di avere una differita di person, abbiamo ora una differita di “Salvato {firstName}“.
Un’altra caratteristica molto interessante del metodo pipe è che può restituire un differito dall’interno del pipe di callback. Immaginiamo di avere due metodi, uno per ottenere un ID di un Cliente attraverso un id interno e un altro per ottenere l’indirizzo di una persona dal ID:
Copia codice

#
function getCustomerById(customerId){
    return jQuery.post("/echo/json/", {
        json: JSON.stringify({
            firstName: "Pippo",
            lastName: "Cani",
            ID: "123456789"
        })
    }).pipe(function(p){
        return p.ID;
    });
}
function getPersonAddressById(ID){
    return jQuery.post("/echo/json/", {
        json: JSON.stringify({
            ID: "123456789",
            address: "Sempre Viva 12345, Legione Straniera"
        })
    }).pipe(function(p){
        return p.address;
    });
}
function getPersonAddressById(id){
    return getCustomerById(id)
        .pipe(getPersonAddressById);
}
getPersonAddressById(123)
    .done(function(a){
        alert("L'indirizzo è " + a);
    });
#
Come potete vedere qui, ho aggiunto un nuovo metodo getPersonAddressByID. Questo metodo restituisce una differita che è una combinazione dei due metodi. Se uno dei metodi della pipeline non supera il “master” differito allora fallirà.
Le pipelines presentano alcuni altri usi, per esempio è possibile rifiutare la differita all’interno del callback del pipe.
Un altro caso interessante del uso che mi viene in mente per i pipes sono le differite ricorsive. Immagina che hai iniziato un’operazione asincrona nel backend, ed è necessario fare il “polling” per vedere se il compito è fatto e, quando il compito è fatto, fare qualcosa di diverso.
Copia codice

#
//1: fatto, 2: cancellato, other: attesa
function getPrintingStatus(){
    var d = jQuery.Deferred();
    jQuery.post(
        "/echo/json/",
        {
            json: JSON.stringify({
		status: Math.floor(Math.random()*8+1)
	    }),
            delay: 2
        }
    ).done(function(s){
        d.resolve(s.status);
    }).fail(d.reject);
    return d.promise();
}
function pollUntilDone(){
    //fare qualcosa
    return getPrintingStatus()
            .pipe(function(s){
                if(s === 1 || s == 2) {
                    // se lo status è fatto o cancellato
                    // restituisce lo status
                    return s;
                }
                // se lo status è in attesa ...
                // chiama la stessa funzione ...
                // e restituisce un differito ...
                return pollUntilDone();
            });
}
jQuery.blockUI({message: "Caricando..."});
pollUntilDone()
    .pipe(function(s){
        // progetto il codice di stato
        // in una stringa di senso compiuto.
        switch(s){
            case 1:
                return "fatto";
            case 2:
                return "cancellato";
        }
    })
    .done(function(s){
        jQuery.unblockUI();
        alert("Lo status è " + s);
    });
#
Combinando le promesse con jQuery.when
Un altro metodo molto utile è di jQuery.when. Il metodo accetta un numero arbitrario di promesse, e restituisce un master differito che:

  • sarà “resolved” quando tutte le promesse saranno risolte:
  • sarà “rejected” se una delle promesse sarà rifiutata

La richiamata ha i risultati di tutte le promesse.
Questo è un esempio:

Copia codice

#
function getCustomer(customerId){
    var d = jQuery.Deferred();
    jQuery.post(
        "/echo/json/",
        {json: JSON.stringify({
            firstName: "Pippo",
            lastName: "Cani",
            ID: "123456789"})
        }).done(function(p){
        d.resolve(p);
    }).fail(d.reject);
    return d.promise();
}
function getPersonAddressById(ID){
    return jQuery.post(
            "/echo/json/",
            {json: JSON.stringify({
                 ID: "123456789",
                 address: "Siempre Viva 12345, Legione Straniera"
            })
        }).pipe(function(p){
            return p.address;
        });
}
jQuery.when(getCustomer(123), getPersonAddressById("123456789"))
    .done(function(person, address){
        alert("Il nome è " + person.firstName + " e il suo indirizzo è " + address);
    });
#
Come si può vedere alla fine di questo esempio, jQuery.when restituisce una nuova differita e stiamo usando due risultati èer callback realizzato.

Notate che ho cambiato il metodo GetCustomer; questo perché nella promessa di una chiamata AJAX, il carico utile è contenuto come primo elemento nel risultato, ma ha anche altre cose come il codice di stato.

In questo esempio si possono mescolare jQuery.when e pipes come segue:

Copia codice

#
function getCustomer(customerId){
    var d = jQuery.Deferred();
    jQuery.post(
        "/echo/json/",
        {json: JSON.stringify({
            firstName: "Pippo",
            lastName: "Cani",
            ID: "123456789"
        })
    }).done(function(p){
        d.resolve(p);
    }).fail(d.reject);
    return d.promise();
}
function getPersonAddressById(ID){
    return jQuery.post(
        "/echo/json/", {
        json: JSON.stringify({
            ID: "123456789",
            address: "Siempre Viva 12345, Legione Straniera"
        })
    }).pipe(function(p){
        return p.address;
    });
}
jQuery.when(getCustomer(123), getPersonAddressById("123456789"))
    .pipe(function(person, address){
        return jQuery.extend(person, {address: address});
    }).done(function(person){
        alert("Il nome è " + person.firstName + " e il suo indirizzo è " + person.address);
    });
#
Un altro caso interessante con l’operatore jQuery.when, è quando è necessario caricare parecchie cose sullo schermo, ma si vuole solo un unico messaggio per il loading:
Copia codice

#
function getCustomer(customerId){
    var d = jQuery.Deferred();
    jQuery.post(
        "/echo/json/",
        {json: JSON.stringify({
            firstName: "Pippo",
            lastName: "Cani",
            ID: "123456789"
        }),
        delay: 4
    }).done(function(p){
        d.resolve(p);
    }).fail(d.reject);
    return d.c;
}
function getPersonAddressById(ID){
    return jQuery.post(
        "/echo/json/", {
        json: JSON.stringify({
            ID: "123456789",
            address: "Siempre Viva 12345, Legione Straniera"
        }),
        delay: 2
    }).pipe(function(p){
        return p.address;
    });
}
function load(){
    jQuery.blockUI({message: "Caricando..."});
    var loadingCustomer = getCustomer(123)
        .done(function(c){
             $("span#firstName").html(c.firstName)
        });
    var loadingAddress = getPersonAddressById("123456789")
        .done(function(address){
            $("span#address").html(address)
        });
    jQuery.when(loadingCustomer, loadingAddress)
        .done(jQuery.unblockUI);
}
load();
#
Ci sono altri metodi utili e modi in cui è possibile combinare i differiti e incoraggio vivamente di leggere il suo uso nella documentazione di jQuery su Deferred Object.
Questo è tutto per ora! Spero che questo post sia utile, come lo è per me a portata di click.