Présentation du plugin lxJavascriptPlugin

L’article d’hier sur les bonnes pratiques Javascript dans un projet Symfony faisait mention d’un plugin que nous utilisons en interne et qui est maintenant disponible sur Github: lxJavascriptPlugin. Ce court article va brièvement présenter son fonctionnement et son utilisation.

L’installation du plugin est très rapide:

  • téléchargez les sources sur Github dans le répertoire plugins de votre projet,
  • éditez le fichier config/settings.yml pour y inclure le helper lxJavascript:
    all:
      .settings:
        standard_helpers: [ ... , lxJavascript ]

Et c’est tout! Voyons maintenant le fonctionnement.

Le premier but du plugin est de solutionner les problèmes de granularité du code Javascript dans un projet Symfony. Lorsque l’on utilise par exemple des widgets JQuery, des partials pour les réseaux sociaux, ou des composants pour des GoogleMap, on se retrouve vite avec du code Javascript éparpillé dans tout notre projet, et par conséquent tout autant éparpillé dans le code des pages générées.

Pour régler ce problème lxJavascriptPlugin propose un premier outil: le helper lxJavascriptHelper. Son utilisation est très similaire à celle du javascriptHelper de Symfony, mais avec la méthode lx_javascript:

  • pour inclure un fichier source externe à la page:
    <?php lx_javascript('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js') ?>
  • pour inclure directement du code javascript, par exemple le bout de code pour Google Analytics, le fonctionnement est similaire à celui d’un slot:
    <?php lx_javascript() ?>
      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', '*********']);
      _gaq.push(['_trackPageview']);
      (function() {
        var ga = document.createElement('script');
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        ga.setAttribute('async', 'true');
        document.documentElement.firstChild.appendChild(ga);
      })();
    <?php lx_end_javascript() ?>

    Ici la balise <script> n’est pas nécessaire, mais vous pouvez l’utiliser si vous le souhaitez (par exemple pour garder la coloration syntaxique de votre IDE)

  • pour insérer tout le code javascript déclaré via lx_javascript() à la fin de votre layout.php:
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
      <head>
        ...
      </head>
      <body>
        ...
        <?php lx_include_javascripts() ?>
      </body>
    </html>

Le soucis de javascript dans les templates est adressé. Reste maintenant le problème du code javascript inséré via d’autres moyens, comme par exemple un widget qui utilise JQuery. Pour cela lxJavascriptPlugin propose une classe statique lxJavascriptStorage qui offre les fonctionnalités du helper depuis n’importe où dans votre code:

  • pour ajouter une source externe:
    lxJavascriptStorage::addRemoteJavascript('http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js');
  • pour ajouter du code javascript. Voyons par exemple la méthode render() du widget sfWidgetFormJQueryDate:
    public function render($name, $value = null, $attributes = array(), $errors = array())
    {
      //code
      return $this->getOption('date_widget')->render($name, $value, $attributes, $errors).
               $this->renderTag('input', array('type' => 'hidden', 'size' => 10, 'id' => $id = $this->generateId($name).'_jquery_control', 'disabled' => 'disabled')).
               sprintf(<<<EOF
    <script type="text/javascript">// <![CDATA[
      [...]
    // ]]></script>
    EOF
        ,
        //arguments du sprintf
      );
    }

    Nous voyons bien le javascript retourné dans le code du widget, et donc en milieu de page. Cette fonction render() pourrait, avec lxJavascriptPlugin, ressembler à ça:

    public function render($name, $value = null, $attributes = array(), $errors = array())
    {
      //code </code>
     
      $js = sprintf(<<<EOF
    <script type="text/javascript">// <![CDATA[
      [...]
    // ]]></script>
    EOF
        ,
        //arguments du sprintf
      );
      lxJavascriptStorage::addJavascriptCode($js);
     
      return $this->getOption('date_widget')->render($name, $value, $attributes, $errors).
               $this->renderTag('input', array('type' => 'hidden', 'size' => 10, 'id' => $id = $this->generateId($name).'_jquery_control', 'disabled' => 'disabled'));
    }

    Peu de changements, mais ici le javascript sera rendu avec tout le reste du javascript en pied de page.

Notez enfin que la méthode lx_include_javascripts() rendra en premier les sources externes, puis le code javascript concaténé dans une unique balise <script>. Si tous les exemples précédents sont utilisés dans une application, le javascript en pied de page donnera ceci:

?View Code JAVASCRIPT
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">// <![CDATA[
  //javascript du widget
 
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', '*********']);
  _gaq.push(['_trackPageview']);
  (function() {
    var ga = document.createElement('script');
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    ga.setAttribute('async', 'true');
    document.documentElement.firstChild.appendChild(ga);
})();
/* ]]> */</script>

Vous pouvez obtenir lxJavascriptPlugin sur Github.

Partagez cet article