Avatar billede dramsgaard Nybegynder
28. december 2010 - 00:13 Der er 7 kommentarer og
1 løsning

validering af inputfelter

Jeg har lavet flg. script til at validere input fra to felter "pris_fra" og "pris_til".
Felterne må være tomme, eller indeholde positive decimaltal. Hvis begge felter er udfyldte skal "pris_fra" altid være lig med eller mindre end "pris_til".
Problemet er, at hvis feltet "pris_fra" ikke er udfyldt, men feltet "pris_til" er udfyldt bliver dette felt af en eller anden grund ikke valideret. Nogen der har et bud på hvorfor?

<SCRIPT language="JavaScript">
<!--
function validate()
//Valider prisinterval
{
var n=document.SearchForm.Pris_fra.value;
var m=document.SearchForm.Pris_til.value;
var fejl="Fejl: Prisintervallet er ikke korrekt udfyldt!"

if (n==""){n=0;} //hvis 'pris fra' er tom - så giv værdi 0
if (m==""){m=1000000000000;} // hvis 'pris til' er tom - så giv en meget høj værdi

if (n<0 || n > m){alert(fejl);return false;} // er prisinterval 'fra' mindre end 'til' og positivt
if (!n.match(/([1-9]?\d(,\d)?)$/)){alert(fejl);return false;} // er 'pris fra' et nummer
if (!m.match(/([1-9]?\d(,\d)?)$/)){alert(fejl);return false;} // er 'pris til' et nummer

return true;
}
//-->
</SCRIPT>
Avatar billede webweaver Praktikant
28. december 2010 - 01:47 #1
Hvilken validation er det at den ikke "gennemgår"? Og når du siger at den ikke bliver valideret, mener du så at du kan udfylde formen forkert, og alligevel gå videre, eller mener du at du kan udfylde den rigtigt, og så alligevel få en fejl ... eller?

pris_fra er ikke udfyldt, og derfor bør n = 0, så dermed er den første af de 3 nederste if sætninger ikke aktuelle, og så er der kun den sidste if sætning tilbage, som arbejder med pris_til. Den som giver fejl?
Avatar billede softspot Forsker
28. december 2010 - 09:03 #2
Prøv at indsætte denne kodeblok i head-sektionen på et rent HTML-dokument og se om funktionen ikke lever op til dine krav (du kan evt. selv oprette flere tests, som kalder med andre værdisæt du ønsker at teste):

  <script type="text/javascript">
    function validatePrisinterval(nIn,mIn) {
      debug("(nIn: " + nIn + ", mIn: " + mIn + ") ");

      // sæt standardværdier for tomme intervalgrænser
      if (nIn == "") { nIn = "0"; }
      if (mIn=="") { mIn="2000000000"; }

      // undersøg om til og fra priserne er tal
      var isNumber = /^\d+(,\d*){0,1}$/;

      if (!isNumber.test(nIn)) return false;
      if (!isNumber.test(mIn)) return false;
     
      // omsæt strengene til reelle tal
      var n = parseFloat(nIn.replace(/,/,"."), 10);
      var m = parseFloat(mIn.replace(/,/,"."), 10);

      debug("n: " + n + ", m: " + m + " => ");
     
      // undersøg om tallene ligger indenfor de gyldige grænseværdier
      if (n > m) return false;

      return true;
    }

    // UNITTESTS!!!

    // intervaller som burde give fejl
    testFn(!validatePrisinterval("", "-1"));
    testFn(!validatePrisinterval("0", "-1"));
    testFn(!validatePrisinterval("950", "200"));
    testFn(!validatePrisinterval("alfa1", "alfa2"));
   
    // intervaller som burde være gyldige
    testFn(validatePrisinterval("", ""));
    testFn(validatePrisinterval("0", "1"));
    testFn(validatePrisinterval("10", ""));
    testFn(validatePrisinterval("10,010", ""));
    testFn(validatePrisinterval("10,010", "432,19"));

    // funktion der udskriver tekst i browseren
    function debug(txt) {
      document.write(txt);
    }

    // funktion der giver en tilbagemelding på testen
    function testFn(fnRes) {
      fnRes ? debug("OK<br>") : debug("FEJLEDE<br>");
    }
  </script>

