Læsning, beregning og skivning i felter med JavaScript





Hvad går det ud på?

En af de ting man ofte kan få brug for på sin hjemmeside er noget hvor man i et eller flere felter udfylder nogle værdier, hvorefter der regnes på disse og der returneres en eller flere værdier. Det kan være valutaomregninger eller konvertering fra f.eks. fod og tommer til centimeter, eller noget helt tredje. Her går jeg det igennem med pH-beregninger for svage og middelstærke syrer, da det indeholder de elementer man skal bruge til en generel løsning. Herfra blot er et spørgsmål om at konvertere og opskalere til andre løsninger.

Lad nu være med at gå i sort over ikke at kunne forstå matematikken og kemien i opgaven og fokusér på metodikken i løsningen!

Sådan lige kort hvad udfordringen op opgaven går ud på: Når man skal finde pH for middelstærke og svage syrer, skal man løse ligningen

Ka = [H+] · [B-]
[HB]

Dette er reelt en andengradsligning, der kommer til at se således ud:

x2 + Ka·x - Ka·c = 0

Syrestyrkekonstanten Ka og den nominelle koncentration c er de to værdier man kender, og dem man skal beregne ud fra. x er den aktuelle koncentration af H+, den man skriver som [H+], og er den som man beregner pH ud fra, som pH = -log[H+].

Finten i det er, at andengradsligninger kan have 2 løsninger. Hvis der er 2 løsninger, må en af dem være forkert, så først skal vi løse andengradsligningen og derefter skal vi afgøre hvilken værdi der er rigtig, hvis der er flere muligheder. Den rigtige værdi skal der så regnes videre på, så vi finder den ønskede pH-værdi.


Læsning fra felter

Hvis vi nu starter fra en ende, så skal man til pH-beregningerne bruge to felter, et til den nominelle koncentration (c(syre)) og et til syrestyrkekonstanten (Ka), et script til at lave pH-beregningen og en knap til at eksekvere beregningen. Det der skal bruges i HTML-filen ser således ud:

<FORM ONSUBMIT="Calculate_pH(); return false">
<I>c</I>(syre) (M): <INPUT TYPE="text" ID="Concentration">
<I>K</I><SUB>a</SUB>-værdi: <INPUT TYPE="text" ID="AcidityConstant">

<INPUT TYPE="submit" VALUE="Udregn">
</FORM>

Brugerfladen kommer så til at se således ud:


c(syre) (M):
Ka-værdi:




Så har vi brugerfladen på plads for indtastning. Vi skal også bruge et skrivefelt til siden, så vi har et sted til resultatet. Her bruger vi en DIV, men det skal blot være en tag til tekst. Den skal have en ID, i dette tilfælde pH_value, så vi har noget at genfinde feltet med (Bemærk: bindestreger i ID-navne er forbudt ved JavaScript, fordi de bliver behandlet som et matematisk minus, og derfor gør, at koden ikke fungerer). Så ser koden således ud:

<FORM ONSUBMIT="Calculate_pH(); return false">
<I>c</I>(syre) (M): <INPUT TYPE="text" ID="Concentration">
<I>K</I><SUB>a</SUB>-værdi: <INPUT TYPE="text" ID="AcidityConstant">

<INPUT TYPE="submit" VALUE="Udregn">
</FORM>

<DIV ID="pH_value"></DIV>

Vi skal nu have lavet et script der laver beregningerne. Vi laver scriptet som et eksternt script, dvs. vi laver en .js-fil. Filen kalder vi pH-Calculations.js og lægger i directoriet JavaScripts. Vi skal derfor i HTML-sidens HEAD-tag have linjen

<SCRIPT TYPE="text/javascript" SRC="JavaScripts/pH-Calculations"></SCRIPT>

så JavaScriptet bliver indlæst og klar til brug.


I .js-filen skal vi starte med at oprette den rutine der hedder Calculate_pH, som bliver startet når vi trykker på knappen. Det ser således ud:

function Calculate_pH() {
}

Det første scriptet skal kunne er at læse fra de to felter med ID Concentration og AcidityConstant. Dette gøres ved at definere et par variabler på denne måde:

function Calculate_pH() {
var FieldValueConcentration = document.getElementById("Concentration").value;
var FieldValueAcidityConstant = document.getElementById("AcidityConstant").value;
}


