If you’ve worked with PDF forms, you are probably familiar with radio buttons:
There is one problem with radio buttons: When you have a selection that also includes “non of the above”, you have to create a separate option for that: A radio button group – once selected – cannot be unselected.
Sometimes it would be useful to allow the user to unselect a radio button. This can be accomplished with a checkbox group:
A checkbox group behaves just like a radio button group (e.g. only one option can be selected), but does allow you to have all options deselected by clicking on the currently selected item.
There is no automatic way to create these checkbox groups as for radio buttons, we have to manually apply the same name to all checkboxes that we want to be part of the group (on the “General” tab of the field properties), and then provide different export values for the different checkboxes in one group. This can be done on the “Options” tab of the field properties:
The same tab also allows us to modify the style of the checkbox. To make it look more like a radio button, I usually select “Circle” as the check box style. As you can see from the screenshots above, the checkbox still has a square “box”, whereas a real radio button uses a round container, but the checkmark is now a black “dot” or circle, just like for a radio button.
If you’ve created a complex form with radio buttons, and your requirements for the form change late in the implementation phase, and all of a sudden you need to make sure that a radio button selection can be deselected, you will have to convert all radio button groups to checkbox groups.
This is may be a very cumbersome change for a complex form if done manually, but with the help of some JavaScript, we can make this change automatically with a few lines of JavaScript code.
If you run the following code in e.g. an Acrobat Action, all radio button groups will get converted to equivalent checkbox groups:
function processRB(f) { // try to get all the widgets var nWidgets = 0; var fields = []; while (true) { var w = this.getField(f.name + "." + nWidgets); if (w == null) break; // work with this widget: var w_info = { name: f.name, name2: w.name, rect: w.rect, style: w.style, display: w.display, page: w.page }; fields.push(w_info); nWidgets++; } console.println("Found " + nWidgets + " widgets"); var theExportValues = f.exportValues; var theName = f.name; var theStyle = f.style; var theDisplay = f.display; this.removeField(f.name); for (var rb in fields) { var fn = this.addField({ cName: theName + "_CB", cFieldType: "checkbox", nPageNum: fields.page, oCoords: fields.rect }); } var cb = this.getField(theName + "_CB"); cb.exportValues = theExportValues; cb.style = theStyle; cb.display = theDisplay; } // iterate over all form fields and look for radio button groups for (var i = 0; i < this.numFields; i++) { var f = this.getField(this.getNthFieldName(i)); if (f.type == "radiobutton") { processRB(f); } }
To “fine tune” this process, it would also be possible to run the conversion script only for radio buttons that have a certain name. You can do this by e.g. changing the loop in the last few lines to something like this:
// iterate over all form fields and look for radio button groups for (var i = 0; i < this.numFields; i++) { var f = this.getField(this.getNthFieldName(i)); if (f.type == "radiobutton") { var p = /RadioButtonGroup$/g; if (p.test(f.name)) { processRB(f); } } }
This will only convert a group that is named “RadioButtonGroup”. You can come up with a more complex test for the name by using any method that JavaScript allows.
The same approach can also be used to change the type of other field typesΒ (e.g. change a number of text fields to drop down controls).
Karl,
I’m not a programmer, so I’m not sure how to edit your JavaScript to convert other types of form fields. It would really help if you could give an example of how the script could be changed for other types of form fields, as in your example of changing text fields to drop down controls.
Jay, you can use something like this:
function convertTextToDropdown(doc, f) {
var theName = f.name;
var rect = f.rect;
var page = f.page;
doc.removeField(f.name);
doc.addField({
cName : theName,
oCoords : rect,
nPageNum : page,
cFieldType : "combobox"
});
}
// iterate over all form fields and look for text fields
for (var i = 0; i < this.numFields; i++) { var aFields = []; var f = this.getField(this.getNthFieldName(i)); if (f.type == "text") { aFields.push(f.name); } for (var j in aFields) { convertTextToDropdown(this, this.getField(aFields[j])); } }
I need to change text fields into radio buttons. Can you please tell me how to manipulate the java script to achieve this? Thank you!
Can u explain how to unlock all field using javascript or else tell me how to check unlock fields in a entire document
Even though this has nothing to do with the blog post, here is some information about the “Locked” property: This checkbox only locks the properties of the field when using the properties dialog. The user can easily uncheck that box and get write-access to the properties again. There is no JavaScript equivalent to this checkbox, we cannot uncheck it or check it via JavaScript. However, you can modify the field, even though it may be locked, via JavaScript.
I am hoping to change checkboxes INTO radio buttons.. what is the best way to do that?
Tucker, it looks like I missed your question when you posted it. Sorry about that. You can certainly change checkbox groups into radio buttons. When you look at the script, you should see how I am detecting radio buttons, and then getting all “widgets” for that control. You can do the same thing for widgets in a checkbox group. Just follow my example and look for widgets in a checkbox group, and then create a radio button group out of that information.
I tried to modify your script to change several Buttons in one document, all Buttons perform a mailto:xyz@abc.com, i want to change this to 123@abc.com, but i stuck. Is it possible to do this with JavaScript?
Peter, what you want to do is something completely different than to convert a group of boxes. You can add an action to a button via JavaScript (see the Field.setAction() method), but this will replace anything that was there before. This means you cannot just replace a string in an existing button action, you will have to know what was there before and recreate everything else that you may have to do when the button is pressed.
Thank you for your hint. I found a way to delete the old buttons and create new ones via js, but unfortunately the ios Reader does not support submitForm via js.
How do you run these scripts (in Acrobat DC)?
Tim, the same way as in Acrobat XI: Create an Action using the Action Wizard, then add a “Run JavaScript” action step to your Action and paste this script into the editor.
Is there a way to allow for multi-checkboxes to be clicked?
Jafet, a group of checkboxes can have multiple selections, whereas a radio button group only allows one selected button.
Wow!! Thank you so much for this. Just saved me at least an hour of tedious work.
Dude, You are a WIZARD! Thanks so much!
Hi There, I know this is an old article but, I tried using it and I’m getting an Syntax error; SyntaxError: syntax error
1:Console:Exec
undefined
Not sure what to do to fix it, any help would be appreciated.
I have a form to create in Adobe Pro. 4 boxes to select from but the last button is an Opt out choice so the other 3 cannot be checked. How do I do that, using radio boxes?
Dan, without more information, it’s impossible to suggest a fix. How are you running the code? Which version of Acrobat do you have? Did you modify the code I posted, and if so, how?
Jill, I am sorry, but I don’t quite understand how your form is working. when you have radio buttons, you can only select one button at a time. So if you selected your opt-out button, you cannot select any other button without also deselecting the opt-out selection again.
Karl, I have Acrobat Pro DC (2015), I have not modified the code at all (it is exactly what I want to do), and have tried running the code from the debugger as well as attached to a temporary button placement. Thanks for the response.
Hello, I am very unfamiliar with javaScript and would like to use this to change some radio buttons. Is there something I need to change in the posted javascript to relate specifically to my document?
Sarah, without knowing any JavaScript, you will not be able to recover if something goes wrong. In theory, you should not have to change anything, but usually, you don’t want to convert all radio button groups (and you do say “some” in your comment), so ideally, you would write a filter in JavaScript so that only those groups you want to have converted will get processed.
Dan / others; If you encounter the same issue of the “syntax error”, make sure you highlight the code within the console before executing.
Verified steps from the latest Acrobat Pro DC:
1) Open the Javascript Toolbar via Tools -> Javascripts.
2) Click “Debugger” on the toolbar.
3) In the “View” section, select “Console” in the dropdown, then paste the code from Karl in the box.
4) Highlight the code in the box, and press Ctrl + Enter on your keyboard.
Thank you for this information. I was able to successfully convert the radio button group “sources” to checkboxes using your code; however, even though the properties indicate they are checkboxes, they still act like radio buttons (i.e. when I check one and then another, the check in the first goes away). What am I missing? Thanks.
Version: Acrobat Pro XI
Joel, a checkbox group behaves exactly like a radio button group: Only one item can be selected at any given time. The only difference is that you can deselect all options, by clicking on the currently selected item. This is not possible with a radio button group. If you want a different behavior, you need to use different names for the individual checkboxes. Using the same name will create such a checkbox group. The script will always use a checkbox group (meaning that all buttons share the same name), but you can of course modify the script to adjust the output.
Hi, Karl-
I just ran onto your blog as I was searching for a way to convert checkboxes to radio buttons, fabulous resource.
I tried running the script as written, just to see what happens, and it deleted existing radio buttons. (Trying this before trying to edit the script to do the opposite) I wonder what I’m doing wrong? Acrobat 11.
I would be glad to pay you for the script to do the conversion from checkbox to radiobutton. In addition, I’m interested in getting you to create some plugins- for example, could you create a plugin (or a script) to convert all H1 tags to H2? What about table scoping, say, scoping top row to column and left column to row, globally, for all tables in a document?
Thanks for your patience with a newbie!
Chris, I will reply by email to you directly.
Apparently, my company does not give me permissions to edit or create Java Script π
I tried doing the check boxes instead of radio buttons manually and I am not able to give them the same name/different export values as I had with my radio buttons.
Amelia, unfortunately, I don’t understand what you are asking for. Radio buttons and checkboxes should be able to be named the same way (and have the same export values). You just need to make sure that you remove your radio buttons before you add your checkboxes. You cannot have two fields with different types share the same field name.
Thank you for posting this. I have Acrobat forms form the IRS that other programs could not process because there was something unusual about the checkboxes, but modifying your script to simply replace the checkboxes with new checkboxes solved the problem. Thanks again.
I followed Russell’s instructions for running the script in Acrobat DC, but still get the errors:
Found 2 widgets
Exception in line 32 of function processRB, script Console:Exec
Exception in line 47 of function top_level, script Console:Exec
RangeError: Invalid argument value.
Doc.addField:32:Console undefined:Exec
undefined
When I run it from the console or as an action, it deletes the first two “buttons” (a yes and no choice) then stops with this error:
“Found 2 widgets
Exception in line 32 of function processRB, script Console:Exec
Exception in line 47 of function top_level, script Console:Exec
RangeError: Invalid argument value.
Doc.addField:32:Console undefined:Exec
undefined”
line 32 is this: oCoords: fields.rect
line 47 is this: processRB(f);
Any idea what the problem might be?
Hi Karl I have this script for a stamp that I modified for my use and it has 3 radio button selection in it and i would need the script to allow me to deselect the one so none of them are selected I’ve tried to run your script but it just end up deleting all 3 radio button not sure why. Im not sure if I can post the script in this post or if I could email your the script if you could help me out that would be great.
Thanks
Acrobat Pro X
Yvan – please email the script to me. My email address is on the About page. Make sure that you reference this comment in your email, so that I know what I am looking at π
Your script worked for me when I changed the following lines:
nPageNum: fields[rb].page,
oCoords: fields[rb].rect
However, the checkboxes did not retain the tab order from the replaced radio buttons. Is that possible?
@D: Yes, that’s possible. The tab order is different from the order in which the script processes the fields, so the newly created fields would be inserted into the tab order in the order in which they were created. This means that you save some time by not having to manually create these fields, but you need to spend (a lot less) time to update the tab order.
Thanks for your script Karl, it’s been extremely useful to help gain some insight into Acrobat scripting syntax and for making conversions across multi-page documents. Unfortunately, I have several hundred PDF Forms where text fields are getting placed by the form detection instead of check boxes. I’ve been trying to modify your script to change a “text” field into a “checkbox” field, by basically doing the same process of creating a new field type with the same name and then deleting the original.
I was wondering if you could point out what’s wrong in this particular script:
function processCB(f) {
console.println(“Doing ” + f.name);
var theName = f.name;
var theStyle = f.style;
var theDisplay = f.display;
var thePage = f.page;
var theRect = f.rect;
this.removeField(f.name);
var newName = theName.substring(theName.indexOf(“_”)+1);
var fn = this.addField({
cName: newName,
cFieldType: “checkbox”,
nPageNum: thePage,
oCoords: theRect
});
fn.exportValues = [ theName ];
fn.style = theStyle;
fn.display = theDisplay
}
// iterate over all form fields and look for text fields
for (var i = 0; i < this.numFields; i++) {
var f = this.getField(this.getNthFieldName(i));
if (f.type == "text") {
processCB(f);
–i;
}
}
Any guidance you can offer would be greatly appreciated, the project to convert all of these PDF's to make them usable has been a nightmare.
Thanks again!
Also, just noticed Sarah asked essentially the same thing previously, so my apologies if I missed the explanation somewhere. Thanks again for all your expertise and assistance.
Hi Karl, THANK YOU!!! And I hope the below can help others π
I had issues with this script. First, it didn’t work until I did what D said:
nPageNum: fields[rb].page,
oCoords: fields[rb].rect
Then I had some display issues so I put the “cb” block in the loop.
Then, I’ve overriden the export value to be “on” just like my other fields.
And finally, I added another bit at the end to change every checkbox (including the new ones) to have the check mark style.
Like I said, I hope this helps others the way you have helped me π
function processRB(f) {
// try to get all the widgets
var nWidgets = 0;
var fields = [];
while (true) {
var w = this.getField(f.name + “.” + nWidgets);
if (w == null) break;
// work with this widget:
var w_info = {
name: f.name,
name2: w.name,
rect: w.rect,
style: w.style,
display: w.display,
page: w.page
};
fields.push(w_info);
nWidgets++;
}
console.println(“Found ” + nWidgets + ” widgets”);
var theExportValues = f.exportValues;
var theName = f.name;
var theStyle = f.style;
var theDisplay = f.display;
this.removeField(f.name);
for (var rb in fields) {
console.println(” Doing widget #” + rb);
var fn = this.addField({
cName: theName + “_CB” + rb,
cFieldType: “checkbox”,
nPageNum: fields[rb].page,
oCoords: fields[rb].rect
});
var cb = this.getField(theName + “_CB” + rb);
//cb.exportValues = theExportValues;
cb.exportValues = [“On”];
cb.style = theStyle;
cb.display = theDisplay;
}
}
// iterate over all form fields and look for radio button groups
for (var i = 0; i < this.numFields; i++) {
var f = this.getField(this.getNthFieldName(i));
if (f.type == "radiobutton") {
processRB(f);
}
}
// iterate over all form fields and convert checkboxes to the check style
for (var j = 0; j < this.numFields; j++) {
var f = this.getField(this.getNthFieldName(j));
if (f.type == "checkbox") {
f.style = style.ch
}
}