Archives pour la catégorie Web

HTML Media Capture : prenez des photos depuis un champ de formulaire

HTML Media Capture et l’attribut capture.
Mettez à profit les périphériques de votre mobile pour remplir les champ file

HTML5 apporte de nombreuses nouvelles fonctionnalités, notamment concernant les formulaires.

Nous allons voir dans ce billet la spécification HTML Media Capture.
Celle-ci permet d’élargir les capacités des champs de formulaires de type file.
Jusqu’à présent, les champs de formulaires de type file permettaient juste d’ouvrir une fenêtre pour récupérer dans le système de fichiers celui (ou ceux) à envoyer avec le formulaire.
Il est dorénavant possible d’utiliser ces mêmes champs pour utiliser l’un des périphériques de capture (audio, vidéo ou image) pour créer le fichier à envoyer.

Comment le mettre en Å“uvre ?
La mise en place d’un tel système est particulièrement simple.
Il suffit d’ajouter au champ un attribut capture et le tour est joué ! Cet attribut étant de type booléen, c’est-à-dire que sa seule présence (sans valeur ou quelle que soit sa valeur) suffit à indiquer au navigateur le comportement souhaité.

Enfin… il suffit… pas tant que ça en fait.
En réalité, l’attribut capture n’est pas suffisant, en effet, ce seul attribut ne permet pas de savoir quel type de media est demandé, donc quel périphérique utiliser.
Il est donc nécessaire de préciser aussi l’attribut accept avec une valeur correspondant au type mime souhaité.

Notez que l’attribut capture n’oblige pas l’utilisateur à utiliser un périphérique : il lui est demandé s’il veut envoyer un fichier existant ou s’il veut utiliser le périphérique approprié.

Exemples.
Voici les trois cas possibles d’utilisation à l’heure actuelle :

<form action="..." method="post" enctype="multipart/form-data">
    <!-- Pour une image (appareil photo) -->
    &lt;input type="file" name="image" accept="image/*" capture&gt;
    <!-- Pour une vidéo (caméra) -->
    &lt;input type="file" name="video" accept="video/*" capture&gt;
    <!-- Pour un son (micro) -->
    &lt;input type="file" name="son" accept="audio/*" capture&gt;
    &lt;input type="submit" value="Upload"&gt;
</form>

Compatibilité.
À l’heure actuelle, seuls les navigateurs pour mobiles et tablettes semblent supporter cette fonctionnalité.
Voir la table de compatibilité pour mobiles.
Mais gageons que les versions desktop des navigateurs vont l’implémenter rapidement.

Voir les spécifications du W3C (comprenant des exemples plus avancés).

Forcer le chargement d’un fichier en HTML5

Lorsque vous proposez une ressource aux visiteurs de votre site (images, documents PDF ou autres, etc.), les navigateurs vont essayer de les afficher via des fonctionnalités intégrées ou des extensions/plugins.
Or, si vous souhaitez juste proposer ces ressources au téléchargement, vous serez obligé de « forcer la main » au navigateur côté serveur :

En gros, la technique consiste à associer au fichier souhaité un en-tête HTTP Content-Disposition qui indiquera que celui-ci doit être téléchargé et non affiché.

Bien entendu, si votre page est uniquement en (X)HTML, vous êtes de la revue ! La seule technique possible est de transformer votre fichier dans un format qui ne peut être affiché par le navigateur (la technique la plus classique étant de le compresser en archive zip).

Mais cela, c’était avant.
Car désormais, HTML5 vous permet de rendre vos fichiers téléchargeables, quel que soit leur format, de façon très simple.

Il suffit d’utiliser l’attribut download.
Lire la suite

HTML5 : quelques nouveautés de l’API DOM pour JavaScript

La spécification HTML5 définit différents modules indépendants. Cette modularité a pour avantage de permettre de travailler sur certains aspects du standard sans avoir besoin de se soucier de l’état d’avancement des autres.
Parmi ces modules, l’API DOM est celui qui permet de définir les propriétés et méthodes disponibles en JavaScript pour manipuler le DOM.
Nous allons voir les différentes nouveautés particulièrement utiles de cette API.
Lire la suite