Det er sådan, at for at scriptet kan regne rigtigt, skal begge felter være udfyldte og de to værdier i dette tilfælde SKAL være tal. Tomme felter tester man ved at spørge om feltværdien er "". Om en feltværdi er et tal, kan man spørge på med kommandoen isNaN(). Hvis et eller begge felter er tomme eller indeholder andet end tal, skriver man en fejlbesked i feltet pH_value. Bemærk: Vi spørger ikke direkte på feltværdien, men indirekte ved at se på de to variabler der er dannet ud fra feltværdierne. Den del ser således ud:

if (isNaN(FieldValueConcentration) | FieldValueConcentration == "" | isNaN(FieldValueAcidityConstant) | FieldValueAcidityConstant == "") {
var pH_value = document.getElementById("pH_value");
while(pH_value.firstChild)pH_value.removeChild(pH_value.firstChild)
var ErrorMessage = document.createTextNode("Forkert eller ingen indhold i et eller flere talfelter. Bemærk: Der bruges . (punktum) som decimaladskiller!");
pH_value.appendChild(ErrorMessage);
}

Ingen af de indtastede værdier må være nul eller negative, så det skal der også testes for, før vi begynder at udregne pH-værdien. Vi spørger derfor på, om de to feltværdier er større end nul. Hvis ikke, skriver man en fejlmeddelelse i feltet pH_value.

else if (FieldValueConcentration <= "0" | FieldValueAcidityConstant <= "0") {
var pH_value = document.getElementById("pH_value");
while(pH_value.firstChild)pH_value.removeChild(pH_value.firstChild)
var ErrorMessage = document.createTextNode("Koncentrationer og syrestyrkekonstanter kan ikke være 0 eller negative!");
pH_value.appendChild(ErrorMessage);
}

Vi har nu fået fat i indholdet af de to felter, og sikret os at indholdet er OK, så nu kan vi gå i gang med udregningerne.


Udregningerne

Løsningen af andengradsligningen gør vi ved det der hedder diskriminantmetoden. Den nærmere omstændigheder for matematikken er underordnet, men hvis diskriminanten, D, er negativ er der ingen løsninger på andengradsligningen, er diskriminanten nul er der én løsning og er den større end nul, er der to løsninger. Lige i dette eksempel behøver vi ikke at tage højde for en negativ diskriminant. Når der er en syre i vandet vil der også være en pH at beregne.

Vi fortsætter fra de to foregående test for om de indsatte tal er OK, så rutinen starter med et else, og herfra beregner vi diskriminanteten som en variabel. Hvis diskriminanten er 0 laves der en beregning, og ellers laves der 2 beregninger.

else {
var pH_value = document.getElementById("pH_value");
var Discriminant = Math.pow(FieldValueAcidityConstant,2) + 4*FieldValueConcentration;
if (Discriminant == "0") {
var AcidConcentration = -0.5*FieldValueAcidityConstant;
}
else {
var AcidConcentration1 = -0.5*FieldValueAcidityConstant + 0.5*Math.sqrt(Discriminant);
var AcidConcentration2 = -0.5*FieldValueAcidityConstant - 0.5*Math.sqrt(Discriminant);
}
}

Bemærk, at når diskriminanten er 0, beregnes variablen AcidConcentration, som er den værdi vi skal bruge til den videre beregning af pH, men der ved den anden mulighed bereges variablerne AcidConcentration1 og AcidConcentration2. Det er fordi vi ikke ved hvilken af løsningerne der er den korrekte, dvs. hvilken der er variablen AcidConcentration. Det er det næste der skal regnes på.

Det vi regner på er koncentrationer, så den korrekte værdi må nødvendigvis være større end nul. Den kan til gengæld ikke være større end c(syre), da dette vil være en fysisk umulighed. Så, det vi gør er at spørge på om variablen AcidConcentration1 er mindre end eller lig med 0 eller større end FieldValueConcentration (dvs. den c(syre) vi har indtastet). Hvis dette er tilfældet, er AcidConcentration1 ikke det rigtige resultat, og variablen AcidConcentration er da lig med AcidConcentration2. I modsat fald er variablen AcidConcentration lig med AcidConcentration1. Så ser koden således ud (tilføjelser til det foregående er med fed skrift):

else {
var pH_value = document.getElementById("pH_value");
var Discriminant = Math.pow(FieldValueAcidityConstant,2) + 4*FieldValueConcentration;
if (Discriminant == "0") {
var AcidConcentration = -0.5*FieldValueAcidityConstant;
}
else {
var AcidConcentration1 = -0.5*FieldValueAcidityConstant + 0.5*Math.sqrt(Discriminant);
var AcidConcentration2 = -0.5*FieldValueAcidityConstant - 0.5*Math.sqrt(Discriminant);
}

if (AcidConcentration1 <= "0" | AcidConcentration1 > FieldValueConcentration) {
var AcidConcentration = AcidConcentration2;
}
else {
var AcidConcentration = AcidConcentration1;
}

}

