Ajouter un calcul dans un calendrier de type "DatePicker" ?

Résolu
Utilisateur anonyme - 31 janv. 2011 à 14:55
 Utilisateur anonyme - 12 févr. 2011 à 12:23
Bonjour !

J'utilise un calendrier type "DatePicker" qui fonctionne très bien.

voir ici : Formulaire qui fonctionne

Il a été construit sur la base Demo de PopCalendarXP trouvé ici : Demo du DatePicker et adapté dans mon formulaire en PHP que je maitrise pas du tout mais qui fonctionne parfaitement !!

Je voudrais ajouter un calcul automatique du nbr de jours pour l'afficher dynamiquement dans mon Formulaire (zone "Nombre de Nuitées"). Je ne sais pas du tout comment faire.

Quelqu'un peut'il m'aider ?

Merci
JClaude

22 réponses

007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
11 févr. 2011 à 14:07
C'est dommage de recalculer les dates sans utiliser les arguments y,m,d de la fonction fAfterSelected ! Vous tuez toutes les possibilités d'adaptation du script...

Peut-être conviendrait-il (pour ne pas faire porter le test sur des objets) de ne mettre en mémoire (dans _crtCal) que les noms des inputs concernés avec dans les fonctions des _crtCal=_startc.name ou _crtCal=_endc.name qui devraient redonner dc1 et dc2.

Avec quelques tests et mises au point la fonction proposée devrait pouvoir fonctionner.

Quant au questionnaire, hormis les champs readonly pour les dates (déjà évoqués) j'aurais personnellement tendance à ne pas faire figurer l'indication «Nombre de nuitées» tant que celui-ci n'est pas susceptible d'être calculé. C'est un élément étranger au questionnaire qui ne doit pas troubler l'utilisateur au départ et pour lequel il est inutile de prévoir un champ de formulaire (sauf à renvoyer un élément masqué) si celui-ci ne peut être modifié !

Voir à cet égard quelques indications sur cette page et les suivantes pour faire de jolis formulaires et plus généralement pour écrire un code plus ramassé (voir les old script pages)...

Bon vent.
3
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
2 févr. 2011 à 10:52
La difficulté essentielle ne résidant pas dans le calcul mais dans son lancement qui devrait être lancé lors du choix ou de la modification d'une des dates, il est difficile de répondre avec un code calendrier caché dans les noms et id d'une iframe hors fenêtre !

Remède proposé : mieux exhiber le code du DatePicker ou en trouver un autre plus accessible...
0
Utilisateur anonyme
5 févr. 2011 à 15:47
Bonjour !
Je peux vous joindre le js du datepicker si cela peut aider ??

ou même la totalité du dossier d'exemple ! Mais c'est peut être trop demander ??

Merci
0
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
5 févr. 2011 à 20:58
Une première piste ...

La page PlugingsSDK.htm (accessible à partir de Tutorials.htm) indique que la fonction de « callback » fAfterSelected (la seconde du script plugins.js) est appelée après chaque clic sur le calendrier. C'est donc elle qu'il convient d'utiliser pour mettre à jour, si possible (c'est-à-dire si les deux dates sont présentes), le nombre de nuitées cherché.

En travaillant sur la page de démonstration DateRangeDemo.htm, et donc sur le fichier plugins.js du sous-répertoire DateRange des Demos, il est alors loisible d'activer cette fonction en supprimant, après les commentaires la décrivant, les deux slashes qui précèdent son nom et en développant le corps de cette fonction.

///// Calendar AfterSelected Handler ///...
// It's triggered whenever a date gets fully selected.
// The selected date is passed in as y(ear),m(onth),d(ay)
// e is a reference to the triggering event object
// NOTE: DO NOT define this handler unless you really need to use it.
///////////...

function fAfterSelected(y,m,d,e) {
alert(y+' '+m+' '+d)
} 

Un alert permet alors de vérifier le fonctionnement du script, cette fonction est bien appelée après chaque clic sur l'un des deux calendriers.

Malheureusement, je n'arrive pas à trouver le moyen de savoir quel calendrier est concerné à partir de l'évènement e correspondant, ni même (après avoir ajouté des id="dc1" et id="dc2" aux deux inputs dans la page DateRangeDemo.htm) à relire directement les valeurs de ces deux balises avec des document.getElementById('cd1').value ???