Personnalisez le menu contextuel avec Firefox

HTML5 redéfinit certains aspects et certaines balises du HTML.
Parmi les éléments qui retrouvent une nouvelle jeunesse figure la balise menu.
Bien sûr, évoquer cette balise ne présente que peu d’intérêt puisqu’elle n’est, à l’heure actuelle (et sauf erreur de ma part) reconnue par aucun navigateur…

Par aucun navigateur ? Vraiment ?

En fait, pas tout à fait : parmi les différentes utilisations de la balise menu, une est utilisable par Firefox depuis la version 8 : la personnalisation du menu contextuel lié à un élément de la page (ou de la page elle-même).

La syntaxe de la balise menu est la suivante :

<menu type="..." id="...">

où type correspond au comportement attendu pour le menu et id l’identifiant du menu.
Cette balise peut (dans le cadre du menu contextuel) contenir soit des sous-menus représentés par une nouvelle balise menu soit des éléments de menu représentés par des balises menuitem.

Bon, assez d’explications théoriques, passons à la pratique avec un exemple :

<menu type="context" id="developpez">
   
  <menu>
     
     
     
     
  </menu>
</menu>

Dans cet exemple (relativement simple), nous ajoutons des liens vers developpez.com et différents forums du site.
Vous pouvez constater que le type de menu est context pour préciser qu’il s’agit de personnaliser le menu contextuel.
D’autre part, le sous-menu et les éléments des menus possèdent des attributs label indiquant le texte à afficher correspondant à chaque option.
Les éléments de menus possèdent quant à eux des attributs icon (image apposée à côté de l’élément) et onclick (action JavaScript à lancer au clic sur cet élément).

Pour autant, vous aurez beau ajouter cette portion de code dans votre page et faire des clics droits partout dans la page (sur Firefox bien entendu) pour tester, rien ne se passera !
En fait, nous avons oublié l’essentiel : déterminer à quel élément de la page le menu contextuel est associé.
Pour préciser cela, il suffit d’ajouter un attribut contextmenu à l’élément souhaité. La valeur de cet attribut doit correspondre à l’identifiant (attribut id) du menu.
Dans l’exemple suivant, nous posons cet attribut sur la balise body afin que le menu contextuel s’applique sur toute la page :

  <title>Menu contextuel</title>
   
    html, body{
      height: 100%
    }
    h1{
      text-align: center;
    }
   
 
 
  <h1>Exemple de menu contextuel personnalisé</h1>
  <div>Faites un clic droit dans la page pour voir les options ajoutées au menu contextuel.</div>
<menu type="context" id="developpez">
   
  <menu>
     
     
     
     
  </menu>
</menu>

Notre exemple est maintenant fonctionnel. Vous pouvez voir un exemple en ligne.

Comprendre la balise script

S’il est bien une balise qui est souvent mal utilisée en HTML, c’est la balise <script>.
Nous allons essayer dans ce billet de faire le point sur cette balise en comprenant pourquoi.

  • La syntaxe

La syntaxe de base est relativement simple et ne pose pas de problème :
 
Il est toutefois important de noter que même si elle ne possède pas forcément de contenu, elle reste susceptible d’en avoir (le script en lui-même) ce qui fait que contrairement à une balise mais à l’instar d’une balise , elle n’est pas autofermante et doit posséder une balise fermante.

  • Les attributs

L’attribut src ne pose habituellement pas de gros soucis.
Cet attribut correspond à l’URL à laquelle se trouve le fichier correspondant. Attention toutefois, dans le cas d’une URL relative, de bien comprendre où se trouve le script en fonction de l’URL effective (celle affichée par le navigateur) qui appellera le script. Attention donc par exemple aux include en PHP.

En revanche, deux attributs sont assez souvent confondus, il s’agit des attributs language et type.
Il faut déjà savoir que le premier est deprecated depuis HTML 4 alors qu’au contraire, le second est required. Cela signifie qu’il faut bannir language.
La syntaxe correcte devient donc
 
Mais alors, si l’attribut language est à bannir, pourquoi le retrouve-t-on si souvent ?
D’abord, parce que malheureusement, plusieurs facteurs empêchent de l’éradiquer.
Déjà, de nombreux scripts usuels sont bien référencés et recopiés tels quels bien que très anciens. Du coup, l’attribut se propage facilement.
D’autre part, peut-être surtout, parce que beaucoup ignorent la signification de cet attribut.
A la base, il servait à indiquer le langage et la version du langage de script utilisé. Cependant, aucune norme n’a été trouvée pour savoir ce qu’il pouvait bien contenir, ce qui a donc amené à ce qu’il soit déprécié. De toute façon, le seul langage de script universellement reconnu par les navigateurs est JavaScript (quelle que soit sa déclinaison : ECMAScript, JScript, …) donc l’information n’a que peu d’intérêt. De même, préciser une version à utiliser n’a pas vraiment de sens : JavaScript, pour des raisons de rétro-compatibilté ne perd pas de fonctionnalités, il ne fait qu’en accepter de nouvelles !

Note : en HTML5, l’attribut type n’est plus requis et dans cette version, la syntaxe
 
est désormais suffisante.

  • Le contenu

Pendant longtemps (et on retrouve encore couramment la syntaxe), les scripts étaient entourés soit de commentaires HTML soit d’entités CDATA :

<!--
    // Code JavaScript
-->

Là encore, la pratique remonte à un temps que les moins de 20 ans (voire plus !) n’ont pas connue !
Ces syntaxes, héritées du XML, servaient à l’origine à éviter que les navigateurs ne possédant pas d’interpréteur JavaScript (on ne parle pas de ceux qui ont JavaScript désactivé, bien de ceux pour lesquels JavaScript n’existe tout simplement pas !) n’essayent d’interpréter le contenu du script comme du HTML. De mémoire, on parle là de IE3 et de NS3. Il me semble que la part de marché de ces navigateurs atteint depuis longtemps un seuil qui rend cette technique quelque peu obsolète !

  • Où placer les scripts ?

Plusieurs écoles s’affrontent à ce niveau.
Une chose est sure : il est demandé de séparer les différentes couches du document : le HTML pour le contenu, le CSS pour la mise en forme et le JavaScript pour l’ergonomie (ou le le comportement). Ainsi, insérer ses scripts en plein milieu du document est assez maladroit.
Pendant un temps, les bonnes pratiques recommandaient de placer les scripts entre les balises <head> et de les initialiser via l’événement onload de l’objet window.
Cette façon de procéder est plutôt satisfaisante mais l’événement onload implique que l’ensemble du contenu de la page soit chargé avant de lancer les scripts (donc y compris les éléments dits remplacés : images, iframes, object, etc.) et comme les pages Web deviennent de plus en plus gourmandes en ressources externes, cela fini par nuire à l’expérience utilisateur.
Différentes techniques existent pour pallier cela, entre autre, l’utilisation de l’événement DOMContentLoaded, mais qui n’est pas (encore) suffisamment universel pour être totalement satisfaisant.
La problématique est que pour pouvoir utiliser un script, il faut que les éléments du DOM qu’il va utiliser existent au moment où il est appelé. Une solution efficace est alors de placer les scripts juste avant la fermeture du document (avant la balise </body>), ce qui permet d’être sûr que les éléments du DOM ont été créés et de conserver la notion de séparation des couches.
Gardez toutefois à l’esprit que quelle que soit la solution choisie, elle aura une importance majeure lors de l’écriture de codes destinés à être réutilisés.

Comprendre document.write() en JavaScript

S’il est bien une méthode méconnue en JavaScript, c’est la méthode write() de l’objet document.

La syntaxe est pourtant simple :
document.write(arg1, arg2, ..., argn);
Les arguments attendus sont des chaînes de caractères (ou tout du moins des arguments possédant une méthode toString())
Vous noterez au passage que le nombre de paramètres que l’on peut passer à cette méthode est indéterminé.
L’instruction précédente aura pour effet d’ajouter la valeur de chaque paramètre dans la page.
Par exemple
document.write('toto', 12, [1,2,3]);
affichera :