Vi har nu fået beregnet koncentrationen af syre og er klar til at beregne pH-værdien. Vi kalder denne variabel for Result, så vi får tilføjelsen (fremhævet med fed skrift)

else {
var pH_value = document.getElementById("pH_value");
var Discriminant = Math.pow(FieldValueAcidityConstant,2) + 4*FieldValueConcentration;
if (Discriminant == "0") {
var AcidConcentration = -0.5*FieldValueAcidityConstant;
}
else {
var AcidConcentration1 = -0.5*FieldValueAcidityConstant + 0.5*Math.sqrt(Discriminant);
var AcidConcentration2 = -0.5*FieldValueAcidityConstant - 0.5*Math.sqrt(Discriminant);
}

if (AcidConcentration1 <= "0" | AcidConcentration1 > FieldValueConcentration) {
var AcidConcentration = AcidConcentration2;
}
else {
var AcidConcentration = AcidConcentration1;
}

var Result = document.createTextNode("pH = " + -1*Math.log10(AcidConcentration));

}

Fordi der ikke er brug for noget speciel tekstformatering på det der skal skrives, er der her brugt document.createTextNode(). Har man brug for noget tekstformatering vil man i stedet bruge en løsning med innerHTML (bliver gennemgået i et andet sted). MEN, vi er nu klar til at skrive resultatet på siden i det felt vi har oprettet til formålet.


Skrivning i felter

Vi har nu resultatet og skal have det skrevet til feltet pH_value, og så er vi i mål. Dette gøres med en appendChild som ved fejlmeddelelserne, blot skal vi denne gang have skrevet noget tekst + variabel i stedet for ren tekst. Det færdige JavaScript, med de sidste linjer til løsningen med fed skrift, ser så således ud:

function Calculate_pH() {
var FieldValueConcentration = document.getElementById("Concentration").value;
var FieldValueAcidityConstant = document.getElementById("AcidityConstant").value;


if (isNaN(FieldValueConcentration) | FieldValueConcentration == "" | isNaN(FieldValueAcidityConstant) | FieldValueAcidityConstant == "") {
var pH_value = document.getElementById("pH_value");
while(pH_value.firstChild)pH_value.removeChild(pH_value.firstChild)
var ErrorMessage = document.createTextNode("Forkert eller ingen indhold i et eller flere talfelter. Bemærk: Der bruges . (punktum) som decimaladskiller!");
pH_value.appendChild(ErrorMessage);
}


else if (FieldValueConcentration <= "0" | FieldValueAcidityConstant <= "0") {
var pH_value = document.getElementById("pH_value");
while(pH_value.firstChild)pH_value.removeChild(pH_value.firstChild)
var ErrorMessage = document.createTextNode("Koncentrationer og syrestyrkekonstanter kan ikke være 0 eller negative!");
pH_value.appendChild(ErrorMessage);
}


else {
var pH_value = document.getElementById("pH_value");
var Discriminant = Math.pow(FieldValueAcidityConstant,2) + 4*FieldValueConcentration;
if (Discriminant == "0") {
var AcidConcentration = -0.5*FieldValueAcidityConstant;
}
else {
var AcidConcentration1 = -0.5*FieldValueAcidityConstant + 0.5*Math.sqrt(Discriminant);
var AcidConcentration2 = -0.5*FieldValueAcidityConstant - 0.5*Math.sqrt(Discriminant);
}

if (AcidConcentration1 <= "0" | AcidConcentration1 > FieldValueConcentration) {
var AcidConcentration = AcidConcentration2;
}
else {
var AcidConcentration = AcidConcentration1;
}

var Result = document.createTextNode("pH = " + -1*Math.log10(AcidConcentration));

while(pH_value.firstChild)pH_value.removeChild(pH_value.firstChild)
pH_value.appendChild(Result);

}

}

pH-beregneren er nu klar til brug:


c(syre) (M):
Ka-værdi:




Har man brug for det, kan man få rutinen til at skrive flere mellemregninger til flere felter. For denne type beregninger vil man f.eks. have en interesse i at få den beregnede koncentration af H+, da denne er relevant for kemikere, og for studerende vil man også gerne have de to løsninger på andengradspolynomiet, da det er noget af det de typisk skal skrive i deres opgave/rapport. Dette gøres ved at lave flere felter og lave en appendChild til disse.