Såvidt jeg kan se har du flg. problemer med din kode:

* match findes ikke på et strengobjekt (som standard)
* dit regulære udtryk er ikke korrekt
* du arbejder kun med strenge og strengsammenligning, hvilket kan give nogle udfordringer ifht. værdisammenligninger

Jeg har derfor lavet et regulært udtryk der gemmes i isNumber i stedet. På det regulære udtryk kan funktionen test kaldes. Denne tager en streng som parameter og returnerer true hvis strengens indhold matcher udtrykket, ellers returneres false.

Jeg har desuden valgt at arbejde med streng- og tal-variabler i stedet for at arbejde direkte på strengene hele vejen igennem. Jeg omsætter først strengene til tal efter jeg har valideret dem med det regulære udtryk og dermed burde være sikker på at det er tal der findes i strengene.

Til sidst har jeg flyttet fejlrapporteringsansvaret udenfor valideringsfunktionen, så funktionen kun har et formål, nemlig at validere parametre. Du kan evt. pakke kaldet til validatePrisinterval ind i en anden funktion som sørger for at fejlmelde hvis resultatet af valideringen ikke er tilfredsstillende. F.eks. således:

function validateForm() {
  var fra = document.SearchForm.Pris_fra.value;
  var til = document.SearchForm.Pris_til.value;

  if(!validatePrisinterval(fra,til)) {
    alert("Fejl: Prisintervallet er ikke korrekt udfyldt!");
    return false;
  }

  return true;
}


Jeg har, som nævnt i starten, lavet et sæt testcases, dvs. funktioner der undersøger forskellige inputværdiers påvirkning af funktionens returværdi. Dette er et helt simpelt testsetup, som kan gøres meget mere avanceret, men det giver i det mindste en mulighed for at lave nogle tests, som nemt kan gentages. Når du har et sæt tests stablet på benene, kan du med mindre risiko justere (refactor) koden i din funktion uden større risiko for at introducere nye fejl, da alle dine tests jo gerne skulle fortsætte med at returnere OK, selvom du retter i koden.

NB: Du skal naturligvis fjerne kald til debug-funktionen inden du rykker koden over i produktionsmiljøet, men det havde du nok gættet...
Avatar billede dramsgaard Nybegynder
28. december 2010 - 11:43 #3
Mange tak for svarene... og undskyld det har taget lidt tid for mig at vende tilbage.

webweaver >> Det eneste der giver problemer med det script jeg har lavet er, at den ikke fanger ugyldige værdier når "pris_fra" er tom, og der f.eks. er tekst i "pris_til". Alt andet jeg har testet fanger den. Dvs. hvis jeg f.eks. skriver et gyldigt tal i "pris_fra" og en ugyldig værdi i "pris_til" så bliver det fanget, men ikke hvis "pris_fra" ikke er udfyldt!

softspot >> Jeg er ikke helt på hjemmebane i javaScript, så ja, der er helt sikkert mange fejl i min kode.

Hvis jeg kopierer dit script ind i head sektionen i et tomt html dokument, får jeg 'ok' til alle værdier.
Avatar billede softspot Forsker
28. december 2010 - 11:53 #4
Tanken er, at du skal klippe funktionerne (validatePrisinterval og validateForm) ud og klistre dem ind i din egen side og se om det fungerer med de ændringer jeg har lavet. Du skal dog lige fjerne kaldene til debug-funktionen (i validatePrisinterval) inden du prøver at køre det, da det blot er kode som hjælper med at se hvilke værdier der sendes til validatePrisinterval).

Du kan evt. omdøbe validateForm til validate, hvilker burde gøre at koden passer ind i dit eksisterende setup, så du bare kan køre det uden videre.

At alle linierne giver OK, er blot et udstryk for at alle tests fungerer, så det er godt :-)
Hvis du har andre fra- og til-værdier du vil prøve af, kan du blot lave flere kald til testFn og se hvad der så sker...
Avatar billede dramsgaard Nybegynder
28. december 2010 - 12:09 #5
softspot >> Arh - ok :-)
Jeg har sat det ind, og det ser ud til at virke.
Jeg vil lige test det lidt mere, men du kan vist godt smidde et svar :-)

Lige for min forståelse - hvad er det du siger er galt med den regExp jeg havde før?


...og vil jeg evt. kunne lægge en maks grænse ind i regExp på ex. 100 på flg måde?
/^(100 | \d+(,\d*){0,1})$/
Avatar billede softspot Forsker
28. december 2010 - 12:54 #6
Hmm... jeg var vist for hurtig da jeg dømte match ude som en funktion på en string. Jeg noterede mig blot at FireFox påstod (et eller andet med), at den funktion ikke var defineret, så derfor antog jeg at det var fordi den ikke var standard på en string, men det er den jo. Match-metoden på string returnerer dog et array af matches fundet i strengen, så derfor giver en betingelse der undersøger om resultatet er 0, null eller undefined vel ikke helt mening (i bedste fald burde der testes på length-egenskaben af resultatet)...

Bort set fra det, så vil jeg mene at dit regulære udtryk var forkert, dels pga. din brug af spørgsmålstegn (hvad var din intention med spørgsmålstegnene i dit udtryk?), dels fordi du umiddelbart kræver, at tal ikke må starte med 0, når du rent faktisk tillader 0 som en nedre grænse (det er din default for tomme input i fra-feltet).

Grunden til at jeg lagde det regulære udtryk i en variabel, var for at undgå, at definere det samme udtryk to gange og dermed spare mig selv dobbeltvedligehold, når nu udtrykket skulle ændres (som du jo allerede snakker om nu :-)).

Hvis du skal lave en grænseværdi på 100, vil jeg umiddelbart vælge at implementere den som en ny if-sætning, i stedet for at fedte med regulære udtryk. Det er langt nemmere at vedligeholde og gennemskue på sigt, hvis man ikke er en haj til regulære udtryk (hvilket jeg absolut ikke er)... :-)

Jeg har tilrettet funktionen, så den også tjekker for 100 som maks-værdi i fra-feltet, samt fjernet debug-info. Den ser nu ud som vist nedenfor:

function validatePrisinterval(nIn,mIn) {
  // sæt standardværdier for tomme intervalgrænser
  if (nIn == "") { nIn = "0"; }
  if (mIn == "") { mIn="2000000000"; }

  // undersøg om til og fra priserne er tal
  var isNumber = /^\d+(,\d+){0,1}$/;

  if (!isNumber.test(nIn)) return false;
  if (!isNumber.test(mIn)) return false;
     
  // omsæt strengene til reelle tal
  var n = parseFloat(nIn.replace(/,/,"."));
  var m = parseFloat(mIn.replace(/,/,"."));

  // undersøg om tallene ligger indenfor de gyldige grænseværdier
  if (n > m) return false;
  if (n > 100) return false;

  return true;
}

Med ovenstående rettelse til tjek af max-værdien, bør du tilføje et par nye tests, som sikrer at du får testet det scenarium:

// undersøg om max-intervallet for fra fejler når det overskrides
testFn(!validatePrisinterval("101", "200"));
// undersøg om den maksimale fra-værdi tillades
testFn(validatePrisinterval("100", "120"));
Avatar billede dramsgaard Nybegynder
28. december 2010 - 13:32 #7
Jeg er så absolut heller ikke en haj til RegExp, og har prøvet mig frem nogle gange indtil jeg ramte noget jeg syntes virkede - så kan faktisk ikke helt komme med en fornuftig forklaring på at den endte som den endte :-).
Oprindeligt havde jeg også min regExp i en variabel, men lagde den til sidst ned i hver if sætning for ex. at kunne sætte en grænse på til hvert inputfelt i regExp.

Men ja, jeg er enig i, at det nok vil være mere elegant/nemmere at gøre det i en if sætning.

Jeg takker for hjælpen!
Avatar billede softspot Forsker
28. december 2010 - 14:09 #8
Velbekomme og tak for point :-)
Avatar billede Ny bruger Nybegynder

Din løsning...

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.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester