One of the things you may need quite often for your website, is a set of fields, where you enter data, and some routine does something with the data, e.g. use it for calculations, and return one or more values or answers. It might be exchange rates for currency or conversion of foot and inches to centimeters or something entirely different. Here I use pH calculations for weak and almost strong acids, as it contains the elements needed for a generic solution. From here, it is just a matter of changing names and scaling to make it work for other applications.

**Don't fret over not understanding the math and chemistry in the example and keep your focus on the method used for the solution!**

Briefly, this is what the challenge is all about: When calculating pH for almost strong and weak acids, you have to solve the equation

This is really just a quadratic equation, which will look like this:

x^{2} + *K*_{a}·x - *K*_{a}·*c* = 0

The dissociation constant for the acid*K*_{a} and the nominal concentration *c* are the two values we know, and the ones to use for the calculation. x is the actual concentration of H^{+}, the one you write as [H^{+}], and it is the one by which you calculate pH as pH = -log[H^{+}].

The trick is that quadratic equations can have 2 answers. If you have 2 answers (i.e. 2 concentrations), one of them must be wrong, so first you have to solve the quadratic equation, and then, if you have more than one answer, you have to determine which answer is the right one. After this, the right answer/value has to be used for calculating the required pH value.

Briefly, this is what the challenge is all about: When calculating pH for almost strong and weak acids, you have to solve the equation

K_{a} = | [H^{+}] · [B^{-}] |

[HB] |

This is really just a quadratic equation, which will look like this:

x

The dissociation constant for the acid

The trick is that quadratic equations can have 2 answers. If you have 2 answers (i.e. 2 concentrations), one of them must be wrong, so first you have to solve the quadratic equation, and then, if you have more than one answer, you have to determine which answer is the right one. After this, the right answer/value has to be used for calculating the required pH value.

Staring at the beginning, you need two fields for the pH calculations, one for the nominal concentration (*c*(syre)) and one for the dissociation constant (*K*_{a}), a script for the doing the actual pH calculation and a button for executing the calculation. The part needed for the HTML file looks like this:

Then the user interface looks like this:

Now we have the user interface in place to submitting values. We also need a field for writing the result on the page. Here we use a DIV, but is just has to be a tag for text. It has to have an ID, in this case pH_value, so we have a way of finding the field (Note: using dashes in ID names is no-go for JavaScript, as they are perceived as a mathematical minus, thereby making the code fail). Then the code looks like this:

Now we need to create a script for the calculations. We make the script as an external script, i.e. we create a .js file. The file we name pH-Calculations.js and place in the directory JavaScripts. Therefore we need to ad this line to the HEAD tag of the HTML file

so the JavaScriptet is read and ready for use.

In the .js file, we start by creating a routine called Calculate_pH, which is executed when clicking the button. It looks like this:

The first thing the script has to do en read the content of the two fields with the ID Concentration and AcidityConstant. This is done by defining two variables like this:

For the script to do a correct calculation, both fields needs to be filled out, and in this case both values MUST be numbers. Empty fields are found by asking if the field value is "". Whether the field value is a number, you can ask by using the command isNaN(). If one or more fields are empty or contains something other than a number, you write an error message in the field pH_value.**Note: We do not check the field value directly but indirectly by checking the variable created from the field values.** That part looks like this:

None of the entered values can be zero or negative, so you need to test for this as well, before starting the pH calculations. Therefore we ask whether the values are greater than zero. If not, you write an error message in the field pH_value.

We now have the content of the two fields and ensured that they are valid, so now we can start the calculations.

<FORM ONSUBMIT="Calculate_pH(); return false">

<I>c</I>(acid) (M): <INPUT TYPE="text" ID="Concentration">

<I>K</I><SUB>a</SUB> value: <INPUT TYPE="text" ID="AcidityConstant">

<INPUT TYPE="submit" VALUE="Calculate">

</FORM>

<I>c</I>(acid) (M): <INPUT TYPE="text" ID="Concentration">

<I>K</I><SUB>a</SUB> value: <INPUT TYPE="text" ID="AcidityConstant">

<INPUT TYPE="submit" VALUE="Calculate">

</FORM>

Then the user interface looks like this:

Now we have the user interface in place to submitting values. We also need a field for writing the result on the page. Here we use a DIV, but is just has to be a tag for text. It has to have an ID, in this case pH_value, so we have a way of finding the field (Note: using dashes in ID names is no-go for JavaScript, as they are perceived as a mathematical minus, thereby making the code fail). Then the code looks like this:

<FORM ONSUBMIT="Calculate_pH(); return false">

<I>c</I>(acid) (M): <INPUT TYPE="text" ID="Concentration">

<I>K</I><SUB>a</SUB> value: <INPUT TYPE="text" ID="AcidityConstant">

<INPUT TYPE="submit" VALUE="Calculate">

</FORM>

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

<I>c</I>(acid) (M): <INPUT TYPE="text" ID="Concentration">

<I>K</I><SUB>a</SUB> value: <INPUT TYPE="text" ID="AcidityConstant">

<INPUT TYPE="submit" VALUE="Calculate">

</FORM>

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

Now we need to create a script for the calculations. We make the script as an external script, i.e. we create a .js file. The file we name pH-Calculations.js and place in the directory JavaScripts. Therefore we need to ad this line to the HEAD tag of the HTML file

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

so the JavaScriptet is read and ready for use.

In the .js file, we start by creating a routine called Calculate_pH, which is executed when clicking the button. It looks like this:

function Calculate_pH() {

}

}

The first thing the script has to do en read the content of the two fields with the ID Concentration and AcidityConstant. This is done by defining two variables like this:

function Calculate_pH() {

var FieldValueConcentration = document.getElementById("Concentration").value;

var FieldValueAcidityConstant = document.getElementById("AcidityConstant").value;

}var FieldValueAcidityConstant = document.getElementById("AcidityConstant").value;

For the script to do a correct calculation, both fields needs to be filled out, and in this case both values MUST be numbers. Empty fields are found by asking if the field value is "". Whether the field value is a number, you can ask by using the command isNaN(). If one or more fields are empty or contains something other than a number, you write an error message in the field pH_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("Incorrect or missing content in one or more fields. Note: The system uses . (dot/full stop) as decimal mark!");

pH_value.appendChild(ErrorMessage);

var ErrorMessage = document.createTextNode("Incorrect or missing content in one or more fields. Note: The system uses . (dot/full stop) as decimal mark!");

pH_value.appendChild(ErrorMessage);

}

None of the entered values can be zero or negative, so you need to test for this as well, before starting the pH calculations. Therefore we ask whether the values are greater than zero. If not, you write an error message in the field 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("Concentrations and dissociation constants cannot be less than or equal to 0!");

pH_value.appendChild(ErrorMessage);

var ErrorMessage = document.createTextNode("Concentrations and dissociation constants cannot be less than or equal to 0!");

pH_value.appendChild(ErrorMessage);

}

We now have the content of the two fields and ensured that they are valid, so now we can start the calculations.

Solving the quadratic equation is done using the discriminant method. The details for the method are irrelevant here, but if the discriminant is negative, there is no solution to the equation, if the discriminant is zero, there is one solution, and if it is positive, you have two solutions. For this particular example, we don't have to account for a negative discriminant. When there is an acid in the water, you will also have a pH to calculate.

We continue from the previous tests, as to whether the inserted values are valid, starting with an else, and from here we calculate the discriminant as a variable. If the discriminant is 0 you do one calculation, and otherwise you do two calculations.

Notice that when the discriminant is 0, we calculate the variable AcidConcentration, which is the value used for the continued calculation of pH, whereas with the other option, you calculate the variables AcidConcentration1 and AcidConcentration2. This is because we don't know which solution is the right one, at this point, i.e. which one is the variable AcidConcentration. That is the next step.

What we are calculating is concentrations, so the correct value must be more than 0. On the other hand, it can't be more than*c*(acid), as this is physically impossible. So, what we do is asking whether the variable AcidConcentration1 is less than or equal to 0 or bigger than FieldValueConcentration (i.e. the *c*(acid) we have entered). If that's the case, AcidConcentration1 is not the right result and the variable AcidConcentration is equal to AcidConcentration2. If not, then the variable AcidConcentration is equal to AcidConcentration1. Then the code looks like this (the additions to the previous code are highlighted in bold typeface):

Now we have calculated the concentration of acid and we are ready to calculate the pH value. We call this variable Result, then we get the addition (highlighted in bold)

As we don't need any special formatting of the text here, we use document.createTextNode(). If we had needed formatting of the text, we would have used a solution with innerHTML (how to do this is shown elsewhere). BUT, we are now ready to write the result on the page, in the field we have created for this.

We continue from the previous tests, as to whether the inserted values are valid, starting with an else, and from here we calculate the discriminant as a variable. If the discriminant is 0 you do one calculation, and otherwise you do two calculations.

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);

}

var AcidConcentration2 = -0.5*FieldValueAcidityConstant - 0.5*Math.sqrt(Discriminant);

}

}

Notice that when the discriminant is 0, we calculate the variable AcidConcentration, which is the value used for the continued calculation of pH, whereas with the other option, you calculate the variables AcidConcentration1 and AcidConcentration2. This is because we don't know which solution is the right one, at this point, i.e. which one is the variable AcidConcentration. That is the next step.

What we are calculating is concentrations, so the correct value must be more than 0. On the other hand, it can't be more than

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);

}

var AcidConcentration2 = -0.5*FieldValueAcidityConstant - 0.5*Math.sqrt(Discriminant);

}

if (AcidConcentration1 <= "0" | AcidConcentration1 > FieldValueConcentration) {

var AcidConcentration = AcidConcentration2;

}

}

else {

var AcidConcentration = AcidConcentration1;

}

}

}

Now we have calculated the concentration of acid and we are ready to calculate the pH value. We call this variable Result, then we get the addition (highlighted in bold)

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);

}

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));

}

As we don't need any special formatting of the text here, we use document.createTextNode(). If we had needed formatting of the text, we would have used a solution with innerHTML (how to do this is shown elsewhere). BUT, we are now ready to write the result on the page, in the field we have created for this.

We now have the result and have to write it in the field pH_value, and then we are done. This is done using appendChild as we did with the error messages, only this time we need to write some text + variable instead of text only. The finished JavaScript, including the last lines for the solution, including the use of bold text, looks like this:

The pH calculator is now ready for use:

If needed, you can make the script write the intermediate results in additional fields. For this particular calculation, you might have an interest in getting the calculated concentration of H^{+}, as this is relevant for chemists, and for students the two answers to the quadratic equation is also of relevance, as this is something they usually have to write in their reports. This is done by adding more fields/tags and make an appendChild for these.

function Calculate_pH() {

if (isNaN(FieldValueConcentration) | FieldValueConcentration == "" | isNaN(FieldValueAcidityConstant) | FieldValueAcidityConstant == "") {

else if (FieldValueConcentration <= "0" | FieldValueAcidityConstant <= "0") {

else {

var AcidConcentration1 = -0.5*FieldValueAcidityConstant + 0.5*Math.sqrt(Discriminant);

var AcidConcentration2 = -0.5*FieldValueAcidityConstant - 0.5*Math.sqrt(Discriminant);

}

}

var FieldValueConcentration = document.getElementById("Concentration").value;

var FieldValueAcidityConstant = document.getElementById("AcidityConstant").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("Incorrect or missing content in one or more fields. Note: The system uses . (dot/full stop) as decimal mark!");

pH_value.appendChild(ErrorMessage);

var ErrorMessage = document.createTextNode("Incorrect or missing content in one or more fields. Note: The system uses . (dot/full stop) as decimal mark!");

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("Concentrations and dissociation constants cannot be less than or equal to 0!");

pH_value.appendChild(ErrorMessage);

var ErrorMessage = document.createTextNode("Concentrations and dissociation constants cannot be less than or equal to 0!");

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 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_value.appendChild(Result);

}

}

The pH calculator is now ready for use:

If needed, you can make the script write the intermediate results in additional fields. For this particular calculation, you might have an interest in getting the calculated concentration of H