7 Replies Latest reply on Nov 28, 2013 10:25 AM by gkaiseril

    Prevent field from displaying an average until all inputs defined

    Nick in Toronto

      Within an Acrobat form, I am calculating the average of 6 values. Each value is selected from a different dropdown menu. The default value of each dropdown menu is 0. The average is displayed in a text field.


      I want the average field to remain blank until all dropdowns have a value greater than zero. Also, if one of the dropdown values changes back to 0, I want the average menu to revert to " ".


      I am new to Javascript. After many hours of playing around with loops, arrays, "some" methods, if/else etc., I am raising the white flag and looking for assistance.


      I would greatly appreciate some advice on how to code this.


      Thanks - Nick

        • 1. Re: Prevent field from displaying an average until all inputs defined
          George_Johnson MVP & Adobe Community Professional

          Try something like the following as the custom calculation script for the field that calculates the average:

           

          // Custom calculation script for text field

          (function () {

           

              // Initialize variables

               var i, v, sum = 0, nCount = 0;

           

              // Loop through the six dropdowns...

               for (i = 1; i < 7; i += 1) {

           

                  // Get the current field value

                  v = getField("dropdown" + i).value;

           

                  // Add value to the sum and increment the counter if the question has been answered and isn't 0

                  if (v != 0) {

                     sum += v;

                     nCount += 1;

                 }

           

              }

           

              // Set this field's value

              if (nCount == 6) {

           

                 // Set to the average

                  event.value = sum / nCount;

           

             } else {

           

                 // Set to blank if all questions haven't been answered

                  event.value = "";

           

             }

           

          })();

           

           

          This code assumes the dropdown fields are named "dropdown1", "dropdown2", ..."dropdown6". You'll have to edit the code to match the fields names you're using.

          • 2. Re: Prevent field from displaying an average until all inputs defined
            John Frederick Chionglo Level 1

            Hi Nick in Toronto,

             

            I too find it challenging to code problems like the one you just described. To cope with this type of challenge, I draw a process diagram of the application logic. Based on this diagram, I organize my code. Perhaps this method might help you code your application too.

             

            Application Logic Description

             

            A user can select a zero value (T0 – T5) or select a non-zero value (T6 – T11) for each of the six fields.

            There is a counter for the number of non-zero values selected (P6). This counter is incremented whenever a non-zero value is selected, and decremented when a zero value is selected.

             

            There is a seventh field for the average of the 6 numbers in the fields.

             

            If the number of non-zero values is 6 and the field for the average is blank, the average is computed and displayed in the seventh field (T12). If the number of non-zero values is less than 6 and the field for the average is not blank, the seventh field is set to a blank (T13).

             

            Application Logic Diagram

             

            Presentation1.jpg

            Application Code Organization

             

            There are several ways to implement the application logic. Here is one way.

             

            1. Define a document-level variable for the counter.
            2. For each field, the MouseUp event should
              1. Increment the counter if a non-zero value is selected, or decrement the counter if a zero value is selected.
              2. Check if the counter (the number of non-zero value) is 6. If it is 6, compute the average of the six fields and set the seventh field to the average. If it is less than six, set the seventh field to a blank.

             

            Regards,

            John (in the GTA)

            1 person found this helpful
            • 3. Re: Prevent field from displaying an average until all inputs defined
              Nick in Toronto Level 1

              John,

               

              Thanks for taking the time to share your thought process. It took me a few reads to fully understand it, but this is definitely a planning/problem solving approach I will use in the future. I'm sure it will help other users too.

               

              Nick

              • 4. Re: Prevent field from displaying an average until all inputs defined
                John Frederick Chionglo Level 1

                Hi Nick,

                 

                Petri Net Method

                 

                Researchers of Petri Nets from 1962 to about 1990 developed the main ideas (including the basic graphics notations) of the “thought process” I used. One of the literature I read on Petri Nets is the textbook (except for the chapters on Grafcet),

                 

                David and Alla (1992). Petri Nets and Grafcet: Tools for Modeling Discrete Event Systems. New York: Prentice Hall.

                 

                If you want to research the topic on your own, there is a bibliography on Petri Nets.

                 

                Missed Requirement

                 

                It occurred to me that we missed the possibility that a user can select a non-zero value given that a non-zero value is currently selected (T14 – T19) for each of the six fields. Here is the diagram with this requirement.

                 

                Presentation2.jpg

                 

                Since we agree on the general interpretation of the diagram, I am combining several graphics to create a new, more concise diagram. Of course, this is a cryptic diagram to someone who do not agree with the earlier diagram.

                Presentation3_Page_1.jpg

                 

                Additional Requirement

                 

                We can also include the cumulative sum of the non-zero values selected by the user (P8), similar to the cumulative number of non-zero values selected (P6). In this case, a document-level variable for the cumulative sum should be defined, and updated along with counter. When the computation for the average is needed, the cumulative sum is already available and the average is computed by dividing the cumulative sum by the number of non-zero values selectes: m(P8) / m(P6) .

                 

                Presentation3_Page_2.jpg

                 

                If we do this, we would have done something very interesting: there are no for-loops in the code.

                 

                 

                Regards,

                John

                • 5. Re: Prevent field from displaying an average until all inputs defined
                  gkaiseril MVP & Adobe Community Professional

                  You could also set and unset bits within a variable to determine when to perform the calculation but that might be more complex than just trying the perform the calculation and only displaying the results if the needed data is available.

                   

                  There is nothing wrong with any loops in a program. It can save a lot of repetitive coding so the code could be easier to maintain. One could also set up code to exit the attempt to calculate the average when a zero is found.

                  • 6. Re: Prevent field from displaying an average until all inputs defined
                    John Frederick Chionglo Level 1

                    I tried to implement the application logic based on the diagram I proposed earlier. I could not compute the average using only Mouse Up scripts attached to the Dropdown fields and a Calculation script attached to the text field (average).

                     

                    I found another way to implement the application logic for computing the average using document variables (see Figure 1), Keystroke scripts in Dropdown fields (Figure 2, for incrementing or decrementing sum2 and count2) and a Calculation script in the Text field (Figure 3, for computing the average).

                     

                    Presentation5.jpg

                     

                    In the Dropdown fields’ properties, I also unchecked the ‘Check spelling’ and checked the ‘Commit selected value immediately’ checkboxes.

                    • 7. Re: Prevent field from displaying an average until all inputs defined
                      gkaiseril MVP & Adobe Community Professional

                      The following script can be used for the custom JavaScript calcution for the average field:

                       

                      // document level scripts;
                      function GetField(cName) {
                      // get field cName with error handling;
                      var oField = this.getField(cName);
                      if(oField == null) app.alert("Error accessing field " + cName, 0, 0);
                      return oField;
                      }

                      function Average(aFieldNames) {
                      // average array of field values;
                      // return null string if any value is 0 or empty string;
                      var nValue;
                      var nSum = 0;
                      var nAvgerage = "";
                      var oField;
                      for(i = 0; i < aFieldNames.length; i++) {

                       

                      oField = GetField(aFieldNames[i]);
                      if(oField == null) nValue = 0;
                      else nValue = oField.value;
                      if(nValue == 0) {
                      i = aFieldNames.length;
                      nAverage = "";
                      } else {
                      nSum += Number(nValue);
                      nAverage = nSum / aFieldNames.length;
                      }
                      }
                      return nAverage;
                      }
                      // end document level scripts;

                       

                      // custom calculation script for average of fields;
                      event.value = Average(["Dropdown1.0", "Dropdown1.1", "Dropdown1.2", "Dropdown1.3", "Dropdown1.4", "Dropdown1.5"]);

                      // ene custom calculation script for average of fields;

                       

                      The document level scripts can be placed as a document level script or kept in the field's custom calculation script. The funcitions will work with any number of fields and is not dependent upon a given set of field names.