Symfony & jQuery DatePicker

Je vais vous montrer dans cet article comment mettre en place rapidement un datePicker jQuery dans un formulaire Symfony 1.2

Pré-requis

Fichiers externes

  • Télécharger jQuery UI
    (jquery-1.3.2.min.js, jquery-ui-1.7.1.custom.min.js)

    Vous pouvez télécharger une version « customizée » de jQuery UI ici :
    Télécharger JQuery UI

  • Version française
    (uidatepicker-fr.js)

    Vous trouverez le patch français de ce plugin ici :

    Datepicker jQuery en français

  • Intégration dans Symfony
    1. JS
      Copiez les fichiers :
      [jquery UI]/js/jquery-1.3.2.min.js
      [jquery UI]/js/jquery-ui-1.7.1.custom.min.js
      uidatepicker-fr.js
      directement dans [votre_projet]/web/js
    2. CSS
      • Copiez le fichier :
        [jquery UI]/css/jquery-ui-1.7.1.custom.css dans :
        [votre_projet]/web/css.
      • !! Attention !! :
        J’ai dû remplacer toutes les occurrences de :
        url(images/ par :
        url(../images/
    3. Images
      N’oubliez pas de copier le contenu de :
      [jquery UI]/css/smoothness/images dans :
      [votre_projet]/web/images

View.yml

N’oubliez pas de faire référence aux fichiers externes dans le view :

default:
  http_metas:
    content-type: text/html
 
  metas:
    #title:        symfony project
    #description:  symfony project
    #keywords:     symfony, project
    #language:     en
    #robots:       index, follow
 
  stylesheets:    [main.css, jquery-ui-1.7.1.custom.css]
 
  javascripts:    [jquery-1.3.2.min.js, uidatepicker-fr.js, jquery-ui-1.7.1.custom.min.js]
 
  has_layout:     on
  layout:         layout

sfWidgetFormJQueryI18nDate.class.php

J’ai modifié la classe sfWidgetFormJQueryDate pour qu’elle soit compatible avec un format de date français.
De plus, on peut facilement configurer les options du widget jQuery.

  • Code source :
    Fichier : sfWidgetFormJQueryI18nDate.class.php
    Chemin : /plugins/sfFormExtraPlugin/lib/widget/

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    
    <?php
    /*
     * This file is part of the symfony package.
     * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
     * 
     * For the full copyright and license information, please view the LICENSE
     * file that was distributed with this source code.
     */
     
    /**
     * sfWidgetFormJQueryDate represents a date widget rendered by JQuery UI.
     *
     * This widget needs JQuery and JQuery UI to work.
     *
     * @package    symfony
     * @subpackage widget
     * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
     * @version    SVN: $Id: sfWidgetFormJQueryDate.class.php 12875 2008-11-10 12:22:33Z fabien $
     */
    class sfWidgetFormJQueryI18nDate extends sfWidgetFormI18nDate
    {
      /**
       * Configures the current widget.
       *
       * Available options:
       *
       *  * image:   The image path to represent the widget (false by default)
       *  * config:  A JavaScript array that configures the JQuery date widget
       *  * culture: The user culture
       *
       * @param array $options     An array of options
       * @param array $attributes  An array of default HTML attributes
       *
       * @see sfWidgetForm
       */	
     
      protected function configure($options = array(), $attributes = array())
      {
        $this->addOption('image', false);
        $this->addOption('config', $options["config"]);
        $this->addOption('culture', $options["culture"]);
        $this->addOption('years', $options["years"]);
     
        parent::configure($options, $attributes);
     
        if ('en' == $this->getOption('culture'))
        {
          $this->setOption('culture', 'en');
        }
      }
     
      /**
       * @param  string $name        The element name
       * @param  string $value       The date displayed in this widget
       * @param  array  $attributes  An array of HTML attributes to be merged with the default HTML attributes
       * @param  array  $errors      An array of errors for the field
       *
       * @return string An HTML tag string
       *
       * @see sfWidgetForm
       */
      public function render($name, $value = null, $attributes = array(), $errors = array())
      {
        $prefix = $this->generateId($name);
     
        $image = '';
        if (false !== $this->getOption('image'))
        {
          $image = sprintf(', buttonImage: %s, buttonImageOnly: true', $this->getOption('image'));
        }
        return parent::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">
     
      function %s_read_linked()
      {
        \$("#%s").val(\$("#%s").val() + "/" + \$("#%s").val() + "/" + \$("#%s").val());
     
        return {};
      }
     
      function %s_update_linked(date)
      {
        \$("#%s").val(date.substring(0, 2));
        \$("#%s").val(parseInt(date.substring(3, 5), 10));
        \$("#%s").val(date.substring(6, 10));
      }
     
      \$("#%s").datepicker(\$.extend({}, {
        minDate:    new Date(%s, 1 - 1, 1),
        maxDate:    new Date(%s, 12 - 1, 31),
        onSelect:   %s_update_linked,
        beforeShow: %s_read_linked,    
        %s    
        showOn:     "both"
        %s
      }, \$.datepicker.regional["%s"]));
     
    </script>
    EOF
          ,
          $prefix, $id,
          $this->generateId($name.'[day]'), $this->generateId($name.'[month]'), $this->generateId($name.'[year]'),
          $prefix,
          $this->generateId($name.'[day]'), $this->generateId($name.'[month]'), $this->generateId($name.'[year]'),
          $id,
          min($this->getOption('years')), max($this->getOption('years')),
          $prefix, $prefix, $this->getOption('config'), $image, $this->getOption('culture')
        );
      }
    }
  • Explication des modifications :
    1. Ligne 20 :
      Notre widget dérive désormais de sfWidgetFormI18nDate

      20
      
      class sfWidgetFormJQueryDate extends sfWidgetFormI18nDate
    2. Lignes 40, 41 et 42:
      On ajoute les options « config », « culture » et « years » avec le paramètre « options » de la fonction « configure » :

      40
      41
      42
      
        $this->addOption('config', $options["config"]);
        $this->addOption('culture', $options["culture"]);
        $this->addOption('years', $options["years"]);
    3. Lignes 85 et 86
      • Il faut inverser l’ordre du jour et du mois pour être compatible avec un format français, ce qui revient dans un sprintf, à changer l’ordre des lignes dans le code.
      • Il faut faire un parseInt sur le mois pour transformer « 01″ en « 1″, parseInt est la fonction javascript permettant de caster une chaîne de caractères en Integer :
        Premier paramètre : la chaîne à caster (ici : date.substring(3, 5) )
        Deuxième paramètre : Le système numérique à utiliser (ici décimal : 10)
      85
      86
      
          \$("#%s").val(date.substring(0, 2));
          \$("#%s").val(parseInt(date.substring(3, 5), 10));
    4. Lignes 95 et 109
      • On passe les options directement dans le premier argument.
        Le %s de la ligne 95 correspond au $this->getOption(‘config’) de la ligne 109
        Le %s de la ligne 98 correspond au $this->getOption(‘culture’) de la ligne 109
      • Ligne 109 : passage des options et da la culture au widget.
      108
      
      $prefix, $prefix, $this->getOption('config'), $image, $this->getOption('culture')

Exemple d’utilisation

  • Schéma
    person:
      columns:
        [...]
        birthday:
          type: timestamp
        [...]
  • Formulaire (Instanciation du widget)
      [...]
      public function configure()
      {
        for($i = 1900; $i<2010; $i++)
        {
          $years[$i] = $i;
        }
        $this->widgetSchema['birthday'] = new sfWidgetFormJQueryI18nDate(
          array('config' => 'yearRange: \'1900:2009\', 
                               changeYear: true, 
                               changeMonth: true,',
                'culture' => 'fr',
                'years'=> array_combine($years, $years))
          );   
      }
      [...]
  • Aperçu
    jquery datepicker fr

Sources

    

10 Responses to “Symfony & jQuery DatePicker”

  1. sessime dit :

    Salut,
    Merci pour ce billet qui m’aide à implementer ce calendrier.
    Mais le plugin que j’ai telechargé sur le site de symfony je n’ai pas ce fichier sfWidgetFormJQueryI18nDate.class.php à l’endroit indiqué /plugins/sfFormExtraPlugin/lib/widget/ ,j’ai plutot celui sfWidgetFormJQueryDate.class.php ou vous aviez renommé ce fichier pour avoir l’autre.
    Priere me donner des pistes.
    Merci d’avance.

  2. Lionel (ex-lexik) dit :

    Salut,
    Oui j’ai renommé le fichier, et je l’ai modifié pour qu’il gère l’i18n. La classe hérite de ‘sfWidgetFormI18nDate’ et plus de ‘sfWidgetFormDate’.
    Merci pour l’intérêt que vous portez au blog de Lexik =)

  3. Mac Curty dit :

    Bonjour,

    merci pour ce petit tuto, tout marche bien à l’exception d’une petite chose :

    Quand je choisis une date avec le calendrier, il n’y a que les 3 derniers mois qui fonctionnent. Par exemple si je sélectionne une date en mars, le jour et l’année s’affichent correctement dans la partie gauche mais le moi reste vide …

    Si vous avez une idée je suis preneur.

    Bye

  4. TomTom dit :

    Merci pour ce tutoriel.
    C\’est à deux doigts de fonctionner pour moi, mis à part le fait que les mois et les jours sont inversés ! Je m\’explique :
    Les champs du formulaire contiennent \"12 mars 2008\", et dans le widget jQuery, la date par défaut est 3 décembre 2008\". 12/03 correspond à 03/12 et inversement.

    Sur votre exemple, on est au 08/08/1979, forcément ça fonctionne dans les deux sens !

    Vous n\’avez pas ce souci pour les autres dates ?

  5. Empouioui dit :

    Encore un merci pour ce tutoriel,
    Je débute avec Symfony (1.2) et je me retrouve à travailler sur un projet conséquent.
    Votre blog, en général, m\’ai d\’un grand secoure pour comprendre de nombreuses subtilités de ce framework !

    Merci encore !

    PS: Pas de souci pour aucunes dates en ce qui me concerne …

  6. Nicolas dit :

    Ca n’a pas l’air de fonctionner avec symfony 1.4.1 :/

  7. @Nicolas dans symfony 1.4.1 on a pas à inverser l\’ordre du jour et du moins, le plugin supporte désormais un paramètre "date_widget" ou tu peux renseigner le format de la date que tu souhaites

  8. loulouraph dit :

    Hello,

    Pour rendre un peu plus français le widget, je rajoute un config en plus : firstDay: 1, ce qui fait commencer la semaine au lundi.

  9. Laurent dit :

    Merci pour ce tuto.

    J’aimerai n’avoir qu’un champ date au lieu d’avoir 3 champs : jour, mois et année. Que dois-je changer ?

    Merci d’avance,

    Symfony 1.4
    Netbeans 6.8
    php 5.3

  10. Benoit dit :

    Merci pour ce tuto qui m’a permis d’implémenter le datepicker, non sans mal ceci dit ! mais ça fonctionne.

    Par contre, comment fait-on pour inverser l’ordre des select jour et mois ? J’ai toujours le select mois avant le select jour…

    Bon courage pour la suite, continuez comme ça !

Laisser un commentaire

Security Code: