Tag: javascript

Mio screencast su Thinkcode.tv

È online da qualche giorno il mio primo screencast pubblicato per thinkcode.tv. L’argomento è jQuery e nella lezioncina di un’oretta cerco di affrontare la maggior parte dei temi che possono interessare chi si avvicina per la prima volta a questa libreria. Sul sito è disponibile una preview di 5 minuti (presa circa ad un terzo della lunghezza totale del video).

Voglio ringraziare thinkcode per l’opportunità offertami e spero davvero di poter collaborare ancora con loro :)

jQuery sta rapidamente diventando la libreria JavaScript più usata al mondo, per lo sviluppo di applicazioni web interattive e dinamiche. In questo screencast di poco più di un’ora, Claudio Cicali ci guida nell’apprendimento dei concetti di base, mostrando il come e il perché dell’uso della libreria, a partire dalla sua storia, per finire a parlare delle best practice, passando per la manipolazione del DOM, la gestione degli eventi e Ajax. Si tratta di uno screencast indispensabile per lo sviluppatore moderno.

jQuery vs document.getElementById

With the first post of the year, I’d like to present the results of a (very) simple and unreliable performance benchmark.

The question I would like to give an answer to was: giving the selector of an HTML ID, how much the document.getElementById is faster than the jQuery selection? Well – as it tourned out – it is astonishingly faster.

The test run over 100000 calls to the same minimal function and then collect the result in millisecond. For each test, 8 runs were made and the greatest and lowest value were dropped before the average time was computed. Every test was ran against Firefox 3.5.6, Firefox 3.6b5, Chrome 4, Safari 4, IE 8 and Opera 10.10.

“Why don’t run the test also against the soon to be released jQuery 1.4.0?”, I asked myself. So I did.

The test code itself goes along these lines:

function benchmark(f, result) {
  var start = new Date();
  f();
  var stop = new Date();
  document.getElementById(result).innerHTML = stop - start;
}

$("#start").click(function() {
    benchmark(function() {
      var e;
      for(n=0; n < 100000; n++) {
        e = $('#testID');
// or  e = document.getElementById('#testID');
      }
    }, "result");
    return false;
});

And here comes the whole picture:

What did I learn?

  • when possible, use the document.getElementById() native function (or a simple helper wrapper) instead of the jQuery method
  • IE and Firefox 3.5 are embarassingly slow
  • Chrome and Safari are embarassingly fast
  • Firefox 3.6 is gaining a lot of performance points, but still…
  • Opera 10.10 is good, but the gEBI performances are very bad
  • Chrome is loosing something with jQuery 1.4. Well, it seems so. I don’t think this is real.
  • The best performance gain with jQuery 1.4 would be for IE8

Remember that this test is extremely unreliable and of indicative quality only. Do not take any assumption for granted :)

ADDENDUM: as a follow up to a discussion on Friendfeed, I ran one more test. This time I’ve used a wrapper like this one:


function $getId(id) {
  $(document.getElementById(id));
}

$("#startWRAPPER").click(function() {
    benchmark(function() {
      var e;
      for(n=0; n < 100000; n++) {
        e = $getId('testID');
      }
    }, "result");
    return false;
});

When you need an ID, as a jQuery object, using the wrapper can certainly give you same benefits. The test has been ran with the latest jQuery 1.4 version.


Upload progressivo in PHP con APC e JavaScript – Parte 1

Prima parte (leggi la seconda parte, leggi la terza parte)

In questo articolo, suddiviso per motivi di lunghezza in più parti, cercherò di  spiegare il sistema tramite il quale sia possibile monitorare l’upload di un file in modo da visualizzare all’utente lo stato di avanzamento dell’operazione.

Questi articoli non sono vogliono essere un semplice how to, quando invece una dettagliata analisi delle problematiche inerenti a questo sistema diventato ormai di sempre più comune utilizzo sui siti web.

La complessità di tutto questo “giochino” è da imputare principalmente al linguaggio  server side che utilizzerò in questi articoli: il PHP.

Vediamo subito il perché.

A grandi linee, l’upload di un file dal browser al server funziona semplicemente così: l’utente seleziona il file dal proprio computer e poi invia la form. In quel momento il browser inizia una trasmissione dati con lo script che riceve i dati della form, inviandogli senza soluzione di continuità i byte che compongono il file in fase di trasmissione.

