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

Partagez cet article