toto121,2,3

Notez que chaque argument est ajouté à la suite du précédent sans insérer de séparateur.
Malgré tout, certaines valeurs affichent un résultat inattendu :
document.write(false, {toto: 'tata', foo: 'bar'});
affichera :

false[object Object]

c’est-à-dire qu’un booléen ne sera pas transformé en 0 ou 1 mais en false ou true et un objet affichera (en fonction du navigateur) [object Object].

Jusque là, rien de vraiment compliqué à comprendre, d’autant que l’on passe habituellement un seul paramètre correspondant à une chaîne à afficher.

Cependant, le comportement de cette méthode dépend de l’état du document au moment de son appel.
En effet, un document HTML peut avoir deux états distincts : ouvert ou fermé.
Lorsque le navigateur reçoit un contenu HTML à afficher, il commence par ouvrir un document (le flux) puis interprète le code HTML en affichant son contenu et en construisant le DOM et une fois l’intégralité du code interprété, il ferme le document.
Pendant que le document est ouvert, si le navigateur rencontre une instruction JavaScript write(), alors ses arguments sont insérés à l’emplacement de cette instruction dans le code.
C’est le comportement attendu de cette méthode.
Mais il faut savoir que document.write() a besoin que le document soit ouvert pour pouvoir fonctionner correctement. Que se passe-t-il alors si le document est fermé ?
Dans ce cas, JavaScript va appeler en interne l’instruction document.open() puis exécuter le write().
Or document.open() correspond à l’ouverture du flux d’affichage, ce qui signifie que l’appel à cette méthode va recréer un nouveau flux, en commençant par supprimer l’existant.
Pour vous en convaincre, ouvrez une console JavaScript (par exemple Firebug pour Firefox) et dans la ligne de commande, tapez l’instruction
document.open();
et vous constaterez que la page va devenir blanche. Au passage, vous noterez aussi que l’indicateur de chargement se met en place (à la place du favicon), ce qui est le cas lorsque le flux est ouvert.
De la même manière, si vous entrez
document.write('Hello world !');
dans la console, vous constaterez que l’ensemble du contenu a été remplacé par le message « Hello world ! ». Vous pourrez aussi vérifier que l’indicateur de chargement est toujours actif : le document n’a pas été refermé.
Si ensuite vous entrez l’instruction
document.close();
dans la console, l’indicateur de chargement disparaitra au profit du favicon par défaut.

La première impression que l’on pourrait avoir en comprenant ce fonctionnement serait de se dire qu’il faut effectivement faire attention au contexte avant d’utiliser cette méthode.
En fait, il faut surtout considérer write() comme une méthode à bannir.
Déjà, parce qu’une méthode dont on ne peut garantir le comportement n’est pas à recommander.
Ensuite, parce que les bonnes pratiques en développement Web préconisent de séparer les couches : HTML pour l’affichage, CSS pour la mise en forme et JavaScript pour le comportement : utiliser la méthode write() implique d’introduire au niveau de l’affichage du JavaScript qui n’a rien à y faire, surtout que pour manipuler le document, de nombreuses méthodes du DOM sont disponibles et beaucoup plus fiables.
On pourrait aussi évoquer le fait que l’utilisation de write() interdit l’accès aux informations à ceux qui, pour une raison quelconque, ont JavaScript désactivé. Mais surtout, son utilisation (et son existence) force les navigateurs à une pratique particulièrement désagréable et dommageable qui est le chargement des scripts de façon synchrone.
En effet, l’affichage de la page doit être garantit par le navigateur, or si un script possède une instruction write(), alors il est important de pouvoir prévoir de façon certaine à quel endroit du document ses paramètres seront affichés, c’est pour cela que les navigateurs bloquent l’interprétation de la page pendant le chargement et l’évaluation des scripts (à la différence des autres éléments de la page, comme les images ou les iframes) ce qui retarde d’autant l’affichage du reste du contenu.

Le « core » JavaScript s’enrichit de nouvelles méthodes.