À suivre...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
6 févr. 2011 à 11:43
Eureka ! Le script plugins.js étant exploité dans l'iframe, il faut remonter au document parent pour accéder aux deux champs des dates de départ et d'arrivée.

D'où, le bricolage suivant :
function fAfterSelected(y,m,d,e) {
var cd=parent.document.getElementById('dc1').value;
var ca=parent.document.getElementById('dc2').value;
var dd=chnToDate(cd),da=chnToDate(ca),msg;
var nbn=Math.round((da-dd)/86400000);
   if (da && dd) msg=(nbn)?"Nombre de nuités : "+nbn:"Aucune nuité";
// Edition du message(avec ajout d'un paragraphe 

 dans la page principale) 
   parent.document.getElementById('idm').innerHTML=msg;
}
// Convertir des chaînes en date
function chnToDate(c){var i,t,r=/(\d\d).(\d\d).(\d\d\d\d)/;
if (!(t=r.exec(c))) return null;
for (i=0;i<t.length;i++) while (t[i].substr(0,1)=='0') t[i]=t[i].substr(1);
return new Date(t[3],t[1],t[2]).valueOf();
}

Le nombre de nuitées est obtenu par différence des valeurs des dates (exprimées en millisecondes depuis le 1er janvier 1970 à minuit UTC) qu'il convient de diviser par 1000 fois le nombre de secondes dans la journée (86400) pour obtenir des jours (ou des nuits).

Soulignons que La fonction chnToDate, élaborée pour la page de démonstration, doit être modifiée avec l'affichage francophone des dates (intervertir t[1] et t[2] dans la dernière ligne).

Il conviendrait donc de plonger plus sérieusement dans le code proposé pour reprendre les variables, fonctions et méthodes de l'auteur et écrire un code plus propre supportant notamment l'internationalisation.

Cette tâche serait sans doute plus aisée avec un script mieux documenté tel par exemple que le plugin de JQuery mentionné ici (voir la page JqueryUI).

Bonne continuation ...
0
Utilisateur anonyme
7 févr. 2011 à 00:50
Pfff ! Je suis impressionné par le travail réalisé !

J'en demandais pas tant !! Merci !

Mais hélas, après modification du script plugins.js, cela ne fonctionne pas !!
Y'a autre chose à modifier !!

PS : j'avais réussit à récupérer dans le mail envoyé par le formulaire le nbr de nuits. les variables dc1 et dc2 étaient correctes et ne demandait pas de convertion nbr seconde par jour...
0
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
7 févr. 2011 à 10:25
Il convient d'abord d'ajouter, dans la page du formulaire, des identifiants id= "dc1" et id="dc2" sur chacun des inputs des dates de départ et d'arrivée (éléments indispensables pour utiliser getElementById) ou bien encore d'exhiber leurs valeurs à partir de leur «name» avec le code suivant dans le fichier plugins.js.

var cd =parent.document.demoform.dc1.value;
var ca= parent.document.demoform.dc2.value;
// Affichage de mise au point 
alert(cd+' '+ca);
// Correction, msg='' au lieu de msg, pour initialiser le message
var dd=chnToDate(cd),da=chnToDate(ca),msg='';

Remarques :
Le message pourrait être initialisé par toute autre formule du genre msg='Utiliser les calendriers pour insérer les dates par simples clics'; . Indépendamment des questions d'accessibilité (comment renseigne-ton une date sans souris ?), La formule consistant à interdire les modifications des dates (attribut readonly ="readonly") me paraît inadaptée, sauf à ouvrir le calendrier sur un simple clic dans le champ (ou avec le focus et entrée). Dans la situation actuelle, les non-initiés risquent d'avoir des difficultés pour entrer une date.

Enfin, le nombre de nuitées n'étant pas demandé mais résultant maintenant des renseignements donnés, le champs correspondant du formulaire doit disparaître pour être remplacé par une div, un paragraphe p ( j'ai proposé [i]

/i ) ou même un span initialement vide.

