Implementiamo Google Instant sul nostro sito con MooTools

Ieri Google ha pubblicato il nuovo servizio di ricerca istantanea, chiamato per l’appunto “Google Instant”.

A detta di Google, questo nuovo sistema di ricerca permette di far risparmiare 4 secondi a ricerca, che si traduce in un risparmio globale di 11 ore al secondo.

A questo punto mi è venuto un dubbio: se riesco a risparmiare tempo più velocemente del tempo che scorre, potrò tornare indietro nel tempo come Michael J. Fox?

Ma si che si può, vai tranqui...
Ma si che si può, vai tranqui...

Non riuscendo a trovare risposta ai miei quesiti (Michael non so perché ma non mi ha convinto) ho deciso di provare a implementare anche io questo sistema di ricerca utilizzando MooTools e le Google Search APIs.

Piano d’Attacco

La ricerca istantanea non è poi così complicata da realizzare tecnicamente, la cosa più impressionante è la velocità con la quale Google è in grado di fornire i risultati, ma visto che anche noi vogliamo utilizzare i server di google, questo non sarà un problema.

Sfogliando la documentazione delle Google AJAX Search API ci si rende conto subito che il sistema proposto nell’Introduction non ci potrà essere d’aiuto. Queste API infatti, pur essendo molto comode, automatizzano troppo il processo, gestendo da sé il form di ricerca. Il nostro obiettivo invece è quello di eseguire una chiamata AJAX ad ogni pressione di un tasto nella input di ricerca. Infatti nell’esempio che mostrerò ho deciso di non inserire neanche il pulsante di submit.

Proseguendo nella lettura della documentazione arriviamo al paragrafo “Flash and other Non-Javascript Environments” e le cose iniziano a farsi interessanti. Qui infatti ci viene offerta la possibilità di fare una chiamata AJAX e di ottenere la lista dei risultati in formato JSON. Tutto OK quindi, o quasi… In realtà non possiamo fare una classica chiamata AJAX perché verremmo subito bloccati dalla same origin policy ovvero un limite di sicurezza imposto dai browser che non consente di fare chiamate AJAX su domini “esterni”.
Poco più in basso nella documentazione però viene in nostro soccorso JSON-P ovvero una particolare chiamata AJAX non vincolata dalla same origin policy che passa il risultato tramite una callback.

Grazie a MooTools questo tipo di chiamata è veramente semplice, infatti in MooTools More è presente la classe Request.JSONP che ci consente di usare questa tecnologia esattamente come una qualsiasi altra normalissima Request AJAX.

Ora che tutti i pezzi del puzzle sono al loro posto…

Implementazione

Ecco la classe che ho prodotto in pochissimo tempo grazie a MooTools e Google:

var InstantSearch = new Class({
    Implements: Options,

    options: {
        lang: 'en',
        results: 4,
        append: ''
    },

    initialize: function(options) {
        this.setOptions(options);
        this.searchInput = document.id(this.options.searchInput);
        this.resultsContainer = document.id(this.options.resultsContainer);
        this.searchInput.addEvent('keyup', this.updateSearch.bind(this));
    },

    updateSearch: function() {
        if (this.request) this.request.cancel();
        this.request = new Request.JSONP({
            url: 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0',
            method: 'get',
            data: {
                q: this.searchInput.get('value') + ' ' + this.options.append,
                hl: this.options.lang,
                rsz: this.options.results
            },
            onComplete: function(response) {
                this.resultsContainer.set('html','');
                if (response.responseStatus == 200)
                    response.responseData.results.each(function(result) {
                        var resultBlock = new Element('DIV', {'class': 'result'});
                        new Element('H2', {html: result.title}).inject(resultBlock);
                        new Element('A', {
                            html: result.url,
                            href: result.url,
                            title: result.titleNoFormatting,
                            rel: 'external'
                        }).inject(resultBlock);
                        new Element('P', {html: result.content}).inject(resultBlock);
                        resultBlock.inject(this.resultsContainer);
                    }, this);
            }.bind(this)
        }).send();
    }
});

Alcune informazioni utili: l’indirizzo che ho usato per la richiesta JSONP (http://ajax.googleapis.com/ajax/services/search/web?v=1.0) è privo della chiave d’uso che google consiglia di usare sempre, ma che non è obbligatoria e quindi nel nostro esempio ho ritenuto superflua.

La classe va inizializzata passando obbligatoriamente come parametri una input e un container (un DIV o altro) per l’elenco dei risultati, il resto sarà automatico.
Ci sono inoltre alcune opzioni che è possibile alterare, come:

  • lang: permette di cambiare la lingua della ricerca (default: en)
  • results: permette di cambiare il numero di risultati restituiti. Google permette dei valori compresi tra 4 e 8 (default: 4)
  • append: permette di aggiungere una stringa in fondo alla ricerca inserita dall’utente. In questo modo si può ad esempio limitare i risultati a un particolare sito con “site:miosito.it” o aggiungere sempre un determinato termine

Ci sono altre opzioni che google offre per modificare la ricerca, ma ho preferito mantenere la classe il più semplice possibile per questo articolo.

Vediamola all’opera:
[iframe src=”//jsfiddle.net/KhTv2/1/embedded/”]

La velocità è verramente impressionante a mio avviso, tuttavia senza DeLorean mi sa che il viaggio nel tempo dovrà attendere…