Remplacer un contrôle datepicker en JavaScript qui date de 2004 par celui de jQueyUI ? Oui ! N'importe quoi pour se débarrasser d'une vieille librairie dont le rendu jure avec le reste de l'application.
Dans la plupart des écrans, il était possible de choisir une date par le calendrier mais aussi de vider la valeur sélectionnée par un simple clic (ce qui avait pour effet de vider la valeur de l'input). Avec l'ancien contrôle datepicker, chaque input text accueillant une date était associé à une icône pour ouvrir le calendrier de saisie et une autre pour vider le champ. Contrairement à jQuery qui utilise des sélecteurs pour initialiser l'interface, celui-là avait du code HTML et JavaScript ajouté manuellement.
Comme j'allais le remplacer par le datepicker de jQueryUI, mon objectif était d'éviter d'avoir à ajouter du code à l'emplacement de chaque champ date (plus propre) et de voir s'il existait une option built-in à configurer. La documentation de jQuery indique qu'on peut ajouter un "button bar" qui comprend le bouton de fermeture mais contrairement au contrôle Dialog, il ne semble pas possible d'ajouter des boutons personnalisés (du moins, pas dans la version courante 1.8.16). Seul le libellé du bouton peut être modifié pour des fins de traduction.
Et pourquoi ne pas tenter de remplacer le fonctionnement du bouton pour qu'il fasse ce dont j'ai besoin ? Après tout, si on clique à l'extérieur de la zone du calendrier, il se ferme automatiquement, ce qui ne change en rien son comportement.
Pour remplacer le fonctionnement du bouton "Done" (Terminé) par "Clear" (Vider), j'y suis arrivé par un petit hack. Ça fonctionne bien pour les besoins de la cause mais je ne peux pas garantir que ce sera fonctionnel dans tous les cas ni dans les versions ultérieures. Voyez-le comme une solution temporaire pour ajouter simplement une option de configuration.
Pour commencer, référez-vous à la documentation du datepicker de jQueryUI pour l'intégrer à votre projet. Vous aurez probablement à définir des valeurs par défaut pour le contrôle et vous aurez au minimum besoin de celles-ci (remplacez $j par $ si vous n'utilisez pas l'option noConflict) :
$j.datepicker.setDefaults({Si vous inspectez le DOM, vous remarquez que le datepicker s'insère dedans uniquement au premier appel (lorsque le calendrier apparaît à l'écran). Vous trouverez le HTML immédiatement avant la balise de fermeture du BODY. C'est pourquoi il faudra utiliser la fonction live() de jQuery pour que le hack fonctionne.
'dateFormat':'yy-mm-dd',
'buttonImageOnly': true,
'buttonImage': 'images/icon.gif',
'showButtonPanel' : true,
'showOn': 'both'
});
$j(document).ready(function(){La première chose à faire, c'est d'attacher un événement click en mode live sur le bouton qui possède la classe ui-datepicker-close. Il n'y en aura qu'un seul pour tous les champs de la page qui utilisent un datepicker. Dans le markup HTML généré sur demande pour le calendrier, le nom du champ associé (ID de l'input) se trouve passé en paramètre à une fonction attachée inline à l'élément. J'utilise une regex pour l'extraire de l'attribut. Enfin, je vérifie que le libellé du bouton est égal à "Clear" (ou toute autre valeur que vous aurez choisi selon votre personnalisation). Si c'est le cas, je vide l'input.
$j('button.ui-datepicker-close').live('click',
function(){
var id = $j('button.ui-datepicker-current').attr('onclick').replace(/.*gotoToday\('#(.*)'\);/gi, '$1');
if( $j('button.ui-datepicker-close', $j('#ui-datepicker-div')).html() == 'Clear' ){
$j('#' + id).val('');
}
}
);
});
Certaines instances du calendrier pourront maintenant avoir ou non le changement de fonctionnalité du bouton. Pour qu'il l'ait, il suffira de changer le libellé du bouton en visant un ID en particulier ou un sélecteur CSS lors de l'initialisation.
$j(document).ready(function(){Vous auriez fait autrement ? Partagez votre solution!
// avec bouton close (standard)
$j('#datePicker1').datepicker();
// avec bouton Clear
$j('.datePicker2').datepicker({'closeText' : 'Clear'});
}