Development

Documentation/fr_FR/book/1.0/trunk/11-Ajax-Integration

You must first sign up to be able to contribute.

Version 19 (modified by forresst, 9 years ago)
Suite de la traduction (et bientot la fin, une relecture s'impose)

Cette partie de la documentation est en cours de traduction. Cela signifie qu'elle est traduite de manière soit incomplète, soit inexacte. En attendant que cette traduction soit terminée, vous pouvez consulter la version en anglais pour des informations plus fiables.


Chapitre 11 - Intégration d'Ajax

Les interactions du côté client, la complexité des effets visuels et la communication asynchrone sont fréquents dans les applications Web 2.0. Tous exigent le JavaScript, mais le codage fait à la main est souvent lourd et long à déboguer. Heureusement, symfony automatise la plupart des cas utilisés en Javascript dans les templates grâce à un ensemble complet d'aides. Beaucoup de comportements côté client peuvent même être écrits sans une seule ligne de code JavaScript. Les développeurs doivent seulement se soucier de l'effet qu'ils veulent réaliser, et symfony traitera la syntaxe complexe et les problèmes de compatibilité.

Ce chapitre décrit les outils fournis par symfony pour faciliter le codage côté client:

  • Les aides en Javascript de base respectent les balises standard <script> dans les templates de symfony, pour mettre à jour un élément du modèle d'objet du document (DOM) ou déclencher un script via un lien.
  • Prototype est une bibliothèque Javascript intégré dans symfony, qui accélère le développement de script coté client en ajoutant de nouvelles fonctions et méthodes au noyau Javascript.
  • Les aides d'Ajax permettent à l'utilisateur de mettre à jour certaines parties d'une page en cliquant sur un lien, la soumission d'un formulaire, ou la modification d'un élément de formulaire.
  • Les nombreuses options de ces aides fournissent encore plus de flexibilité et de puissance, notamment en employant des fonctions de callback.
  • Script.aculo.us est une autre bibliothèque, aussi intégrée dans symfony, qui ajoute des effets visuels dynamiques pour améliorer l'interface et l'ergonomie.
  • JavaScript Object Notation (JSON) est un standard utilisé pour les communications entre un serveur et un client.
  • Les interactions complexes du coté client sont possibles dans des applications symfony en combinant tous les éléments mentionnés ci-dessus. Complètement automatique, glisser-déposer, liste triée, et texte éditable peuvent être implémenté avec une seule ligne de PHP : en appelant une aide de symfony.

Aides de base en Javascript

JavaScript a longtemps été considéré comme peu utile dans les applications web professionnelles, en raison du manque de compatibilité entre les navigateurs. Aujourd'hui, les problèmes de compatibilité sont résolus (pour la plupart), et certaines bibliothèques robustes vous permettent de programmer des interactions complexes en JavaScript, sans avoir besoin d'innombrables lignes de code et perdre des heures en déboguage. Le plus populaire s'appelle Ajax, qui est décrit dans la section «Aides Ajax» plus loin dans ce chapitre.

Paradoxalement, vous verrez très peu de code JavaScript dans ce chapitre. C'est parce que symfony a une approche originale pour écrire des scripts côté client: il englobe et résume des comportements en aides JavaScript, afin que vos templates finissent par ne plus faire apparaître aucune ligne de code JavaScript. Pour les développeurs, ajouter un comportement à un élément dans la page, prend une ligne de code PHP. Mais cette aide fait appel à du code Javascript en sortie et en inspectant les réponses produites, elle indiquera toute la complexité encapsulée. Les aides traitent de l'uniformité des navigateurs, des cas complexes de limite, de l'extensibilité, et ainsi de suite. Ainsi la quantité de code Javascript qu'elles contiennent, peut être très importante. Par conséquent, ce chapitre va vous apprendre comment ne pas utiliser JavaScript, pour réaliser des effets qui utiliseront du code JavaScript.

Toutes les aides décrites ci-dessus sont disponibles dans les templates, à condition que vous déclarer l'utilisation du groupe d'aide Javascript.

[php]
<?php use_helper('Javascript') ?>

Car vous apprendrez bientôt, que certaines de ces aides produisent du code HTML, et que certaines d'entre elles produisent du code Javascript.

JavaScript dans les templates

En XHTML, les blocs de code JavaScript doivent être englobés dans des déclarations CDATA. Mais cela peut devenir pénible d'écrire des pages exigeant une multitude de bloc de code Javascript. C'est pourquoi symfony fournit une aide javascript_tag(), qui transforme une chaîne de caractère en un XHTML compatible à la balise <script>. Le listing 11-1 montre utilisation de cette aide.

Listing 11-1 - Insérer du JavaScript avec l'aide javascript_tag()

[php]
<?php echo javascript_tag("
  function foobar()
  {
  ...
  }
") ?>
 => <script type="text/javascript">
    //<![CDATA[
      function foobar()
      {
        ...
      }
    //]]>
    </script>

Mais l'utilisation la plus fréquente de JavaScript, encore plus que les blocs de code, c'est dans un lien hypertexte qui déclenche un script particulier. L'aide link_to_function() fait exactement cela, comme le montre le listing 11-2.

Listing 11-2 - Déclencher du JavaScript par un lien avec l'aide link_to_function()

[php]
<?php echo link_to_function('Click me!', "alert('foobar')") ?>
 => <a href="#" onClick="alert('foobar'); return none;">Click me!</a>

Avec l'aide link_to(), vous pouvez ajouter des options à la balise <a> en les passant au troisième argument.

NOTE L'aide link_to() a une soeur button_to(), vous pouvez déclencher du JavaScript à partir d'un bouton (<input type="button">) par l'appel de l'aide button_to_function(). Et si vous préférez une image cliquable, appelez link_to_function(image_tag('myimage'), "alert('foobar')").

Modifier un élément du DOM

Une tâche commune dans les interfaces dynamiques est la mise à jour d'un élément dans la page. C'est quelque chose que vous écrivez habituellement comme indiqué dans le listing 11-3.

Listing 11-3 - Modifier un élément en JavaScript

[php]
<div id="indicator">Data processing beginning</div>
<?php echo javascript_tag("
  document.getElementById("indicator").innerHTML =
    "<strong>Data processing complete</strong>";
") ?>

Symfony fournit une aide qui produit le Javascript, et pas de HTML dans ce cas, et elle est nommée update_element_function(). Le listing 11-4 montre son utilisation.

Listing 11-4 - Modifier un élément en JavaScript avec l'aide update_element_function()

[php]
<div id="indicator">Data processing beginning</div>
<?php echo javascript_tag(
  update_element_function('indicator', array(
    'content'  => "<strong>Data processing complete</strong>",
  ))
) ?>

On pourrait se demander pourquoi cette aide est particulièrement utile, car il est au moins aussi longue que le code JavaScript. C'est vraiment une question de lisibilité. Par exemple, vous pourriez avoir besoin d'insérer du contenu avant ou après un élément, supprimer un élément au lieu de le mettre simplement à jour, ou même ne rien faire en fonction d'un certain état. Dans de tels cas, le code JavaScript devient quelque peu illisible, mais l'aide update_element_function() conserve la lisibilité du template, comme vous pouvez le voir dans le Listing 11-5.

Listing 11-5 - Options de l'aide update_element_function()

[php]
// Insérer du contenu juste après l'élément 'indicator'
update_element_function('indicator', array(
  'position' => 'after',
  'content'  => "<strong>Data processing complete</strong>",
));

// Enlever l'élément avant 'indicator', et seulement si $condition est vraie
update_element_function('indicator', array(
  'action'   => $condition ? 'remove' : 'empty',
  'position' => 'before',
))

Les aides de vos templates rendent plus facile à comprendre n'importe quel code JavaScript, et vous avez une syntaxe unique pour les mêmes comportements. C'est aussi la raison pour laquelle l'aide a un nom si long: il fait le code auto-suffisant, sans qu'on est besoin de commentaires supplémentaires.

Fonctionnement en mode dégradé

La balise <noscript> vous permet de spécifier du code HTML à afficher pour les navigateurs qui ne supporte pas le JavaScript. Symfony le fait avec une aide qui fonctionne dans l'autre sens: il qualifie certaines parties de code de telle sorte que seuls les navigateurs supportant réellement JavaScript l'exécutent. Les aides if_javascript() et end_if_javascript() facilite la création d'applications qui fonctionnent en mode dégradé, comme le montre le Listing 11-6.

Listing 11-6 - Utiliser l'aide if_javascript() pour fonctionner en mode dégradé

[php]
<?php if_javascript(); ?>
  <p>You have JavaScript enabled.</p>
<?php end_if_javascript(); ?>

<noscript>
  <p>You don't have JavaScript enabled.</p>
</noscript>

NOTE Vous n'avez pas besoin d'inclure echo quand vous appelez les aides if_javascript () et end_if_javascript().

Prototype

Prototype est une grande bibliothèque JavaScript qui étend les possibilités du langage de script coté client, elle ajoute les fonctions absentes dont vous avez toujours rêvé, et offre de nouveaux mécanismes pour manipuler le DOM. Le site Web est http://prototypejs.org/.

Les fichiers Prototype sont inclus dans le framework symfony et sont accessibles dans chaque nouveau projet symfony: dans web/sf/prototype/. Cela signifie que vous pouvez utiliser Prototype en ajoutant le code suivant à votre action:

[php]
$prototypeDir = sfConfig::get('sf_prototype_web_dir');
$this->getResponse()->addJavascript($prototypeDir.'/js/prototype');

ou en l'ajoutant dans le fichier view.yml:

all:
  javascripts: [%SF_PROTOTYPE_WEB_DIR%/js/prototype]

NOTE L'aide Ajax de symfony, décrite dans la section suivante, doit pouvoir compter sur Prototype. La bibliothèque Prototype est déjà inclus automatiquement dès que vous utilisez l'une d'entre elles. Cela signifie que vous n'aurez pas à ajouter manuellement le JavaScript Prototype pour votre réponse si votre template appelle une aide _remote.

Une fois la bibliothèque Prototype chargée, vous pouvez profiter de toutes les nouvelles fonctions qui sont ajoutées au noyau de JavaScript. Ce livre n'a pas pour but de toutes les décrire, mais vous trouverez facilement une bonne documentation de Prototype sur le Web, y compris sur les sites Web suivants:

Une des fonctions de Prototype ajoutée à JavaScript est la fonction dollar : $(). En principe, cette fonction est un simple raccourci pour document.getElementById(), mais en plus puissant. Voir le listing 11-7 pour un exemple de son utilisation.

Listing 11-7 - Utiliser la fonction $() pour récupérer un élément par son ID en JavaScript

[php]
node = $('elementID');

// Signifie la même chose que
node = document.getElementById('elementID');

// Il peut également récupérer plus d'un élément à la fois
// Et dans ce cas le résultat est un tableau d'élément du DOM
nodes = $('firstDiv', 'secondDiv');

Prototype fournit aussi une fonction JavaScript qui manquait vraiment: elle renvoie un tableau de tous les éléments du DOM dont la classe est passée en argument:

[php]
nodes = document.getElementByClassName('myclass');

Toutefois, vous aurez rarement à l'utiliser, car Prototype donne une fonction encore plus puissante appelée le double dollar: $$(). Cette fonction retourne un tableau des éléments du DOM basée sur un sélecteur du CSS. Donc, l'appel précédent peut aussi être écrit comme suit:

[php]
nodes = $$('.myclass');

Grâce à la puissance des sélecteurs CSS, vous pouvez analyser le DOM par classe, par ID, par le parent et l'enfant, par le précédent et le suivant. Encore plus facilement que si vous le faisiez avec une expression XPath. Vous pouvez même accéder à des éléments avec une combinaison complexe de sélecteur:

[php]
nodes = $$('body div#main ul li.last img > span.legend');

Un dernier exemple améliorant la syntaxe fourni par Prototype est l'itérateur de chaque tableau. Il offre la même concision que dans PHP, avec la possibilité de définir des fonctions anonymes et des fermetures en JavaScript. Vous devrez probablement l'utiliser si vous avez beaucoup de code JavaScript écrits à la main.

[php]
var vegetables = ['Carrots', 'Lettuce', 'Garlic'];
vegetables.each(function(food) { alert('I love ' + food); });

Parce que la programmation en JavaScript avec Prototype est beaucoup plus agréable que de le faire à la main. Parce que cela fait aussi partie de symfony, vous devriez vraiment passer quelques minutes pour lire la documentation concernant Prototype.

Aides Ajax

Que faire si vous vouliez mettre à jour un élément de la page, pas avec du JavaScript comme dans le Listing 11-5, mais avec un script PHP exécuté par le serveur? Cela vous donnerez la possibilité de changer de page en fonction d'une réponse du serveur. L'aide remote_function() fait exactement cela, comme le montre le Listing 11-8.

Listing 11-8 - Utiliser l'aide remote_function()

[php]
<div id="myzone"></div>
<?php echo javascript_tag(
  remote_function(array(
    'update'  => 'myzone',
    'url'     => 'mymodule/myaction',
  ))
) ?>

NOTE Le paramètre url peut contenir une URL interne (module/action?key1=value1&...) ou une règle de routage, exactement comme dans url_for().

En cas d'appel, ce script mettra à jour l'élément de l'id myzone avec la réponse ou la demande de l'action mymodule/myaction. Ce type d'interaction est appelée Ajax, et c'est le coeur d'une applications Web hautement interactive . Voici comment Wikipedia (http://en.wikipedia.org/wiki/AJAX) le décrit:

Ajax rend les pages Web plus sensibles pour répondre par l'échange de petites quantités de données avec le serveur dans les coulisses, afin que l'ensemble de la page Web n'ai pas besoin d'être rechargées à chaque fois que l'utilisateur fait une modification. Cette initiative vise à accroître l'intéractivité de la page Web, la rapidité et la convivialité.

Ajax s'appuie sur XMLHttpRequest, un objet JavaScript qui se comporte comme une frame cachée, que vous pouvez mettre à jour à partir d'un serveur de requête et réutiliser pour manipuler le reste de votre page web. Cet objet est de bas niveau, et les différents navigateurs l'utilise de différente façon, ainsi l'utilisation manuel des requêtes Ajax signifie généralement de longues portions d'écriture de code. Heureusement, Prototype encapsule tout le code nécessaire pour faire face à Ajax et fournit un simple objet Ajax. Et symfony s'appuie sur cet objet. C'est pourquoi la bibliothèque Prototype est automatiquement chargée lorsque vous utilisez une aide d'Ajax dans un template.

CAUTION L'aide d'Ajax ne fonctionnera pas si l'URL de l'action à distance n'appartient pas au même domaine que la page en cours. Cette restriction existe pour des raisons de sécurité, et s'appuie sur les limites des navigateurs, qui ne peuvent pas être contournées.

Une interaction Ajax est composée de trois parties: un appel (un lien, un bouton, un formulaire, une horloge, ou tout contrôle que l'utilisateur manipule pour lancer l'action), un serveur d'action, et une zone de la page pour afficher la réponse de l'action. Vous pouvez créer des interactions plus complexes si l'action à distance retourne les données qui seront traitées par une fonction Javascript du côté client. Symfony fournit de multiples aides pour insérer des interactions Ajax dans vos templates, elles contiennent toutes le mot remote dans leur nom. Elles partagent également une syntaxe - un tableau associatif avec tous les paramètres de l'Ajax à l'intérieur de celui-ci. Soyez conscient que les aides Ajax retourne du code HTML en sortie, et non du JavaScript.

SIDEBAR Qu'en est-il des actions Ajax?

Les actions, appelées comme des fonctions à distance, sont des actions ordinaires. Elles suivent le routage, peuvent déterminer la vue pour rendre la réponse à return, passer des variables au template, et changer le modèle tout comme les autres actions.

Cependant, lorsque cela est demandé par le biais d'Ajax, les actions retourne true à la suite de l'appel:

[php]
$isAjax = $this->getRequest()->isXmlHttpRequest();

Symfony sait que l'action est dans un contexte Ajax et peut adapter la réponse du traitement en conséquence. Par conséquent, par défaut, les actions Ajax n'incluent pas la barre d'outils du debug web dans l'environnement de développement. Ainsi, elles évitent le processus de décoration (leur template n'est pas inclus dans la mise en page par défaut). Si vous voulez qu'une vue Ajax soit décoré, vous devez spécifier explicitement has_layout: true pour cette vue dans le module du fichier view.yml.

Une dernière chose: étant donné que la réactivité est essentielle dans les interactions Ajax, si la réponse n'est pas trop complexe, ce serait peut-être une bonne idée d'éviter de créer une vue et retourner la réponse directement à l'action. Donc, vous pouvez utiliser la méthode renderText() dans l'action pour sauter le template et accélérer la requête Ajax.

Un lien Ajax

Les liens Ajax forment une grande part des interactions Ajax disponibles dans les applications Web de 2.0. L'aide link_to_remote() génère un lien qui appelle, sans surprise, une fonction à distance. La syntaxe est très proche de celle de link_to() (sauf que le second paramètre est le tableau associatif des options Ajax), comme illustré dans le listing 11-9.

Listing 11-9 - Un lien Ajax avec l'aide link_to_remote()

[php]
<div id="feedback"></div>
<?php echo link_to_remote('Delete this post', array(
    'update' => 'feedback',
    'url'    => 'post/delete?id='.$post->getId(),
)) ?>

Dans cet exemple, en cliquant sur le lien 'Delete this post', ceci lancera un appel à l'action post/delete en tâche de fond. La réponse renvoyée par le serveur apparaît dans l'élément dont l'id est feedback. Ce processus est illustré dans la Figure 11-1.

Figure 11-1 - Pour déclencher une mise à jour à distance avec un lien hypertexte

Pour déclencher une mise à jour à distance avec un lien hypertexte

Pour un lien, vous pouvez utiliser une image au lieu d'une chaîne de caractère : utilisez une règle de nommage à la place d'une URL interne module/action, et ajouter des options à la balise <a> dans un troisième argument, comme illustré dans le listing 11-10.

Listing 11-10 - Les options de l'aide link_to_remote()

[php]
<div id="emails"></div>
<?php echo link_to_remote(image_tag('refresh'), array(
    'update' => 'emails',
    'url'    => '@list_emails',
), array(
    'class'  => 'ajax_link',
)) ?>

Les formulaires Web appelle typiquement une autre action, ceci à pour conséquence de rafraîchir toute la page. La correspondance de link_to_function() pour un formulaire serait que la soumission du formulaire fasse la mise à jour seulement d'un élément dans la page avec la réponse de serveur. C'est ce que fait l'aide form_remote_tag() : ça syntaxe est décrites dans le listing 11-11.

Listing 11-11 - Formulaire Ajax avec l'aide form_remote_tag()

[php]
<div id="item_list"></div>
<?php echo form_remote_tag(array(
    'update'   => 'item_list',
    'url'      => 'item/add',
)) ?>
  <label for="item">Item:</label>
  <?php echo input_tag('item') ?>
  <?php echo submit_tag('Add') ?>
</form>

L'aide form_remote_tag() ouvre <form>, de la même manière que l'aide form_tag(). La soumission de ce formulaire émet une requête POST à l'action item/add en arrière-plan, avec le champ item comme un paramètre de la requête. La réponse va remplacer le contenu de l'élément item_list, comme illustré dans la Figure 11-2, puis ferme le formulaire Ajax avec la balise fermante </form>.

Figure 11-2 - Déclenchement d'une mise à jour d'un formulaire à distance

Déclenchement d'une mise à jour d'un formulaire à distance

CAUTION Les formulaires Ajax ne peuvent être 'multipart'. Il s'agit d'une limitation de l'objet XMLHttpRequest. Cela signifie que vous ne pouvez pas gérer le téléchargement de fichier via un formulaire Ajax. Il y a des contournements, par exemple, en utilisant une iframe cachée au lieu d'un XMLHttpRequest.

Si vous voulez autoriser un formulaire pour travailler à la fois en mode page et en mode Ajax, la meilleure solution est de le définir comme une formulaire standard, mais de fournir, en plus du bouton de soumission, un second bouton (<input type="button" />) pour soumettre le formulaire dans Ajax. Symfony appelle ce bouton par submit_to_remote(). Cela vous aidera à construire des intéractions Ajax avec un mode dégradé. Voir un exemple dans le listing 11-12.

Listing 11-12 - Un formulaire avec une soumission standard et Ajax

[php]
<div id="item_list"></div>
<?php echo form_tag('@item_add_regular') ?>
  <label for="item">Item:</label>
  <?php echo input_tag('item') ?>
  <?php if_javascript(); ?>
    <?php echo submit_to_remote('ajax_submit', 'Add in Ajax', array(
        'update'   => 'item_list',
        'url'      => '@item_add',
    )) ?>
  <?php end_if_javascript(); ?>
  <noscript>
    <?php echo submit_tag('Add') ?>
  </noscript>
</form>

Un autre exemple qui utilise la combinaison de balises à distance et standard, c'est l'édition d'un article. Il permet d'offrir un bouton de prévisualisation en Ajax et un bouton de publication qui utilise une soumission standard.

NOTE Quand l'utilisateur appuie sur la touche Entrée, le formulaire est soumis en utilisant l'action définie dans la balise principale <form>. Dans l'exemple, c'est action standard qui est utilisée.

Les formulaires modernes peuvent réagir lors de la soumission, mais également lorsque la valeur d'un champ est mise à jour par un utilisateur. Dans symfony, vous utilisez l'aide observe_field() pour faire cela. Le listing 11-13 montre un exemple d'utilisation de cette aide pour faire une suggestion: chaque caractère saisie dans un champ item déclenche un appel ajax qui met à jour l'élément item_suggestion dans la page.

Listing 11-13 - Appeler un fonction à distance quand la valeur d'un champ change avec observe_field()

[php]
<?php echo form_tag('@item_add_regular') ?>
  <label for="item">Item:</label>
  <?php echo input_tag('item') ?>
  <div id="item_suggestion"></div>
  <?php echo observe_field('item', array(
      'update'   => 'item_suggestion',
      'url'      => '@item_being_typed',
  )) ?>
  <?php echo submit_tag('Add') ?>
</form>

Le module/action écrit dans la règle @item_being_typed sera appelé à chaque fois que l'utilisateur changera la valeur dans le champ observé (item), même si la soumission du formulaire n'est pas faite. L'action sera capable de recevoir la valeur actuelle de 'item' par le paramètre 'value' de la requête. Si vous voulez passer quelque chose d'autre que la valeur du champ observé, vous pouvez le spécifier comme une expression JavaScript dans le paramètre 'with'. Par exemple, si vous voulez que l'action reçoive un paramètre 'param', écrivez l'aide observe_field() comme montré dans le listing 11-14.

Listing 11-14 - Passer vos propres paramètres à une action à distance avec l'option with

[php]
<?php echo observe_field('item', array(
    'update'   => 'item_suggestion',
    'url'      => '@item_being_typed',
    'with'     => "'param=' + value",
)) ?>

Notez que cette aide ne produit pas un élément HTML, mais plutôt un comportement pour l'élément passé en paramètre. Vous verrez plus d'exemples d'aides JavaScript allouant des comportements plus loin dans ce chapitre.

Si vous voulez observer tous les champs d'un formulaire, vous devriez utiliser l'aide observe_form(), qui appelle une fonction à distance chaque fois qu'un des champs du formulaire est modifié.

Appeler périodiquement une fonction à distance

Dernière mais pas des moindres, l'aide periodically_call_remote() est une intéraction Ajax déclenchée toutes les deux ou trois secondes. Elle n'est pas attachée à un contrôle HTML, mais s'exécute de façon transparente en arrière-plan, comme un comportement de toute la page. Cela peut être utile pour pister la position de la souris, l'auto sauvegarde d'un contenu d'une grande région de texte, etc. Le listing 11-15 montre un exemple d'utilisation de cette aide.

Listing 11-15 - Appeler périodiquement une fonction à distance avec periodically_call_remote()

[php]
<div id="notification"></div>
<?php echo periodically_call_remote(array(
    'frequency' => 60,
    'update'    => 'notification',
    'url'       => '@watch',
    'with'      => "'param=' + \$F('mycontent')",
)) ?>

Si vous ne précisez pas le nombre de secondes (frequency) pour attendre entre deux appels de la fonction distante, la valeur implicite de 10 secondes est utilisée. Notez que le paramètre with est évalué en JavaScript, donc vous pouvez y utiliser des fonctions de Prototype, comme la fonction $F().

Paramètres d'appel à distance

Tous les aides Ajax décrites dans les sections précédentes peuvent prendre d'autres paramètres, en plus des paramètres update et url. Le tableau associatif des paramètres Ajax peut changer et ajuster le comportement des appels à distance et le traitement de leur réponse.

Mettre à jour des éléments distincts selon le statut de la réponse

Si l'action à distance échoue, les aides à distance peuvent vouloir actualiser un autre élément que celui actualisé lors d'une réponse réussie. Pour ce faire, il suffit de remplacer la valeur du paramètre update en un tableau associatif, et de fixer des valeurs différentes de l'élément à mettre à jour en cas de success et failure. C'est utile si, par exemple, il y a beaucoup d'interactions Ajax dans une page et une zone de feed-back d'erreur. Le listing 11-16 démontre la manipulation d'une mise à jour conditionnelle.

Listing 11-16 - Manipuler une mise à jour conditionnelle

[php]
<div id="error"></div>
<div id="feedback"></div>
<p>Hello, World!</p>
<?php echo link_to_remote('Delete this post', array(
    'update'   => array('success' => 'feedback', 'failure' => 'error'),
    'url'      => 'post/delete?id='.$post->getId(),
)) ?>

TIP Seuls les codes erreur HTTP (500, 404 et tous les codes non compris dans la tranche 2XX) déclencheront la mise à jour en échec, pas les actions retournant sfView::ERROR. Ainsi si vous voulez faire une action qui rende un échec Ajax, il doit être appelé par $this->getResponse()->setStatusCode(404) ou semblable.

Actualiser un élément selon la position

Aussi avec l'aide update_element_function(), vous pouvez spécifier l'élément à actualiser par rapport à un élément spécifique en ajoutant un paramètre position. Le listing 11-17 montre un exemple.

Listing 11-17 - Utiliser le paramètre position pour changer le lieu de la réponse

[php]
<div id="feedback"></div>
<p>Hello, World!</p>
<?php echo link_to_remote('Delete this post', array(
    'update'   => 'feedback',
    'url'      => 'post/delete?id='.$post->getId(),
    'position' => 'after',
)) ?>

Cela insérera la réponse de l'appel Ajax après l'élément feedback; c'est-à-dire entre le <div> et le <p>. Avec cette méthode, vous pouvez faire plusieurs appels Ajax et voir les réponses s'accumuler après l'élément 'update'.

Le paramètre position peut prendre les valeurs suivantes:

  • before: Avant l'élément
  • after: Après l'élément
  • top: Au début du contenu de l'élément
  • bottom: A la fin du contenu de l'élément

Actualiser un élément selon la condition

Un appel distant peut prendre un paramètre supplémentaire pour permettre la confirmation par l'utilisateur avant de soumettre vraiment le XMLHttpRequest, comme montré dans le listing 11-18.

Listing 11-18 - Utiliser le paramètre confirm pour demander une confirmation avant d'appeler la fonction à distance

[php]
<div id="feedback"></div>
<?php echo link_to_remote('Delete this post', array(
    'update'   => 'feedback',
    'url'      => 'post/delete?id='.$post->getId(),
    'confirm'  => 'Are you sure?',
)) ?>

Une boîte de dialogue JavaScript "êtes-vous sûrs ?" s'affichera quand l'utilisateur cliquera sur le lien et appellera l'action post/delete seulement si l'utilisateur confirme son choix en cliquant OK.

L'appel à distance peut aussi être conditionné par un test exécutée du côté du navigateur (en JavaScript), si vous précisez le paramètre condition, comme montré dans le listing 11-19.

Listing 11-19 - Appel conditionnel d'une fonction à distance selon le test effectué coté client

[php]
<div id="feedback"></div>
<?php echo link_to_remote('Delete this post', array(
    'update'    => 'feedback',
    'url'       => 'post/delete?id='.$post->getId(),
    'condition' => "$('elementID') == true",
)) ?>

Déterminer la méthode de la requête Ajax

Par défaut, les requêtes Ajax sont faites avec la méthode POST. Si vous voulez faire un appel Ajax qui ne modifie pas de données, ou si vous voulez afficher un formulaire qui a la validation intégrée comme le résultat d'un appel Ajax, vous pourriez avoir à changer la méthode de la requête Ajax vers GET. L'option method change la méthode de la requête Ajax, comme montré dans le Listing 11-20.

Listing 11-20 - Changer la méthode de la requête Ajax

[php]
<div id="feedback"></div>
<?php echo link_to_remote('Delete this post', array(
    'update'    => 'feedback',
    'url'       => 'post/delete?id='.$post->getId(),
    'method'    => 'get',
)) ?>

Autoriser l'exécution d'un script

Si le code de la réponse de l'appel Ajax (le code envoyé par le serveur, inséré dans l'élément update) contient du JavaScript, vous pourriez être surpris de voir que ces scripts ne sont pas exécutés par défaut. Cela doit permettre de réduire les risques d'attaque à distance et permettre l'exécution de script seulement quand le développeur sait à coup sûr quel est le code dans la réponse.

C'est pour cela que vous devez déclarer explicitement l'option script, afin que l'exécution des scripts soit accepté pour des réponses à distance. Le listing 11-21 donne un exemple d'un appel Ajax qui déclare que le JavaScript de la réponse à distance peut être exécuté.

Listing 11-21 - Autoriser l'exécution d'un script dans une réponse Ajax

[php]
<div id="feedback"></div>
<?php
  // If the response of the post/delete action contains JavaScript,
  // allow it to be executed by the browser
  echo link_to_remote('Delete this post', array(
    'update' => 'feedback',
    'url'    => 'post/delete?id='.$post->getId(),
    'script' => true,
)) ?>

Si le template distant contient une aide Ajax (comme remote_function()), il faut être conscient que les fonctions PHP génèrent du code JavaScript, et elles ne s'exécuteront pas à moins que vous rajoutiez l'option 'script' => true.

NOTE Même si vous permettez l'exécution de script pour la réponse à distance, et si vous utilisez un outil pour vérifier le code généré, vous ne verrez pas vraiment les scripts dans le code distant. Les scripts s'exécuteront, mais n'apparaîtront pas dans le code. Bien que particulier, ce comportement est tout à fait normale.

Créer une fonction de rappel (Callbacks)

Un inconvénient important des interactions Ajax, c'est qu'elles sont invisibles à l'utilisateur jusqu'à ce que la zone de mise à jour soit effectivement mis à jour. Cela signifie que, dans les cas d'un réseau lent ou d'un plantage du serveur, les utilisateurs pensent que leur action a été prise en compte, mais en fait, elle n'a pas été traitée. C'est pourquoi il est important d'informer l'utilisateur des événements d'une interaction Ajax.

Par défaut, chaque demande à distance est dans un processus asynchrone au cours duquel diverses fonction de rappel JavaScript (callbacks) peuvent être déclenchées (par des indicateurs de progrèssion et autres). Tous les callbacks ont accès à l'objet request, qui détiennent eux même XMLHttpRequest. Les callbacks correspondent aux événements de toute interaction Ajax:

  • before: Avant que la requête soit initialisée
  • after: Immédiatement après que la requête soit initialisée et avant le chargement
  • loading: Quand la réponse à distance est en train d'être chargée par le navigateur
  • loaded: Quand le navigateur a fini le chargement de la réponse à distance
  • interactive: Quand l'utilisateur peut interagir avec la réponse distancee, même si le chargement n'est pas fini
  • success: Quand XMLHttpRequest est fini, et que le code du statut HTTP est dans la tranche 2XX
  • failure: Quand XMLHttpRequest est fini, et que le code du statut HTTP n'est dans la tranche 2XX
  • 404: Quand la requête retourne le statut 404
  • complete: Quand XMLHttpRequest est fini (lancé après success ou failure, s'ils sont présents)

Par exemple, il est très commun de montrer un indicateur de chargement quand un appel à distance est lancé et le cacher dès que la réponse est reçue. Pour l'accomplir, ajoutez simplement les paramètres loading et complete à l'appel Ajax, comme montré dans le listing 11-22.

Listing 11-22 - Utiliser des Callbacks Ajax pour afficher et cacher un indicateur de progression

[php]
<div id="feedback"></div>
<div id="indicator">Loading...</div>
<?php echo link_to_remote('Delete this post', array(
    'update'   => 'feedback',
    'url'      => 'post/delete?id='.$post->getId(),
    'loading'  => "Element.show('indicator')",
    'complete' => "Element.hide('indicator')",
)) ?>

Les méthodes show et hide, ainsi que l'élément objet Javascript, sont des additions utiles de Prototype.

Créer des effets visuels

Symfony intègre les effets visuels de la bibliothèque script.aculo.us, pour vous permettre de faire plus de chose que d'afficher et cacher les éléments <div> dans vos pages Web. Vous trouverez une bonne documentation sur la syntaxe des effets dans le wiki http://script.aculo.us/. Fondamentalement, la bibliothèque prévoit des objets JavaScript et des fonctions qui manipulent le DOM afin de réaliser des effets visuels complexes. Voir quelques exemples dans le Listing 11-23. Le résultat est une animation visuelle de certaines zones dans une page Web, il est recommandé que vous testiez vous même les effets afin comprendre ce qu'ils font réellement. Le site Script.aculo.us offre une galerie qui vous permet de vous donner une idée des effets dynamiques.

Listing 11-23 - Effets visuels en JavaScript avec Script.aculo.us

[php]
// Highlights the element 'my_field'
Effect.Highlight('my_field', { startcolor:'#ff99ff', endcolor:'#999999' })

// Blinds down an element
Effect.BlindDown('id_of_element');

// Fades away an element
Effect.Fade('id_of_element', { transition: Effect.Transitions.wobble })

Symfony encapsule l'object JavaScript Effect dans une aide appelée visual_effect(), qui fait aussi partie du groupe d'aide Javascript. Elle produit en sortie du JavaScript qui peut être utiliser dans un lien standard, comme démontré dans le listing 11-24.

Listing 11-24 - Effets visuels dans les templates avec l'aide visual_effect()

[php]
<div id="secret_div" style="display:none">I was here all along!</div>
<?php echo link_to_function(
  'Show the secret div',
  visual_effect('appear', 'secret_div')
) ?>
// Will make a call to Effect.Appear('secret_div')

L'aide visual_effects() peut être aussi utilisée dans les callbacks Ajax, comme dans le listing 11-25, qui affiche un indicateur d'activité (comme dans listing 11-22), mais qui est visuellement plus satisfaisant. L'élément indicator apparait progressivement quand l'appel Ajax démarre, et fond progressivement quand la réponse arrive. En outre, l'élément feedback est mis en évidence après avoir été mis à jour par l'appel distant, pour attirer l'attention de l'utilisateur vers cette partie de la fenêtre.

Listing 11-25 - Effets visuels dans des callbacks Ajax

[php]
<div id="feedback"></div>
<div id="indicator" style="display: none">Loading...</div>
<?php echo link_to_remote('Delete this post', array(
    'update'   => 'feedback',
    'url'      => 'post/delete?id='.$post->getId(),
    'loading'  => visual_effect('appear', 'indicator'),
    'complete' => visual_effect('fade', 'indicator').
                  visual_effect('highlight', 'feedback'),
)) ?>

Notez que vous pouvez combiner des effets visuels en les concaténant dans un callback.

JSON

JavaScript Object Notation (JSON) est un format d'échange de données de faible poids. En principe, ce n'est rien de plus que du hachage en JavaScript (voir un exemple dans le listing 11-26) utilisé pour le transport d'information d'objet. Mais JSON a deux grands avantages pour les interactions Ajax: il est facile à lire en JavaScript, et il peut réduire la taille d'une réponse Web.

Listing 11-26 - Exemple d'objet JSON en JavaScript

var myJsonData = {"menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
}}

Si une action Ajax doit retourner des données structurées à la page appelante pour des traitements JavaScript plus important, JSON est un bon format pour la réponse. C'est très utile si, par exemple, un appel Ajax doit mettre à jour plusieurs éléments de la page appelante.

Par exemple, imaginez une page d'appel qui ressemble au listing 11-27. Il y a deux éléments qui peuvent être modifiés. Un aide distante pourrait actualiser seulement l'un des deux éléments de la page (le title ou le name), mais pas les deux en même temps.

Listing 11-27 - Exemple d'un template avec des mises à jour Ajax multiples

[php]
<h1 id="title">Basic letter</h1>
<p>Dear <span id="name">name_here</span>,</p>
<p>Your e-mail was received and will be answered shortly.</p>
<p>Sincerely,</p>

Pour mettre à jour les deux, imaginez que la réponse Ajax puisse être une entête JSON contenant le tableau suivant:

 [["title", "My basic letter"], ["name", "Mr Brown"]]

Ensuite, l'appel distant peut facilement interpréter cette réponse et mettre à jour plusieurs champs dans un enregistrement, avec l'aide d'un peu de JavaScript. Le code dans le listing 11-28 montre ce qui pourrait être ajouté au template du listing 11-27 pour atteindre cet effet.

Listing 11-28 - Mettre à jour plus d'un élément venant d'une réponse à distance

[php]
<?php echo link_to_remote('Refresh the letter', array(
  'url'      => 'publishing/refresh',
  'complete' => 'updateJSON(request, json)'
)) ?>

<?php echo javascript_tag("
function updateJSON(request, json)
{
  var nbElementsInResponse = json.length;
  for (var i = 0; i < nbElementsInResponse; i++)
  {
     Element.update(json[i][0], json[i][1]);
  }
}
") ?>

Le callback complete a accès à l'entête json de la réponse et peut le transmettre à un tiers de la fonction. Cette fonction personnalisée updateJSON() itère sur l'entête JSON, et pour chaque élément du tableau, met à jour l'élément nommé par le premier paramètre avec le contenu du second paramètre.

Le listing 11-29 montre comment l'action publishing/refresh peut retourné une réponse JSON.

Listing 11-29 - Exemple d'une action retournant une entête JSON

[php]
class publishingActions extends sfActions
{
  public function executeRefresh()
  {
    $output = '[["title", "My basic letter"], ["name", "Mr Brown"]]';
    $this->getResponse()->setHttpHeader("X-JSON", '('.$output.')');

    return sfView::HEADER_ONLY;
  }

Le protocole HTTP permet de stocker JSON dans l'entête de la réponse. Comme la réponse n'a pas de contenu, l'action l'envoie immédiatement comme une entête seule. Cela évite entièrement la couche de la vue et c'est est aussi rapide qu'un ->renderText() mais avec une réponse plus petite.

CAUTION Il y a une grande restriction à l'approche montrée dans la listing 11-29 : la taille maximum d'entête HTTP. Il n'y a aucune restriction officielle, mais de grandes entêtes ne peuvent pas être bien transférées ou interprétées par un navigateur.

There is a severe limitation to the approach shown in Listing 11-29: the maximum size of HTTP headers. There is no official limitation, but large headers may not be well transferred or interpreted by a browser. Cela signifie que si votre tableau JSON est important, l'action à distance devrait retourner une réponse normale, à condition que JSON soit comme un tableau JavaScript.

JSON est devenu un standard parmi les applications Web. Les services Web proposent souvent des réponses en JSON plutôt qu'en XML, afin de permettre l'intégration du côté client (mashup), plutôt que du côté serveur. Donc, si vous vous demandez, quel format il faut utiliser pour la communication entre votre serveur et une fonction JavaScript, JSON est probablement le meilleur pari.

TIP Depuis la version 5.2, PHP propose deux fonctions, json_encode() et json_decode(), qui vous permettent de convertir un tableau entre la syntaxe PHP et celle de JSON, et vice versa (http://www.php.net/manual/en/ref.json.php). Elles facilitent l'intégration des tableaux JSON et d'Ajax en général.

Exécuter des interactions complexes avec Ajax

Parmi les aides symfony Ajax, vous trouverez également des outils qui accumulent des interactions complexes avec un seul appel. Ils vous permettent de rehausser l'utilisation comme des applications interactive que l'on trouvent sur ordinateur de bureau (glisser-déposer, complétion automatique, éditer directement) sans avoir besoin de JavaScript complexe. Les sections suivantes décrivent les aides pour les interactions complexes et montrent des exemples simples. D'autres paramètres et réglages sont décrits dans la documentation script.aculo.us.

CAUTION Si les interactions complexes sont possibles, elles ont besoin de temps supplémentaire pour améliorer la présentation, afin de donner un aspect plus naturel. Utilisez-les seulement quand vous êtes sûrs qu'ils améliorent l'ergonomie. Évitez-les quand il y a un risque de désorienter les utilisateurs.

Complètement automatique

Un composant text-input qui affiche une liste de mots correspondant à ce que l'utilisateur est en train de saisir, s'appele un complètement automatique. Avec une aide unique appelé input_auto_complete_tag(), vous pouvez obtenir cet effet, à condition que l'action distante renvoie une réponse sous la forme d'une liste HTML similaire à l'exemple montré dans le listing 11-30.

Listing 11-30 - Exemple d'une réponse compatible avec une balise de complètement automatique

<ul>
  <li>suggestion1</li>
  <li>suggestion2</li>
  ...
</ul>

Insérez l'aide dans le template comme vous le feriez avec une saisie de texte ordinaire, en suivant l'exemple montré dans le Listing 11-31.

Listing 11-31 - Utiliser une aide de complètement automatique dans un template

[php]
<?php echo form_tag('mymodule/myaction') ?>
  Find an author by name:
  <?php echo input_auto_complete_tag('author', 'default name',
    'author/autocomplete',
    array('autocomplete' => 'off'),
    array('use_style'    => true)
  ) ?>
  <?php echo submit_tag('Find') ?>
</form>

Ceci fait appel à l'action author/autocomplete chaque fois que l'utilisateur tape un caractère dans le champ author. C'est à vous de concevoir l'action, afin qu'elle détermine une liste de résultat selon le paramètre de la requête author et les renvoie dans un format similaire au listing 11-30. L'aide affichera alors la liste sous le champ author, et en cliquant sur une des suggestions ou en la sélectionnant avec le clavier, cala viendra compléter l'entrée, comme le montre la Figure 11-3.

Figure 11-3 - Un exemple de complètement automatique

Un exemple de complètement automatique

Le troisième argument de l'aide input_auto_complete_tag() peut prendre les paramétres suivants:

  • use_style: Crée la liste des réponses automatiquement.
  • frequency: Fréquence de l'appel périodique (par défaut à 0,4s).
  • tokens: Pour permettre la tokenisation d'un complètement automatique. Par exemple, si vous réglez ce paramètre à , et si l'utilisateur a entré jane, george, l'action ne reçoivent que la valeur 'george'.

NOTE L'aide input_auto_complete_tag(), comme les suivantes, accepte également les options habituelles des aides distantes décrites plus haut dans ce chapitre. En particulier, il est une bonne habitude de mettre les effets visuels loading et complete pour une meilleure ergonomie utilisateur.

Glisser-Déposer

La capacité de saisir un élément avec la souris, de le déplacer, puis le relâcher à un autre endroit est familier dans les applications de bureau, mais plus rares dans les navigateurs Web. La raison est que ce comportement à coder clairement en JavaScript est très compliqué. Heureusement, nous n'avons besoin que d'une ligne dans symfony.

Le framework prévoit deux aides, draggable_element() et drop_receiving_element(), qui peuvent être considérées comme des modificateurs de comportement. Elles ajoutent des observateurs et des aptitudes à l'élément qu'elles abordent. Utilisez-les pour déclarer un élément déplacable ou un élément pour réceptionner des éléments déplacés. Un élément déplacable peut être saisis en cliquant avec la souris. Jusqu'à ce que le bouton de la souris soit relâché, l'élément peut être déplacé, ou traînés, à travers la fenêtre. Un élément de réception appelle une fonction à distance quand un élément déplacés est déposé sur lui. Le listing 11-32 démontre ce type d'interaction avec un panier recevant un élément.

Listing 11-32 - Eléménts déplaçables et éléments recus dans un panier

[php]
<ul id="items">
  <li id="item_1" class="food">Carrot</li>
  <?php echo draggable_element('item_1', array('revert' => true)) ?>
  <li id="item_2" class="food">Apple</li>
  <?php echo draggable_element('item_2', array('revert' => true)) ?>
  <li id="item_3" class="food">Orange</li>
  <?php echo draggable_element('item_3', array('revert' => true)) ?>
</ul>
<div id="cart">
  <p>Your cart is empty</p>
  <p>Drag items here to add them to your cart</p>
</div>
<?php echo drop_receiving_element('cart', array(
  'url'        => 'cart/add',
  'accept'     => 'food',
  'update'     => 'cart',
)) ?>

Chacun des éléments de la liste peuvent être saisis par la souris et trainés à travers la fenêtre. En cas de libération, ils retournent à leur position initiale. En cas de libération sur l'élément cart, cela déclenche un appel à distance à l'action cart/add. L'action sera en mesure de déterminer quel élément a été déposé dans l'élément cart en regardant le paramètre id de la requête. Donc le listing 11-32 simule une session d'achat réel: vous prenez les articles et les déposez dans le panier, puis vous passez à la caisse.

TIP Dans le listing 11-32, les aides sont écrites juste après l'élément qu'elles modifient, mais ce n'est pas une obligation. Vous pouvez très bien regrouper toutes les aides draggable_element() et drop_receiving_element() à la fin du template. L'important, c'est que le premier argument de l'aide soit nommé, ceci spécifie l'identifiant de l'élément à recevoir le comportement.

L'aide draggable_element() accepte les paramètres suivants:

  • revert: Si la valeur est true, l'élément retournera à son emplacement d'origine, si ce dernier est relaché. Cela peut aussi être une référence de fonction arbitraire, appelée à la fin de la traînée.
  • ghosting: Clone l'élément et entraîne le clone, en laissant l'original en place jusqu'à ce que le clone soit relaché.
  • snap: Si la valeur est false, aucun mouvement saccadé se produit. Sinon, les déplacements peuvent être trainés seulement à l'intersection d'une grille dont l'intervalle est x et y, et dans ce cas, elle prend la forme xy or [x,y] or function(x,y){ return [x,y] }.

L'aide drop_receiving_element() accepte les paramètres suivants:

  • accept: Une chaine de caractère ou un tableau de chaine de caractères décrivant des classes CSS. Les éléments glissables seront acceptés à condition d'avoir au moins l'une de ces classes CSS.
  • hoverclass: La classe de CSS s'ajoute à l'élément quand l'utilisateur traîne un élément déplaçable accepté au-dessus de lui.

Listes triables

Une autre possibilité offerte par les éléments déplaçables, c'est la possibilité de trier une liste en déplaçant ses éléments avec la souris. L'aide sortable_element() ajoute un comportement de tri à un élément, et le listing 11-33 est un bon exemple de mise en oeuvre de cette fonctionnalité.

Listing 11-33 - Example de liste triable

[php]
<p>What do you like most?</p>
<ul id="order">
  <li id="item_1" class="sortable">Carrots</li>
  <li id="item_2" class="sortable">Apples</li>
  <li id="item_3" class="sortable">Oranges</li>
  // Nobody likes Brussel sprouts anyway
  <li id="item_4">Brussel sprouts</li>
</ul>
<div id="feedback"></div>
<?php echo sortable_element('order', array(
  'url'    => 'item/sort',
  'update' => 'feedback',
  'only'   => 'sortable',
)) ?>

Par la magie de l'aide sortable_element(), l'élément <ul> est maintenant triable, ce qui signifie que ses enfants peuvent être réorganisés par glisser-déposer. Chaque fois que l'utilisateur traîne un élément et le libère pour le replacer dans la liste, une demande d'Ajax est faite avec les paramètres suivants:

POST /sf_sandbox/web/frontend_dev.php/item/sort HTTP/1.1
  order[]=1&order[]=3&order[]=2&_=

La liste triée complète est passée comme un tableau (avec le format order[$rank]=$id, le $rank démarre à 0, et le $id est basée sur ce qui vient après le caractère de soulignement (_) dans la liste de l'élément de propriété id. La propriété id de l'élément triable (order dans l'expemle) est utilisé pour le tableau de paramètre. L'aide sortable_element() accepte les paramètres suivants:

  • only: Une chaine de caractère ou un tableau de chaine de caractères décrivant des classes CSS. Seuls les fils de l'élément triables, ayant cette classe peuvent être bougés.
  • hoverclass: la classe CSS est àjoutée à l'élement lorsque la souris est le survol.
  • overlap: Mettre la valeur horizontal si tous les éléments sont affichés sur une ligne, et vertical (La valeur par défaut) quand il y a un élément par ligne (comme dans cette exemple).
  • tag: Si la liste à trier ne contient pas les éléments <li>, vous devez définir quel est l'élément fils de l'élément triable qui sera déplaçable (par exemple, div ou dl).

Edit in Place

De plus en plus d'applications Web permettent aux utilisateurs de modifier le contenu de la page directement sur la page, sans qu'il soit nécessaire de réintroduire le contenu dans un formulaire. Le principe de l'interaction est simple. Un bloc de texte est en surbrillance lorsque l'utilisateur survole avec la souris sur celui-ci. Si l'utilisateur clique dans le bloc, le texte est converti en une zone de texte rempli avec le texte du bloc, et un bouton de sauvegarde apparaît. L'utilisateur peut modifier le texte dans la zone de texte, et une fois qu'il l'enregistre, la zone de texte disparaît et le texte est affiché en clair. Avec symfony, vous pouvez ajouter ce comportement d'édition à un élément avec l'aide input_in_place_editor_tag(). Le listing 11-34 démontre l'utilisation de cette aide.

Listing 11-34 - Exemple de texte éditable

[php]
<div id="edit_me">You can edit this text</div>
<?php echo input_in_place_editor_tag('edit_me', 'mymodule/myaction', array(
  'cols'        => 40,
  'rows'        => 10,
)) ?>

Quand l'utilisateur clique surle texte éditable, il est remplacé par une zone de texte saisissable remplie avec le texte, qui peut être édité. Quand le formulaire est soumis, l'action mymodule/myaction est appelée en Ajax en passant dans le paramètre value, la valeur saisie. Le résultat de l'action met à jour les éléments modifiables. Il est très rapide à écrire et très puissant.

L'aide input_in_place_editor_tag() accepte les paramètres suivants:

  • cols et rows: La taille de la zone de saisie du texte qui apparaît pour l'édition (il devient un <textarea> si rows est supérieur à 1).
  • loadTextURL: L'URI d'une action qui est appelé pour afficher le texte à modifier. Ceci est utile si le contenu de l'élément modifiable utilise une mise en forme spéciale et si vous voulez que l'utilisateur modifie le texte sans mise en forme.
  • save_text et cancel_text: Le texte du lien pour sauver (par défaut "ok") et celui du lien pour annuler (Par défaut "cancel").

Résumé

Si vous êtes fatigué d'écrire du JavaScript dans vos templates pour obtenir des comportements côté client, les aides JavaScript offrent une alternative simple. Non seulement ils automatisent le lien fondamental du comportement et de l'élément à mettre à jour, mais ils fournissent aussi un moyen de développer les interactions Ajax en un clin d'oeil. Avec l'aide d'une puissante syntaxe fournie par Prototype et les grands effets visuels fournis par script.aculo.us, même des interactions complexes s'écrivent en quelques lignes.

Et grâce à cela, une application très interactive est aussi facile à faire que des pages statiques avec symfony, vous pouvez considérer que la quasi-totalité des interactions des applications de bureau sont maintenant disponibles dans les applications Web.