Copy link to clipboard
Copied
Greetings all!
I have a form which contains a series of radio button groups which, when selected, will generate a total score in a textbox based on which buttons are selected. I am looking for the specific functionality of having the total textbox hidden until a button from each group has been selected, rather than the total box showing a running tally as a selection is made in each group.
Basically, I have a textbox: "Total" which will be calculated by the points earned in Groups 1, 2, 3, & 4. Currently, when no buttons are selected, the Total field displays "0". When a selection of "5" is made in Group 1, the Total field now displays "5". What I want is for the Total field to remain hidden until a button has been checked in Groups 1, 2, 3, & 4.
I believe the solution to my question involves writing JavaScript in either the Calculate or Validate tab in the "Total" textbox. I have no experience with JavaScript and all forums I've found up to this point don't quite get at my exact issue. Any help
Read this article:
https://acrobatusers.com/tutorials/show_hide_fields/
You can find out more about radiobuttons and checkboxes here:
https://www.pdfscripting.com/public/Checkboxes-and-Radio-Buttons.cfm
Now, for your specific solution you'll need to use a calculation script in the "Total" field. It is best to group the radio button groups so they can be handled together.
By this I mean name grouping. So "Area1.RadioGroup1" "Area1.RadioGroup2", etc. So Area1 is the field name group.
So this
...The test in the "if" statement is specific to radiobuttons, i.e., it tests for a value of Not "Off". For text fields that contain numbers you'll need to test for an empty field or 0.
if(aTextBox.every(function(a){return (a.value != "") && (a.value != 0)}))
For the summation, the "+" operator in JavaScript is both addition and concatonation. Which operation it performs depends on whether it value is interpreted as a number or string. And So, the code needs to be explicit.
aTextBox.forEach(
...This type of display behavior is best handled with a custom format script. Formatting changes the display of a field, but not the underlying value.
You can read more about it here:
https://acrobatusers.com/tutorials/formatting_text_fields/
Copy link to clipboard
Copied
Read this article:
https://acrobatusers.com/tutorials/show_hide_fields/
You can find out more about radiobuttons and checkboxes here:
https://www.pdfscripting.com/public/Checkboxes-and-Radio-Buttons.cfm
Now, for your specific solution you'll need to use a calculation script in the "Total" field. It is best to group the radio button groups so they can be handled together.
By this I mean name grouping. So "Area1.RadioGroup1" "Area1.RadioGroup2", etc. So Area1 is the field name group.
So this code gets a list of all the radio button groups
var aRadGrps = this.getField("Area1").getArray();
// This tests to see if all fields are selected
if(aRadGrps.every(function(a){return a.value != "Off"}))
{ // Now you can calculate the total and make it visible
event.target.display = display.visible;
var sum = 0;
aRadGrps.forEach(function(a){sum+=a.value});
event.value = sum;
}
else // Make hidden
event.target.display = display.hidden;
Copy link to clipboard
Copied
Greetings Thom,
Thank you for your reply! The code worked great for my radio button groups! Now I'm trying to get the same functionality from my "Sub-total" fields to my "Total" fields to my "Grand Total" field.
My radio button groups are "Area1.RadioGroupX"-"Area10.RadioGroupX".
I named 5 of my 10 Sub-total Fields "Area11.TextBox1" "Area11.TextBox2"..."Area11.TextBox5" and the other 5 are "Area12.TextBox1"..."Area12.TextBox5".
I need the TextBoxes in Area11 to add up and display in "Area13.TextBox1", and I need Area12 to add up and display in "Area14.TextBox1". Then I need Area13 and Area14 to average together and display in "Area15.TextBox1" for a grand total.
I tried to take the code you provided to total up my radio boxes and rewrite it to refer to the desired textboxes instead, it's halfway working... Here's what I created based off of your code:
var aTextBox = this.getField("Area11").getArray();
if(aTextBox.every(function(a){return a.value != "Off"}))
{event.target.display = display.visible;
var sum = 0;
aTextBox.forEach(function(a){sum+=a.value});
event.value = sum;}
else // Make hidden
event.target.display = display.hidden;
Like I said, it's only halfway working. It'll correctly add up the fields if I fill them out in order, but if I start from the bottom and work my way up, the total values stack in front of eachother (instead of 20+40=60, I get 2040, etc.). Additionally, the field isn't hidden until all subvalues have been created.
Thanks again for your help, it is greatly appreciated!!!
Copy link to clipboard
Copied
The test in the "if" statement is specific to radiobuttons, i.e., it tests for a value of Not "Off". For text fields that contain numbers you'll need to test for an empty field or 0.
if(aTextBox.every(function(a){return (a.value != "") && (a.value != 0)}))
For the summation, the "+" operator in JavaScript is both addition and concatonation. Which operation it performs depends on whether it value is interpreted as a number or string. And So, the code needs to be explicit.
aTextBox.forEach(function(a){sum+=Number(a.value)});
Copy link to clipboard
Copied
Thanks again! That worked perfectly!
Now that my form is working properly, I've identified one final function I'd like the form to have. As this form is yielding a grade of a performance, I'd love for there to be a way for the text "NO GO" to appear in the "Grand Total" field should either of the following criteria be met:
1) The total final score is below 80%
2) If one of more radio buttons in the "Not Proficient" or "0" column are selected.
To explain #2 a bit, my form has 5 columns worth 5,4,3,2,0 respectively (which I've done by assigning the corresponding number to the Radio Button Choice in each of the buttons in each group). If a student earns any "0"s, the entire performance must be redone and reassessed.
So if a student earns an 85%, I'd like "85%" to display in the Grand Total field (This is currently happening).
If a student earns a 75%, I'd like the Grand Total field to display "75% NO GO"
If a student scores ANY "0"s (regardless of whether or not the final % is over 80), I'd like the Grand Total field to display "XX% NO GO"
Thanks in advance!
Copy link to clipboard
Copied
This type of display behavior is best handled with a custom format script. Formatting changes the display of a field, but not the underlying value.
You can read more about it here:
https://acrobatusers.com/tutorials/formatting_text_fields/
Copy link to clipboard
Copied
Thanks! I was able to use that article to solve the first half of my issue, but I couldn't figure out how to solve my second request. If the "0" radio button is selected in any group, I want the field to display "NO GO". I'm not sure how to reference an isolated radio button within all of my groups.
Here's what I tried, but it didn't work. Like I said, I'm not sure how to reference the buttons I'm trying to reference.
if(radgrpchoice = 0) event.value = "NO GO"
Thanks again for your help so far! This should be my last question!
Copy link to clipboard
Copied
Up at the top I showed code for testing to see if all radio button groups were off
if(aRadGrps.every(function(a){return a.value != "Off"}))
This code usese the "every" member of the Array object. There is also a "some" member that returns true if any element in the array returns true.
if(aRadGrps.some(function(a){return a.value == 0}))
Copy link to clipboard
Copied
Thank you! It's halfway working.
I have 2 Areas that each generate a sub-total which are then displayed in Area3.Group1 and Area3.Group2. These subtotals then get added together in Area4 for a final score.
Currently, if the overall average is below 80%, "NO GO" is displayed. If a radio group in Area2 has a 0 selected, the code works and "NO GO" is displayed, regardless of the overall percentage, which is what I want. However, if a 0 is selected in Area1, the displayed value does not change to "NO GO"
Here is the code for my GO / NO GO field:
var aTextBox = this.getField("Area3").getArray();
if(aTextBox.every(function(a){return (a.value != "") && (a.value != 0)}))
{event.target.display = display.visible;
event.value = sum;
if(aRadGrps.some(function(a){return a.value == 0})) event.value = "NO GO";
if(event.value < 80) event.value = "NO GO";
if(event.value >= 80) event.value = "GO";}
else // Make hidden
event.target.display = display.hidden;
Here's a pic of the bottom of my form for context:
Thanks again for all of your help!
Copy link to clipboard
Copied
Since the code needs to produce a single result for a single object, i.e. "event.value", it needs to be written so that result is mutually exclusive, meaning there is only one path to a result. And a path for every input scenario.
Next, if you want me to look at your code, it must be formatted correctly.
Copy link to clipboard
Copied
Thanks. I think I understand your reply to mean that I'm not able to have multiple "if" statements which could lead to contradicting results. What is perplexing me is that if the total is above 80% (which should yield a "GO") but a 0 is selected in Area2, "NO GO" displays (which again, is what I want). But if the total is above 80% and a 0 is selected in Area1, "GO" displays. So for some reason the provided code is working correctly if the 0 comes from Area2, but not if it comes from Area1.
I'll try to mess with it some more. In the meantime, here is the code again, hopefully this time in the correct format. Thanks again for your help!
var aTextBox = this.getField("Area3").getArray();
if(aTextBox.every(function(a){return (a.value != "") && (a.value != 0)}))
{event.target.display = display.visible;
event.value = sum;
if(event.value < 80) event.value = "NO GO";
if(event.value >= 80) event.value = "GO";
if(aRadGrps.some(function(a){return a.value == 0})) event.value = "NO GO";}
else // Make hidden
event.target.display = display.hidden;
Copy link to clipboard
Copied
So no, this isn't formatted correctly. The idea behind formatting is to clearly show the structure of the code, so it is intuitively understood. Indenting, spacing, and bracket placement of are big parts of this.
var aTextBox = this.getField("Area3").getArray();
if(aTextBox.every(function(a){return (a.value != "") && (a.value != 0)}))
{
event.target.display = display.visible;
event.value = sum;
if(event.value < 80) event.value = "NO GO";
if(event.value >= 80) event.value = "GO";
if(aRadGrps.some(function(a){return a.value == 0})) event.value = "NO GO";
}
else // Make hidden
event.target.display = display.hidden;
There are several issues with this code. First of course is that there are multiple paths to contraditory results. It's definately not going to work. You need to re-think how to structure this so that it matches the required conditions. To do this, write out each condition set as a sentence, make sure each is unique. These represent the individual "if" statements. Now build each one into an "if"/"else if" structure.
You can take this to the next level by identifying common conditions that can be factored out into a nested "if" but this is unnecessary.
Now the next problem is that I don't see where the Area1 and Area2 inputs to the conditions are identified.
What's the "Area1" 0 and what's the "Area2" 0?
Copy link to clipboard
Copied
Thank you, and I apologize for how non-existent my script-writing skills are.
To answer the question at the end of your reply: "Area1" and "Area2" each contain sets of radio groups (Area1 contains 9 sets, and Area2 contains 4 sets) . From my screenshot above, Area1 is totalled in "Area3.Group1" and Area2 is totalled in "Area3.Group2". So the 0 I'm attempting to refer to is any radio button selection in the far right "UNSAT" column, and this applies to both Areas 1 & 2.
The thing that has me thinking that the code is close to working is that it seems to work if a 0 is selected in Area2. As you can see in the following screenshot, I have selected the top value button in all of my radio groups with the exception of a single "0" selection in Area2, and the field displays "NO GO".
But, if I select a 0 button in Area1, the field displays "GO".
To respond to your "write each condition set as a sentence," ultimately my sentences would be as follows:
Don't display anything until all groups that will be calculated have received a selection.
If "Final Score" is >= 80%, display "GO".
If "Final Score" is <80%, display "NO GO".
If 0 has been selected in any radio groups in Area1 or Area2, display "NO GO", even if "Final Score" is >= 80%.
Thanks again! I hope my perpetual lack of understanding is not testing your patience too much 🙂
I truly am grateful for your continued assistance!
Copy link to clipboard
Copied
So there is no "even if "Final Score is ..." The conditions have to be written as a set of distinct conditions. Because that is how they will be coded.
For example:
1) If "Final Score" is <80%, or 0 select in Area1 or Area2, then display "NO GO"
2) else if "Final Score" is >= 80%, display "GO"
3) else display what?
Now, you just said that "Area3" contains the Area1 and Area2 radio buttons, but then "aTextBox" is created from Area3 on the first line. So this can't be right. What is the exact code that defines the Area1 and Area2 radio buttons?
Copy link to clipboard
Copied
So my colleague and I worked on this a little yesterday, and the below code works in accomplishing all of my desired functionality with the one exception that we were unable to make the field hidden until all values have been selected. Anytime we inserted any script to attempt to make the field hidden, the field would display a value instead of the desire text of GO or NO GO. So if possible, I'm just looking to add the functionality for this field to remain hidden until all radio groups in Area1 and Area2 have a selected made.
To answer your above question regarding the code that defines the radio buttons in Area1 and Area2, these radio groups are simply groups containing 5 buttons each where I input the value each button would generate in the radio button Properties>Options>Radio Button Choice.
Here is my currect script:
var aRadGrps1 = this.getField("Area1").getArray();
var aRadGrps2 = this.getField("Area2").getArray();
event.value = sum;
if (aRadGrps1.some(function(a){return a.value == 0}) || aRadGrps2.some(function(a){return a.value == 0}))
{
event.value = "NO GO";
}
else if (event.value < 80)
{
event.value = "NO GO";
}
else
event.value = "GO";
Copy link to clipboard
Copied
You're original code for visibility should work
if(aTextBox.every(function(a){return (a.value != "") && (a.value != 0)}))
event.target.display = display.visible;
else
event.target.display = display.hidden;
Another way to do this is with a custom format script. Instead of hiding/showing the field. Just set the output to blank, or "unfinished".
Here's a custom format scirpt:
if(aTextBox.some(function(a){return (a.value == "") || (a.value == 0)}))
event.value = "";
It sets the field display to blank if any text box value is blank or 0.