C’est une information qui est, il me semble, passée relativement inaperçue mais qui est selon moi assez intéressante à souligner.
Le noyau JavaScript, qui était resté longtemps figé, s’est enrichi avec les dernières versions des navigateurs, de nouvelles méthodes bien utiles.

Pour rappel, le noyau JavaScript (aussi appelé core JavaScript), par opposition au DOM JavaScript (ou JavaScript côté client) regroupe les objets natifs de JavaScript et surtout, la partie censée être commune à toutes ses variations.
Il regroupe en particulier les objets natifs Array et String qui ont vu leur prototype amélioré.
Il est à noter que ces ajouts sont aussi disponibles (sauf mention contraire) dans Internet Explorer depuis la version 9.

  • L’objet Array

La méthode every()
Cette méthode permet d’appliquer à tous les membres du tableau une fonction de rappel afin de savoir si tous les éléments du tableau remplissent une condition.
Syntaxe
Array.every(callback, thisObjet);
Exemple

function isImpair(nb){
    return nb & 1;
}
alert([1,5,17,89].every(isImpair));
alert([1,5,17,89, 100].every(isImpair));

La méthode filter()

Comme son nom l’indique, cette méthode permet de filtrer les éléments d’un tableau selon le résultat renvoyé par une fonction de rappel.
Syntaxe
Array.filter(callback, thisObjet);
Exemple

function isInferieurADix(nb){
    return nb < 10;
}
alert([2,5,6,8,10,11].filter(isInferieurADix));

La méthode forEach()
Cette méthode permet d’appliquer un traitement à chaque élément du tableau.
Syntaxe
Array.forEach(callback, thisObjet);
Exemple

var tab = ['a','b','c','d','e'],
    resultat = '',
    i = 0;
function arrayToString(){
    resultat += 'Rang '+i+'\t\tvaleur : '+this[i]+'\n';
    i++;
}
tab.forEach(arrayToString, tab);
alert(resultat);

La méthode map()
La méthode map() va appliquer à chaque élément du tableau le traitement de la fonction de rappel.La méthode map()
Syntaxe
Array.map(callback, thisObjet);
Exemple

var tab = ['a','b','c','d','e'];
function double(val){
    return val + val;
}
alert(tab.map(double));

La méthode some()
Similaire à la méthode every(), cette méthode va vérifier si au moins un des éléments du tableau est valide selon le résultat renvoyé par la fonction de rappel.
Syntaxe
Array.some(callback, thisObjet);
Exemple

function isInferieurADix(nb){
    return nb < 10;
}
alert([10,20,30,40,50].some(isInferieurADix));
alert([5,10,20,30,40,50].some(isInferieurADix));
  • L’objet String

Ces méthodes renvoient la nouvelle chaîne mais ne modifient pas celle d’origine.

La méthode trim()
Supprime tous les caractères d’espacement en début et fin de chaîne.
Syntaxe
String.trim();
Exemple

var str = '\tTest ';
var strTrimmed = str.trim();
alert('!'+str+'!\n!'+strTrimmed+'!');

La méthode trimRight()
Supprime les espacements en fin de chaîne.
Syntaxe
String.trimRight();
Exemple

var str = '\tTest ';
var strTrimmed = str.trimRight();
alert('!'+str+'!\n!'+strTrimmed+'!');

La méthode trimLeft()
Supprime les espacements en début de chaîne.
Attention : étonnamment, cette méthode n’est pas (encore) disponible pour Internet Explorer et Opera…
Syntaxe
String.trimLeft();
Exemple

var str = '\tTest ';
var strTrimmed = str.trimLeft();
alert('!'+str+'!\n!'+strTrimmed+'!');

À noter aussi, pour l’objet Date, l’apparition de la méthode toISOString().

PHP Tour Lille 2011

Voilà enfin arrivé ce jour tant attendu (en tout cas par moi). Je suis donc prêt, bic et carnet en main, à prendre pleins de bonnes notes sur les différents aspects de PHP.

8h30, je suis sur le parking et avance vers le site de Euratecnologies de Lille. Déjà, rien que pour la réaffectation de ce bâtiment, le détour en valait la peine.