Enfin, les variables dc1 et dc2 récupérées sont bien correctes sous forme de chaînes de caractères (l'insertion du message d'alerte devrait le mettre en évidence) mais il faut lire les jours mois et années, supprimer les zéros résiduels en tête (précaution peut-être superfétatoire, mais un entier précédé d'un zéro est un nombre octal en javascript) et, enfin, passer par les millisecondes pour calculer proprement le nombre de nuitées.

Si le mail envoyé par le formulaire contient ce nombre de nuitées cela veut dire que l'auteur a implémenté une telle fonction préservant toutes les fonctionnalités de son calendrier. La chercher et l'utiliser me paraît la seule solution à préconiser !
0
Utilisateur anonyme
7 févr. 2011 à 16:47
Bonjour !

Merci encore pour cette réponse...

Ce n'est pas l'auteur mais moi-même qui est ajouté le nbr de nuits, mais uniquement dans le formulaire lorsqu'il envoi le mail de confirmation.
L'affichage du nbr de nuit n'apparait pas dans le formulaire pendant la saisie des dates arrivée et départ (ce que je voudrais).
Il faut donc, comme vous le préconisez, intervenir en amont dans le javascript pour "alimenter" un champ input du formulaire.

Je vais m'appuyer sur votre proposition pour faire des essais.

Merci
0
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
7 févr. 2011 à 18:51
Ok, d'accord.
Il n'y a pas de calcul de nuitées dans le script plugins.js qui est chargé, comme contrast.js, par la page ipopeng.htm. Par contre, j'ai trouvé à la ligne 19 de cette page la constante MILLIDAY (égale à 8640000) utilisée pour calculer un numéro de semaine. Celle-ci est donc à votre disposition comme les variables suivantes (lignes 7 à 11 de contrast.js) qui devraient, pour bien faire, conditionner la méthode de lecture et de calcul des dates (expression régulière, ajout de deux digits aux années, ordre des termes).
var gsSplit="/";	// separator of date string. If set it to empty string, then giMonthMode and gbPadZero will be fixed to 0 and true.
var giDatePos=1;	// date format sequence  0: D-M-Y ; 1: M-D-Y; 2: Y-M-D
var gbPadZero=true;	// whether to pad the digits with 0 in the left when less than 10.
var giMonthMode=0;	// month format 0: digits ; 1: full name from gMonths; >2: abbreviated month name in specified length.
var gbShortYear=false;   // year format   true: 2-digits; false: 4-digits


Quant à l'affichage du nombre de nuitées, il ne doit pas être modifiable par le visiteur mais doit pourtant figurer dans le formulaire pour être transmis au serveur. Il convient donc de prévoir non seulement un paragraphe (ou autre) d'affichage mais encore un input type="hidden" avec un name à l'intérieur du formulaire.
Bon courage.
0
Utilisateur anonyme
8 févr. 2011 à 12:42
Je suis en train de me poser la question !

Ne serait'il pas plus simple de "faire le calcul" de nuitée dans le formulaire PHP plutôt que d'intervenir sur le js ??

Un calcul dynamique (sans bouton 'calcul') dans un formulaire Php est'il possible ??

Vu que DC1 et DC2 s'affiche dans mon formulaire, en profiter pour calculer nbnuit=dc2-dc1 et afficher nbnuit dans le input nbnuit en readonly ??

Je suis perdu !!
0
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
8 févr. 2011 à 14:03
Bien entendu, le calcul des nuitées peut être fait sans bouton dès que l'utilisateur à précisé les deux dates. Ensuite, le calcul des dates est très semblable en javascript et PHP. Même s'il n'y a pas de millisecondes en PHP, il convient dans les deux cas de passer de chaînes de caractères à des entités numériques avant d'opérer une différence.

1/ Commenter le tableau affichant le nombre de nuitées (lignes 138 à 150 du formulaire.php) en placant un <!-- avant et un --> après pour insérer à la suite le tableau suivant :


    


3/ Modifier comme suit le fichier plugins.js situé sur le site dans le même répertoire que ipopeng.htm (en principe formulaire/calendrier)

function fAfterSelected(y,m,d,e) {
var cd=parent.document.demoform.dc1.value,ca=parent.document.demoform.dc2.value;
alert(cd+' '+ca);
var dd=chnToDate(cd),da=chnToDate(ca),msg='',nbn;
nbn=Math.round((da-dd)/MILLIDAY);
if (da && dd) msg=(nbn)?"Nombre de nuités : "+nbn:"Aucune nuité";
parent.document.getElementById('idm').innerHTML=msg;
parent.document.getElementById('nbnuit').value=nbn;
}
function chnToDate(c){var i,t,r=/(\d\d).(\d\d).(\d\d\d\d)/;
if (!(t=r.exec(c))) return null;
for (i=0;i<t.length;i++) while (t[i].substr(0,1)=='0') t[i]=t[i].substr(1);
return new Date(t[3],t[2],t[1]).valueOf();
}


4 / Recharger le formulaire pour faire les tests et vérifier que les nuitées s'affichent non seulement sur la page mais aussi dans la balise input, théoriquement cachée, et arrivent bien lors de l'envoi dans un $_POST["nbnuit"] sur le serveur.

Lorsque tout fonctionne commenter ou supprimer l'alert du fichier plugins.js et ajouter le deuxième d de hidden pour cacher effectivement l'input correspondant. Ouf!
0
Utilisateur anonyme
8 févr. 2011 à 14:20
C'est génial !!
ça marche... Heu ! Ca marche presque...

En fait, le calcul est faux 215 nuits aux lieu de 7...

Ce vais voir ça !!
0
Utilisateur anonyme
8 févr. 2011 à 14:29
GENIAL !

Celle fois ci ça fonctionne impec !!

J'ai remplacé MILLIDAY par 2674800000 et ça roule !!

Merci BEAUCOUP !!!
0
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
8 févr. 2011 à 17:39
D'où sort cette valeur ?
Cela devrait fonctionner encore mieux (et surtout les mois suivants), avec MILLIDAY et en intervertissant t[1] et t[2] dans la dernière ligne de la fonction chnToDate pour obtenir le code suivant.

return new Date(t[3],t[2],t[1]).valueOf();


C'est avec les dates au format anglosaxon de l'exemple ( mm/jj/aaaa ) qu'il convient de faire une inversion. Décidément les anglais font tout à l'envers !
0
Utilisateur anonyme
9 févr. 2011 à 10:48
Hello !

J'ai interverti t[1] et t[2], remit MILLIDAY

Bin, ça à l'air de marcher... Quoique !

A cheval sur deux années (28/12/2011 à 02/01/2012), ça marche plus... Il me sort un nombre négatif (mais c'était pareil avec 2674800000)!

Je comprend pas pourquoi !
0
Utilisateur anonyme
9 févr. 2011 à 11:03
Heu ! Sorry !
J'ai relu tout !, j'ai nettoyé un peu !
Et là, curieusement, ça à l'air de fonctionner même à cheval sur 2 années...
Je continue à tester.
A+
0
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
9 févr. 2011 à 12:40
En regardant plus attentivement le code (c'est toujours instructif), voici une solution plus satisfaisante de modification du script plugings.js.

var _crtCal,_datDpr= _datArr=0;

function fAfterSelected(y,m,d,e) {var nbn,msg='';
if (_crtCal==_startc) _datDpr=new Date(y,m,d).valueOf();
if (_crtCal==_endc) _datArr=new Date(y,m,d).valueOf();
alert(_datDpr+' '+_datArr)
if (_datDpr && _datArr) {nbn=Math.round((_datArr-_datDpr)/MILLIDAY);
msg=(nbn)?"Nombre de nuités : "+nbn:"Aucune nuité";}
parent.document.getElementById('idm').innerHTML=msg;
parent.document.getElementById('nbnuit').value=nbn;
}

Trois variables globales (_crtCal,_datDpr et _datArr ), représentant respectivement le calendrier ouvert, et les deux dates en millisecondes, sont définies et initialisées (voir ci-après) dans différentes fonctions puis mises à jour dans fAfterSelected où les arguments y,m,d permettent maintenant d'actualiser la date correspondant au calendrier en cause sans devoir refaire les deux calculs (la fonction chnToDate est inutile et ne doit plus figurer dans le script).

Par contre, trois autres ajouts sont indispensables dans les fonctions fStartPop, fEndPop et fClearSelected qui figurent dans le même script (lignes 120 à 150 après l'ajout précédent).

Dans les deux premières fonctions, lancées à l'ouverture des calendriers, il s'agit d'ajouter une troisième ligne _crtCal =startc; ou _crtCal=endc; renseignant le calendrier en cause. Les fonctions se présentent alors comme suit après modification (la ligne précédant la fonction fStartPos doit subsister sans modifications).

var _startc,_endc;
function fStartPop(startc,endc) {
  _startc=startc;
  _endc=endc;
  _crtCal=startc; // ajout
  var sd=fParseInput(endc.value); 
  if (!sd) sd=gEnd;
  fPopCalendar(startc, [gBegin,sd,sd]);
}

function fEndPop(startc,endc) {
  _startc=startc;
  _endc=endc;
  _crtCal=endc; // ajout
  var sd=fParseInput(startc.value);
  if (!sd) sd=gBegin; 
  fPopCalendar(endc, [sd,gEnd,sd]);
}


Dans la troisième, il s'agit simplement d'ajouter une première ligne.

function fClearSelected() { // clear the date field and reset the dynamic range.
  _datDpr=_datArr=0; // ajout
_startc.value="";
  _endc.value="";
   fUpdSelect(0,0,0);
  gRange=[gBegin,gEnd];
  gdBegin=new Date(gBegin[0],gBegin[1]-1,gBegin[2]);
  gdEnd=new Date(gEnd[0],gEnd[1]-1,gEnd[2]);
  fRepaint();
}


Sauf erreur de ma part, cette solution devrait répondre à la question posée en préservant toutes les fonctionnalités du script et notamment les changements de présentation ou de configuration susceptibles d'être opérés dans contrast.js

Bonne continuation.
0
Utilisateur anonyme
9 févr. 2011 à 13:29
Pfff ! Quel boulot super !!
Je suis impressionné... J'ai encore des heures de taff pour bien tout saisir !! Vous êtes génial !!

Mais mais mais... je suis très chiant !! Y'a quand même quelques p'tits trucs qui me gène:
Le nbr de nuit qui apparait en 'négatif' tant qu'on ne choisit pas une date de départ (affichage dès la date de départ)!!
'idm' et/ou 'nbnuit' qui ne s'efface pas lorsqu'on 'clear' dans le popup du datepicker
'idm' qui ne s'efface pas lors du 'reset' du formulaire.

Mais je chipote.. Non vraiment merci ! C'est top.
0
Utilisateur anonyme
9 févr. 2011 à 13:43
Heu ! Avec les modifs de variable.

Mon input nbnuit affiche "undefined"
0
007Julien Messages postés 276 Date d'inscription mercredi 22 septembre 2010 Statut Membre Dernière intervention 8 janvier 2014 4
9 févr. 2011 à 21:35
Ce ne sont, en effet, que des petits trucs que vous devriez pouvoir résoudre progressivement.

Je ne comprend pas bien comment le nombre de nuit peut devenir négatif ? Je ne fais pas ce constat sur mon programme de test. A priori cela ne peut se produire que si le test if (_datDpr && _datArr) {...} ne fonctionne pas, essayez peut-être if (_datDpr!= 0 && _datArr!=0) {...}. Le calcul ne devrait être effectué que si les deux dates sont non nulles. Vérifiez donc ce point en plaçant, par exemple, un alert("test OK "+nbn+" "+msg); dans le crochet après le calcul de ces valeurs...

Ensuite, il convient de mettre le nombre de nuit à zéro (comme les messages en blanc var nbn=0,msg='';) dans la fonction fAfterSelected . Ceci devrait résoudre les problèmes d'affichage après clic sur une des dates d'un des calendriers.

Enfin, il convient aussi d'effacer les messages et nombre de valeurs dans la fonction fClearSelected, il suffit pour ce faire d'ajouter les deux lignes suivantes dans cette fonction

parent.document.getElementById('idm').innerHTML ='';
parent.document.getElementById('nbnuit').value='';


Pour bien faire, plutôt que d'éparpiller l'édition de ces valeurs dans les différentes fonctions, il conviendrait de définir une fonction d'édition qui serait appelée à chaque fois.

Sur ces points, je vous laisse la main.
0
Rejoignez-nous