Lato server il PHP dal momento che inizia la ricezione del file, “appoggia” su un file temporaneo i dati che stanno arrivando finché la trasmissione non sarà terminata o cancellata. Nel secondo caso il PHP provvederà a cancellare il file temporaneo e tutto finisce lì. Nel caso di ricezione avvenuta, lo script riprenderà il controllo e sarà in grado di copiare il file temporaneo dove meglio crede (move_uploaded_file(), non dico certo niente di nuovo.)

Non esistono sistema “nativi” da parte del browser per capire quanti byte ha al momento trasmesso. È possibile utilizzare dei trucchetti lato client che prevedono l’utilizzo di un piccolo Flash movie che fa da “gateway” usando Flash stesso per aprire il socket di trasmissione dati verso il server. In tal caso sarà lo stesso Flash a fornire le indicazioni che ci interessano e la gestione è assai più semplice. Tuttavia l’approccio (usato in tantissime soluzioni di alto livello) non è scevro da problemi e in questa sede non ci interessa.

Senza usare Flash, dunque, quello che occorre fare è chiedere al server continuamente a che punto è arrivato leggendo il file temporaneo che sta crescendo man mano che la trasmissione procede.

Questa richiesta verrà fatta dunque via Ajax, chiedendo ad un altro script PHP lo stato di avanzamento del file xxxyyyzzz…

Sembra facile, ma non è.

Il problema nasce dal fatto, come dicevo poco fa, che stiamo usando PHP. Soltanto dalla versione 5.2 in poi è possibile infatti usare un sistema per chiedere al PHP a che punto è con l’upload. Prima, non esisteva modo… impossibile sapere il nome del file temporaneo da un altro processo, né tantomeno dal processo PHP che lo sta generando.

Dalla versione 5.2 è stato introdotto un “hook” che permette alle estensioni PECL del php di intercettare le fasi di upload di un file (no, non si può fare direttamente da PHP). Ovviamente non è che adesso ci mettiamo lì, con il nostro compilatore C a scrivere la nostra fantastica estensione che usa quell’hook. Questo lavoro, fortunatamente, è già stato fatto da qualcuno.

Credo che la maggior parte degli sviluppatori in PHP siano a conoscenza di APC. Il suo mestiere è duplice. In primis è un cosidetto sistema di “opcache”, ovvero permette al PHP di salvarsi i nostri script “precompilati” (passatemi il termine), in modo da velocizzarne le esecuzioni successive (stessa cosa di eAccelerator o xcache, se conoscete già queste alternative). In secundis, mette a disposizione agli script PHP un buffer di memoria ad accesso rapido, per salvare al suo interno delle informazioni magari lette da un sottostitema più lento (dbms, per esempio). È più o meno quello che fa memcache, solo che in questo caso non c’è bisogno di un servizio esterno che giri. APC infatti è un’estensione del PHP e come tale, una volta che questa sia stata compilata e caricata dal PHP, è disponibile da subito.

Fin qui – credo – nessuna grossa novità.

La cosa interessante è che, dalla versione PHP 5.2, APC implementa appunto la gestione di quel famoso “hook” per il monitoraggio dell’upload, offrendo un sistema ai normali script PHP per interrogare l’andamento della creazione del nostro file. Non solo: tramite il servizio di APC sarà così possibile controllare se il nostro file ha terminato il caricamento, se il caricamento è stato annullato dall’utente o da un problema di rete e fare dei semplici calcoli per sapere anche il “rate” di trasmissione in kbyte.

Nella seconda parte dell’articolo vedremo come fare ad implementare un sistema del genere, usando “solo” HTML, PHP e un po’ di sano JavaScript.

Nel frattempo, assicuratevi di avere a disposizione APC (perlomeno) sulla vostra macchina di sviluppo. In Ubuntu è questione di “sudo apt-get install php-apc” e far ripartire Apache. La configurazione, eventualmente, la troverete in
/etc/php5/apache2/conf.d/apc.ini


Quello che si impara da una linea di codice

Ieri ho avuto necessità di mettere il cursore sul primo campo di una form, automaticamente all’apertura della pagina. Il primo campo però che non contenesse la classe “hasDatepicker” (un widget di jQueryUI). Tagliando qui e là alla fine credo di aver risolto con una sola riga di codice che, aldilà del suo scopo, contiene diverse cosette che vorrei condividere. Il codice (che usa jQuery) è questo:

var fi;
(fi = $('form :input').not(".hasDatepicker")) && fi.length && fi[0].focus();