Après avoir récupéré mon badge et mon petit cadeau, un éléphant rose (ça va se chamailler à la maison), je me dirige vers l’auditoire pour la keynote présentée par Jean-Marc Fontaine de Alter Way.
La bienvenue nous est souhaitée et la présentation des deux jours nous est narrée, tout en nous présentant l’AFUP et en nous motivant pour ouvrir des antennes dans nos régions (peut-être une bonne idée à creuser là).

Le sujet de la première conférence à laquelle j’ai assisté est la présentation de PHP 5.4 par Julien Pauli, nous expliquant les grandes nouveautés, qui ne se trouvent pas forcément dans le langage, mais bien dans sa construction, avec la mise en place de RFC, permettant à chaque utilisateur d’émettre des changements dans le langage.
Un cycle de vie déterminé de 3 ans par mise à jour majeure et de 1 an pour une mise à jour mineure.
De plus une bonne nouvelle est que la descendance ne sera plus cassée dans les versions mineures.
Bien sûr, les nouveautés liées au langage nous sont présentées, mais cela n’est plus un secret et l’on trouve tout sur developpez.com.
Par contre, Julien nous annonce un gain de performance de l’ordre de 55% par rapport à PHP5.3, avec benchmark à la clé.
Julien nous a promis ses slides sur le site de l’AFUP très prochainement.

Ensuite, j’ai assisté à l’industrialisation du site lamaisondevalerie.fr , faisant partie du groupe Conforama, présentée par Sophie Beaupuis.
Ici expliquer en quelque mots serait difficile tant les infos étaient nombreuses, on a pu voir tout le panel d’outils utilisés pour le développement de son application (très orienté Zend avec la suite de produit complets).
Ce qui était agréable dans cette présentation est que madame Beaupuis s’est mouillée en nous expliquant les freins liés à son projet et a eu l’honnêteté de dire ‘désolée je ne connais pas’.

J’ai pris 5 minutes pour vous faire ces quelques lignes et je remercie Jean Marc Fontaine de m’avoir trouvé un petit Wifi.
Ce soir je vous poste la suite de cette première journée.
Un seul regret actuellement, est de ne pas avoir pris de CV avec moi, parce que les offres d’emploi ici sont palpables… Merci le réseautage !

Par MaitrePylos

Un classique AJAX : utiliser les données au bon moment !

S’il est une erreur classique chez les débutants en AJAX, que l’on retrouve régulièrement sur le forum AJAX, c’est de vouloir utiliser les données du serveur avant de les avoir reçues.

Faisons une petite analogie.
Imaginons que vous ayez une poule. Tous les matins, vous souhaitez savoir combien d’œufs ont été pondus, vous envoyez donc quelqu’un les compter.
J’imagine, qu’au moment même où cette personne part compter les Å“ufs, il ne vous viendrait pas à l’esprit de l’appeler pour lui demander le compte : la moindre des choses est d’attendre qu’elle soit revenue car avant, elle ne connait pas l’information !

Avec AJAX, c’est exactement pareil. Le premier A de l’acronyme signifie asynchronous (asynchrone), c’est-à-dire que JavaScript ne va pas attendre la réponse du serveur avant de continuer à exécuter le code, sauf bien entendu si vous avez spécifié le mode synchrone.
Ainsi, le seul moment où l’on est sûr d’avoir reçu la réponse est lorsque la propriété readyState de l’objet XMLHttpRequest vaut 4 et que la propriété status correspond à un code de réussite de la requête (classiquement 200). C’est pourquoi tous les traitements se basant sur la réponse du serveur doivent être traités dans le callback de la requête..

Avant d’écrire son code, il est donc fondamental de se demander si les données que l’on veut utiliser existent ou non.

A titre d’exemple, un petit code :

var xhr = new XMLHttpRequest(), monResultat;
xhr.open('POST', url);
xhr.onreadystatechange = function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        monResultat = xhr.responseText;
        alert(monResultat);
    }
};
xhr.send('variable=valeur');
alert(maVariable);

