28. juni 2003 - 11:51Der er
47 kommentarer og 1 løsning
Beregning af hele antal dage mellem to datofelter
Jeg mangler én sidste (ønskelig) funktion i en formular, hvor jeg har to dato-felter (firstinput og secondinput). I felterne indtastes dato for første nat (DD/MM/ÅÅÅÅ) og dato for sidste nat (DD/MM/ÅÅÅÅ). Hvorledes tilføjer jeg et felt, hvori der automatisk skal blive skrevet antal overnatninger ud fra indtastningerne i dato-felterne? Det skal bemærkes, at datoen i de to dato-felter godt kan være ens (f.eks. 28/06/2003 i begge), og resultatet skal så være "1" i mit nye ønskelige felt, "Antal overnatninger".
Der bliver allerede valideret på datoerne nu i min nuværende funktion. Det eneste jeg mangler er som sagt en udregning af samlede antal dage, som en ekstra oplysning til bestillingen.
//Check for firstinput dat = document.frmEnquiry.firstinput.value; if (dat == ""||!regex.test(dat)){ errorMsg += "\n\tFørste overnatning \t- Indtast første nat i dette format: (DD/MM/ÅÅÅÅ)\n"; }else{ dat = dat.split("/"); var tdate = new Date(parseInt(dat[2]),parseInt(dat[1])-1,parseInt(dat[0])); if (tdate.getDate()!=parseInt(dat[0])||tdate.getMonth()+1!=parseInt(dat[1])||tdate.getFullYear()!=parseInt(dat[2])){ errorMsg += "\n\tFørste overnatning \t- Ugyldig dato (DD/MM/ÅÅÅÅ)\n"; }else{dato1=tdate.getTime(); var chdato = new Date().getTime()+ (24*60*60*1000); if (chdato>dato1) errorMsg += "\n\tFørste overnatning \t- Når du benytter denne formular,\n\t\t\t kan du tidligst bestille to dage frem\n" }; }
//Check for secondinput dat = document.frmEnquiry.secondinput.value; // alert(dat); if (dat == ""||!regex.test(dat)){ errorMsg += "\n\tSidste overnatning \t- Indtast sidste nat i dette format: (DD/MM/ÅÅÅÅ)\n"; }else{ dat = dat.split("/"); var tdate = new Date(parseInt(dat[2]),parseInt(dat[1])-1,parseInt(dat[0])); if (tdate.getDate()!=parseInt(dat[0])||tdate.getMonth()+1!=parseInt(dat[1])||tdate.getFullYear()!=parseInt(dat[2])){ errorMsg += "\n\tSidste overnatning \t- Ugyldig dato (DD/MM/ÅÅÅÅ)\n"; }else{ if(dato1>tdate.getTime()) errorMsg += "\n\tSidste overnatning \t- Dato kan ikke være tidligere end første nat\n" }
}
Derudover bruger jeg følgende input-maske (også lavet af dig):
//Script til inputmaske for datofeltet. START var newVal=""; var dd=0; var mm=0; var repeatRemove=0;
function getCharCode(e){ return (e.which)?e.which:e.keyCode; }
function restoreVal(eC,fld){ if (eC==8||repeatRemove>0){ if (newVal.length>repeatRemove){ newVal=newVal.substring(0,newVal.length-repeatRemove) }else{ newVal=""; } } repeatRemove=0; fld.value=newVal; }
function inputDate(e,fld){ removeChar=false; newVal=fld.value; charCode = getCharCode(e); if ((fld.value.length==2 || fld.value.length==5) && charCode==47){newVal+="/";return true;} if (fld.value.length==10 || charCode>57 || charCode<48){ return false; }
newVal=fld.value+String.fromCharCode(charCode)
switch (fld.value.length){ case 0: if (+newVal>3){repeatRemove++;return false;} break; case 1: if (+newVal>31){repeatRemove++;return false;} if (+newVal==00){repeatRemove++;return false;} dd = +newVal; newVal+="/"; break; case 2: newVal=fld.value+"-"+String.fromCharCode(charCode) if (charCode>49){repeatRemove++;return false;} break; case 3: if (charCode>49){repeatRemove++;return false;} break; case 4: var mm = parseInt(newVal.substring(3),10); if (mm==2 && dd>29 || mm>12 || mm==00){repeatRemove++;return false;} if (dd==31 && (mm==4 || mm==6 || mm==9 || mm==11)){repeatRemove++;return false;} newVal+="/"; break; case 5: newVal=fld.value+"-"+String.fromCharCode(charCode) break; case 6: if (charCode<50 || charCode>50){repeatRemove++;return false;} //Tillader 2 som første tal i årstal break; case 7: var yy = parseInt(newVal.substring(6)); if (yy<20 || yy>20){repeatRemove++;return false;} //Tillader 20 som første to tal i årstal break; case 8: var yyy = parseInt(newVal.substring(6)); if (yyy>200){repeatRemove++;return false;} //Tillader kun 0 som trejde tal, hvis første to er 2 og 0. break;
} return true; } //Script til inputmaske for datofelt. SLUT
Hvordan fletter jeg det du nu har lavet, ind i ovenstående?
-- jeg tog selve dato-testen og brugte den (de øverste 20 - 30 linjer) fordi den indeholder en rigtig dato som en del af valideringen ...
-- egentlig var det fordi jeg var doven -- det ligger naturligt for mig *-]
-- men da jeg var igang gik det op for mig, at det kun giver mening at snakke om forskelle i dage, hvis datoerne dur, så min konklusion blev til at vi skulle flette det ind i dit live-script, so from here we go !-)
Lav datochecket til en selvstændig funktion, som kaldes under valideringen med et eller andet som 'dummy'-argument -- f.eks. datocheck('valider') altså skal funktionen datocheck pilles ud af dit checkscript og være noget for sig selv ...
På onchange-eventen på den anden dato kalder du så din datochecker med datocheck(this.form) og indsætter de linjer jeg refererede til i stedet for den (sikkert) manglende afsluning du har i dag:
if (f=='[object]'){(f.forskel.value=Math.floor((tdate.getTime()-dato1)/86400000));} else return errorMsg;
-> Rønving, Jeg må nok bede dig komme med et eksempel (jeg er meget nybegynder indenfor javascript) - eller også må jeg nok opgive; det er jeg selvfølgelig helst fri for. Jeg kan ikke følge dig i din vejledning og aner faktisk ikke, hvad jeg skal ændre og hvor! ;-(
Det kan godt være du er doven (hvilket jeg dog ikke helt tror på), men det er jeg ikke. Jeg leder og forsøger, men det er meget i blinde. Hjælp....
En ny global variabel: fdate defineret samme sted som bla. newVal -- og så:
case 8: var yyy = parseInt(newVal.substring(6)); if (yyy>200){repeatRemove++;return false;} //Tillader kun 0 som trejde tal, hvis første to er 2 og 0. break; case 9: if(fld.name=='firstinput'){ fdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); }else{ sdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); } var forsk = (fdate-sdate)/(24*60*60*1000); fld.form.forskel.value = forsk + 1; //<-- skal den altid lægge en til ?-)
Det er kun input-maske-scriptet der skal ændres -- her får du det hele:
//Script til inputmaske for datofeltet. START var newVal=""; var fdate; var dd=0; var mm=0; var repeatRemove=0;
function getCharCode(e){ return (e.which)?e.which:e.keyCode; }
function restoreVal(eC,fld){ if (eC==8||repeatRemove>0){ if (newVal.length>repeatRemove){ newVal=newVal.substring(0,newVal.length-repeatRemove) }else{ newVal=""; } } repeatRemove=0; fld.value=newVal; }
function inputDate(e,fld){ removeChar=false; newVal=fld.value; charCode = getCharCode(e); if ((fld.value.length==2 || fld.value.length==5) && charCode==47){newVal+="/";return true;} if (fld.value.length==10 || charCode>57 || charCode<48){ return false; }
newVal=fld.value+String.fromCharCode(charCode)
switch (fld.value.length){ case 0: if (+newVal>3){repeatRemove++;return false;} break; case 1: if (+newVal>31){repeatRemove++;return false;} if (+newVal==00){repeatRemove++;return false;} dd = +newVal; newVal+="/"; break; case 2: newVal=fld.value+"-"+String.fromCharCode(charCode) if (charCode>49){repeatRemove++;return false;} break; case 3: if (charCode>49){repeatRemove++;return false;} break; case 4: var mm = parseInt(newVal.substring(3),10); if (mm==2 && dd>29 || mm>12 || mm==00){repeatRemove++;return false;} if (dd==31 && (mm==4 || mm==6 || mm==9 || mm==11)){repeatRemove++;return false;} newVal+="/"; break; case 5: newVal=fld.value+"-"+String.fromCharCode(charCode) break; case 6: if (charCode<50 || charCode>50){repeatRemove++;return false;} //Tillader 2 som første tal i årstal break; case 7: var yy = parseInt(newVal.substring(6)); if (yy<20 || yy>20){repeatRemove++;return false;} //Tillader 20 som første to tal i årstal break; case 8: var yyy = parseInt(newVal.substring(6)); if (yyy>200){repeatRemove++;return false;} //Tillader kun 0 som trejde tal, hvis første to er 2 og 0. break; case 9: if(fld.name=='firstinput'){ fdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); }else{ sdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); } var forsk = (fdate-sdate)/(24*60*60*1000); fld.form.forskel.value = forsk + 1; //<-- skal den altid lægge en til ?-) } return true; } //Script til inputmaske for datofelt. SLUT
-- jeg har kaldt feltet for forskel, så det skal du lige tilpasse ,-) Prøv det !-)
Okay, jeg har nu indsat den nye inputmaske og tilføjet feltet "forskel" i min formular. Der sker bare ikke noget. Selvom jeg indtaster en dato i begge felterne "firstinput" og "secondinput" sker der intet i feltet "forskel", som jo gerne skulle vise antal dage ??
Kan ikke lige forstå, men jeg har heller ikke testet funktionaliteten, din form er jo blevet noget kompleks efterhånden *g*
-- prøv lige efter case 9: at indsætte: alert(fld.name+" | "+fdate) - og lige efter fdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); at indsætte: alert(fdate)
-- fjerndebugging, men forhåbentlig kan vi også få sådan noget til at spille -- i teorien skulle der ikke være noget galt ...
Det er ikke det bedste med fjerne-debugging, men vi kommer forhåbentlig igennem alligevel ,-)
Start med at ændre:
case 9: if(fld.name=='firstinput'){ fdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); }else{ sdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); } var forsk = (fdate-sdate)/(24*60*60*1000); fld.form.forskel.value = forsk + 1; //<-- skal den altid lægge en til ?-) } --- til:
case 9: if(fld.name=='firstinput'){ fdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); }else{ sdate = new Date(newVal.substring(6),newVal.substring(3,5),newVal.substring(0,2)); var forsk = (fdate-sdate)/(24*60*60*1000); alert(forsk+" | "+fld.form.forskel.name); fld.form.forskel.value = forsk + 1; } }
-- den eliminerer med sikkerhed den første fejl -- og så må vi debugge den anden !o]
Efter at have rettet til: alert(forsk+" | "+fld.name);
får jeg nu en alert:
" -1 | secondinput " og derefter en scriptfejl: "Et objekt er obligatorisk" linje 100 tegn 11:
fld.form.forskel.value = forsk + 1;
quote -- da jeg sidst så på dit eksempel sikrede jeg mig, at der var en aktiv form -- det er vel ikke ændret ?-) unquote
Nej, det eneste jeg har ændret er den automatiske opdatering af datoen i feltet "secondinput" i forhold til "firstinput" (secondupdate), da det gav nogle problemer, hvis man skulle rette i feltet "secondinput".
Nu sker der dælme noget! Straks jeg fik formen aktiv igen bliver der skrevet i "forskel"-feltet - dog regner den lidt forkert, så jeg lavede denne linje:
-- gaab, jeg har nogle problemer med kilde-hentning, så jeg bruger 'anderes Methoden' som desværre ikke kan tage linjeskift med over, så alt bliver en mudderdej -- derfor har jeg ikke haft din kode gennem min egen maskine -- beklager ...
Uuha ja, man er nok lidt hurtig til at juble! Okay, den tæller dage nu - :-) Men hvorfor dælen virker valideringen nu ikke? Siden kan heller ikke sendes til "send_email.asp" mere ??? Har du nogen forklaring på dette fænomen?
Når jeg forsøger at trykke "send" på formularen, får jeg nu denne (velkendte) fejl: (bare et nyt sted)
"Et objekt var ventet" linje 244 tegn 1
Linjen er denne: <form method="post" name="frmEnquiry" action="send_email.asp" onSubmit="return CheckForm();">
Har det mon noget at gøre med onSubmit="return CheckForm();" da jeg jo ikke kan få en validering frem. Det er i min web-editor jeg får alle disse fejl-meldinger - i browseren bliver formularen bare ikke sendt afsted - ej heller valideret ??
Jamen, med den anden funktionalitet, som er lagt ind, ville jeg droppe popup-kalenderen -- vi kunne jo lægge en egentlig validering ind under case 9:
Vi har jo lavet alle grundlæggende valideringer vha. inputmasken, vi mangler sådan set kun at teste om februar godt må have 29 dage det pågældende år -- ikke den helt store udfordring -- vi skal bare gøre opmærksom på, at koden bliver irriterende kompliceret, hvis det skal bruges til datoer forbi d. 28/2/2100 *gg*
Ja, jeg er også kommet til den konklusion, at jeg dropper den popup tingest. Jeg bruger jo også selv en pop-up stopper, og flere og flere gør det. Hvilket jeg sagtens kan forstå. //.^_^.\\
Det med at februar godt må have 29 dage har jeg ikke lige tænkt over, men det kunne selvfølgelig være godt at få den med.
Meeeeeeeeeen formularen skal bestemt IKKE bruges til efter 28/2/2100 ;-)
Det var godt nok en smart måde at få tjekket på på datoen 29/2 - det med at den fjerner tegn tilbage til 29.
Men jeg har faktisk opdaget en lille ting: Hvis datoerne involverer et månedskifte med mindre end 31 dage, bliver der talt forkert !!! Jeg har siddet og tjekket efter med gammeldags fingerregning og enkalender. ;:(
Nu er der dælme endnu et problem med dato-felterne! Felterne accepterer ikke, hvis jeg indtaster september som dato. Har oprettet problemet i et nyt spørgsmål: http://www.eksperten.dk/spm/372564
case 9: var yyyy = parseInt(newVal.substring(6)); if (mm == 2 && dd == 29 && yyyy%4 !=0){repeatRemove+=8;return false;}
if(fld.name=='firstinput'){ fdate = new Date(newVal.substring(6),parseInt(newVal.substring(3,5),10)-1,parseInt(newVal.substring(0,2),10)); }else{ sdate = new Date(newVal.substring(6),parseInt(newVal.substring(3,5),10)-1,parseInt(newVal.substring(0,2),10)); var forsk = Math.round((sdate-fdate)/(24*60*60*1000)); fld.form.forskel.value = forsk + 1; } } return true;
Den grundlæggende fejl var at den sidste algoritme ikke havde taget højde for javascripts idiosynkrasi med månedsnumre -- de er jo en mindre end månedsnummeret ...
Derudover skulle jeg lige checke hvorfor den pludselig gave ikke hele tal -- det var simpelthen pga. sommertid, så der må vi regulere for den time mere eller mindre -- nemmest med en round
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.