In italiano si legge così: prendi tutti gli elementi input della form, elimina quelli che hanno classe “hasDatepicker”. Dei risultanti (se esistono) prendi il primo e rendilo attivo.

(se hai in mente un modo per ottimizzare ancora, ti prego di leggere la nota alla fine del post)

Cosa possiamo rilevare, di interessante, da una sola righetta di codice?

  • Il one liner usa la tecnica del “corto circuito”, visto che JavaScript ce lo permette: un’espressione viene valutata da sinistra verso destra e l’elaborazione viene interrotta appena si raggiunge un valore che non può cambiare. In questo caso, la sequenza di “&&” fa sì che appena una delle tre espressioni è falsa, la valutazione viene interrotta (in questo caso quella che ci interessa in particolare è la seconda, che in pratica verifica se è stato trovato almeno un elemento).
  • La prima parte dell’espressione (l’assegnamento) deve essere racchiusa tra parentesi perché altrimenti non sarebbe sintatticamente valida. In questo modo invece si forza l’interprete a valutarla in maniera atomica, so to speak. Le parentesi come “aiutino” sintattico si trovano spesso, in JavaScript.
  • jQuery oltre ai selettori standard e quelli usabili anche tramite querySelectorAll, ne ha alcuni suoi molto comodi. Uno di questi è appunto “:input” che permette di selezionare tutti gli elementi input di una form ma anche select e textarea in un colpo solo.
  • Ottenuta una selezione di elementi (sempre assimilabile ad un array anche se la selezione è vuota, come si vede dalla seconda e terza parte dell’espressione), è possibile filtrare via degli elementi non voluti tramite il metodo “not”. Esiste anche il metodo controparte filter(), che permette di elminare gli elementi che NON hanno corrispondenza con il suo parametro/i.

Nota: probabilmente c’è un modo ancora più corto per fare questa operazione… la prima cosa che mi viene in mente è usare l’attribute selector, in modo da scrivere qualcosa come $(“form :input[class!=hasDatepicker]:first”). Quello che non mi piace molto, in questo contesto, è che l’operatore “!=” di quel selettore, ritorna true anche quando l’attributo “class” dell’elemento non è presente del tutto, per cui la selezione potrebbe essere “prendi il primo input della form che non ha una classe” che non è esattamente quello che volevo (dovrei fare delle prove, in effetti). Inoltre, probabilmente, questo articoletto non sarebbe mai nato ;)


Namespace anonimi in JavaScript

Questo brevissimo articolo potrebbe essere sicuramente un addendum ad un mio precedente articolo.

La tecnica dei “namespace anonimi” (il nome credo di averlo appena inventato e mi scuso se non fosse formalmente correttissimo) è utile nel caso si volesse aggiungere uno snippet di codice JavaScript all’interno di un template per fare una cosa molto specifica che non merita di essere inserita all’interno dei file JavaScript di tutta l’applicazione. Ne ho avuto bisogno recentemente quando ho dovuto far scomparire un campo di una form se il valore di una certa SELECT non fosse impostato. Avevo bisogno di una variable di appoggio, ma ovviamente non volevo che questa finisse nell’oggetto globale.

Senza indugiare oltre, ecco il codice (l’ho diviso in tre passi per chiarezza espositiva):

/* Passo 1.
   Definiamo una funzione anonima per creare un namespace;
   è necessario racchiudere la definizione all'interno di una coppia
   di parentesi, o il parser JavaScript darebbe errore */

(function() {
});

/* Passo 2.
   Inseriamo all'interno del nostro "namespace" il codice che ci
   interessa eseguire. Si noti che la variable $s in questo modo
   non è globale ma rimane chiusa nel namespace (che era quello
   che volevamo ottenere) */

(function() {
  var $s = $('#generatingActionId');
  if ($s.val() == '') {
    $('#generatingActionRef-label').hide();
  }
});

/* Passo 3.
   Infine "attiviamo" il nostro codice, eseguendo la funzione anonima;
   notare la coppia di parentesi direttamente alla fine della definizione
   della funzione */

(function() {
  var $s = $('#generatingActionId');
  if ($s.val() == '') {
    $('#generatingActionRef-label').hide();
  }
})();

I contenuti di questo sito sono distribuiti con una licenza Creative Commons 2.5 eccetto dove diversamente specificato.

Tema WordPress Punto5 sviluppato da Claudio Cicali; icone del set famfamfam silk e komodomedia.

© 2005-2010
Claudio Cicali