Ici, le premier alert() affiché sera celui de la dernière ligne : JavaScript n’attend pas la réponse du serveur pour continuer à exécuter le code et cette alerte affichera undefined, puisqu’au moment où cette instruction est interprétée, aucune affectation n’a encore été faite pour maVariable ! Puis, lorsque le serveur aura répondu, le second alert() sera affiché avec cette fois la valeur attendue.

Voir aussi :

Les fonctions de rappel (callback) ou les utilisations cachées de eval()

Il existe de nombreux cas en JavaScript qui nécessitent l’utilisation de fonctions de rappel (callback en anglais).
Une fonction de rappel est une fonction passée en paramètre d’une autre fonction. Pour JavaScript, c’est le cas par exemple de setTimeout(), setInterval() ou encore des fonctions appelées par un gestionnaire d’événement.

Cette notion de fonction de rappel est d’autant plus difficile à appréhender pour les débutants qu’il existe différentes façons distinctes de la définir, dont certaines erronées.

Les trois plus fréquentes sont les suivantes :

  1. document.onclick = maFonction();
  2. document.onclick = "maFonction()";
  3. document.onclick = maFonction;
  1. setTimeout(maFonction(), délai);
  2. setTimeout("maFonction()", délai);
  3. setTimeout(maFonction, délai);

Les exemples (1) sont tout simplement faux et ne produiront pas le résultat attendu. Ils sont un mélange entre les deux formes suivantes et dues à la confusion entre une fonction et le résultat de l’exécution de celle-ci.
Lorsque l’interpréteur JavaScript rencontre la notation maFonction() (donc avec les parenthèses), il comprend qu’il faut exécuter la fonction et le fait donc sur le champ. Or ce qu’attendent les méthodes nécessitant une fonction de rappel, c’est une référence à la fonction. Avec la notation des exemples (1), c’est le résultat de l’exécution qui sera affecté au clic ou au timer, sans attendre le moment souhaité par le développeur.
Les exemples (2) sont syntaxiquement corrects, mais fortement marqués d’obsolescence. En fait, dans ces cas ci, il n’y a pas de fonction de rappel de définie mais une portion de code qui sera évaluée au moment de l’appel. En interne, JavaScript va utiliser la méthode eval() pour interpréter le code, comme le montre l’exemple suivant :

function eval(){
    alert('eval() is evil !');
}
function toto(){
    alert('toto');
}
document.onclick = "toto()";

Dans cet exemple, c’est bien le message eval() is evil ! qui sera affiché. Cette façon de procéder, liée à la préhistoire de JavaScript, est fortement déconseillée !

Dans les exemples (3), c’est bien la référence à la fonction qui est utilisée De ce fait, lorsque le moment sera venu, cette fonction pourra être exécutée sans passer par l’utilisation de eval(), comme le montre l’exemple suivant :

function eval(){
    alert('eval() is evil !');
}
function toto(){
    alert('toto');
}
document.onclick = toto;

C’est bien le message toto qui est affiché lors du clic sur la page.

Note : si vous utilisez une console (par exemple celle de Firebug) pour tester les codes ci-dessus et que vous faites « Exécuter » deux fois de suite, vous obtiendrez le message eval() is evil, cela est dû au fait que l’injection du code dans le document utilise elle aussi des méthodes utilisant en interne eval() qui vient d’être redéfinie.

Mais alors, comment passer des paramètres à la fonction de rappel ?
Effectivement, le seul moyen de passer des paramètres à la fonction de rappel était celle des exemples (2), qui sont déconseillés.
Pour passer des paramètres, il va falloir utiliser une quatrième technique qui consiste à englober l’appel de la fonction de rappel dans une fonction anonyme. Cette fonction anonyme étant définie au moment de l’affectation, elle correspond donc à une référence à une fonction et non à une exécution de celle-ci :

function eval(){
    alert('eval() is evil !');
}
function toto(texte){
    alert(texte);
}
document.onclick = function(){
    toto('Paramètre !');
};

Ce code affiche bien le paramètre passé à la fonction toto, elle-même englobée dans une fonction anonyme.