Stefan Cameron on Forms
Building intelligent forms using Adobe LiveCycle Designer

Process All Fields

A common requirement on the Adobe Designer Forums is to find all fields on a form and do something specific with them.

For instance, you may want all mandatory fields to be automatically highlighted when a user attempts to submit a form electronically before having filled all mandatory fields. While Acrobat provides a button to toggle mandatory field highlighting on/off (via the Highlight required fields check box in the yellow Form Field toolbar), Acrobat’s Scripting Object Model doesn’t provide a function to do the same. Therefore, you’re left having to write some script to achieve the same functionality.

Since this is requested so often, I thought I would try to put together some canned script that you can copy and paste into your form in order to instantly have the ability to make changes on everything that’s considered a field on your form.

Download Script [js]
Download Sample [zip]

Minimum Requirements: Designer 7.0, Acrobat 7.0.

The first download is for a JavaScript file which contains the “plug & play” script that you can simply copy & paste into any event handler or script object and immediately start concentrating on what you want to do when you find a button, a check box, a text edit, etc.

It’s divided into two parts: The first (at the top-end of the script) is a series of Field Processor Functions for each field/object type that may be found within a form. Each function receives a reference to the field in question. The second (at the bottom-end of the script) defines the ProcessAllFields function — the brains behind this operation. This function detects the field type and calls the appropriate Field Processor Function.

All you need to do is add script to the Field Processor Function(s) for the field types you need to do stuff with.

The second download contains the JavaScript file along with a sample form which demonstrates how to get from the bare-bones Field Processor Functions and ProcessAllFields function to a solution which finds all non-filled mandatory fields on a form and highlights them with the current Acrobat Highlight Color. You’ll find customized versions of the Field Processor Functions and ProcessAllFields function in the script object (named “ScriptObject” — yes, I know, this is an unbelievably original name!) while the script execution flow begins in the Submit button’s Click event.

When the Submit button is clicked, the form is searched for non-filled (empty) mandatory fields. If such fields are found, they’ll be highlighted, the RemoveHighlight button will be made visible and an error message will be displayed. Otherwise, the Email Submit dialog will open.


Posted by Stefan Cameron on June 26th, 2006
Filed under Scripting,Tutorials
Both comments and pings are currently closed.

29 Responses to “Process All Fields”

  1. Rob McDougall on August 25th, 2006

    Hi Stefan,

    It occurs to me that it would be nice to remove the recursion in this example. My thinking was that I should be able to utilize xfa.resolveNodes() and the proper SOM expression to get a nodelist of all the fields. I haven’t been able to concoct the right SOM expression however. I thought “xfa.form..#field[*]” should work after all:

    The .. notation indicates a recursive search through the children of an object.

    The # notation allows you to access a note by type.

    The [*] notation returns all the occurrences that match.

    Unfortunately, this doesn’t work. Any idea why?

  2. Rob McDougall on August 25th, 2006

    OK, I just re-examined the documentation for the .. operator. While the docs don’t say it, the examples indicate that the .. operator only finds the first occurrence of a subcontainer below the parent. That seems a little odd to me. Is there some way to find all occurrences within all subcontainers?

  3. Stefan Cameron on August 29th, 2006

    Rob,

    It took me a little while to figure-out what was going on with the FormCalc double-dot (“..”) operator.

    While documentation on the subject may lead one to think that it’s a recursive operator or that recursion is possible with it, the operator isn’t designed to be recursive.

    The double-dot “..” operator is specific to FormCalc and is designed to perform a top-to-bottom, depth-first search of the RHS (right hand side) operand looking for a single object which matches the RHS. Once that object is found, if the RHS is augmented with the “[*]” syntax to locate all occurrences of an object, it looks for all occurrences only within the container which was found to contain the first match.

    Consider the following simplified object hierarchy:

    R
    +-- A
        +-- C
        +-- C
    +-- B
        +-- C
        +-- C

    Searching for “R..C” would return the first C from the top which is parented to A.

    Searching for “R..C[*]” would return the first two Cs from the top, both parented to A, but none of the Cs parented to B.

  4. Steve Lodge on February 22nd, 2007

    Stefan,
    I am trying customize your example here..I am creatig exams where the push of one button will look for the correct answer (radio button in an exclusion group with a value of 1) of every multiple choice question and will add each correct answer to a sum calculation for the final mark. If the user selects an incorrect answer, the incorrect answer is highlighted and the correct answer is selected. I figured your example would be perfect to manipulate for this but don’t want to break what you’ve created being an intermediate developer. I was hoping you could give me some insight.
    Hope you can help.
    Steve

  5. Stefan Cameron on March 6th, 2007

    Steve,

    I can see why you would want to use my sample as a base to work with.

    I would suggest that you first modify the “ProcessAllFields” function in the “ScriptObject” script object such that it calls a new function named “ProcessExclusionGroup” for every exclusion group that it finds as it recursively iterates through the XFA Object Model. At the moment, the “ProcessAllFields” function will call the “ProcessRadioButton” function for every radio button within an exclusion group which means you’ll end-up verifying the same exclusion group many times.

    Once you have the “ProcessExclusionGroup” function in place, then you can loop through the nodes it contains to find the radio buttons in the same way that the “ProcessAllFields” function does, simply looking for nodes with a “field” class name (since you know they’ll be radio buttons at this point).

    Also, given the exclusion group, you can get its rawValue property which will tell you the value of the selected radio button. Since the correct answer has a radio button with a value of 1, if the exclusion group’s rawValue is 0, you know the student didn’t select the correct answer. You can then loop through the radio buttons, highlighting the incorrect selection in red and setting the exclusion group’s rawValue property to 1 (which will automatically select the radio button with the correct answer).

    Please let me know if you have any questions.

  6. Newbie on March 26th, 2007

    I am a newbie to Livecycle Designer 7.0 – I just created a survey with multiple required fields. I like the fact that before a user can submit the form via email, required fields are highlighted so the user knows they are required and cannot submit until filled-in. What I was wondering, is there a way to make ONLY the required fields THAT WERE MISSED highlighted so they can be found easier? It seems so cluttered when a required field, that is already filled in, becomes highlighted in addition to those fields that are not filled in. Thanks

  7. Stefan Cameron on March 28th, 2007

    Newbie,

    Based on your question, it sounds like you’ve already figured-out how to highlight all the required fields when the user clicks the Submit button. Now you’re just wanting the empty required fields to be highlighted instead of all of them, correct?

    In that case, you should be able to tweak your script to ignore fields which have a value. You can determine if a field has a value by performing the following test on a field object reference (“MyField”):

    // JavaScript:
    if (MyField.rawValue =! null && MyField.rawValue.length > 0)
        // the field has a value

    // FormCalc:
    if (HasValue(MyField)) then
        // the field has a value
    endif

  8. suchita on May 8th, 2007

    Hi Stefen,

    I have a similar requirement. I have downloaded your code. Looks great to me. But I am facing one problem in that.
    In your sample, for the textedit fields you have given borders to the fields (Object -> Field -> Appearance -> Custom -> Lowered 3D).
    But in my form it is set to none for all the fields. And there are hundreds of such fields. So I can not change the borders. But because of this, the script fails.
    Kindly suggest me how to achieve this functionality without changing anything with the fields.
    I need to implement this code urgently.

  9. Stefan Cameron on May 12th, 2007

    suchita,

    I understand your problem. Off the top of my head, I can think of two alternatives to modifying the content area border (the one that’s for the value area, modified by the Appearance property in the Object palette’s Field tab):

    The first would be to modify the entire field’s fill color rather than its content area. In this case, you would simply pass the field object to the SetColor method (rather than passing “oField.ui.resolveNode(“…”)” and then use the “fillColor” property as I describe in my post on setting a field’s fill color.

    The second would be to highlight the field’s caption rather than highlighting its value. To do this, you would simply pass the field object to the SetColor method (as in my first suggestion) but the SetColor method would change to this:

    function SetColor(oField, sColor, bRemove)
    {
        oField.caption.font.weight = bRemove ? "" : "bold"; // bold when highlighted, regular otherwise
        oField.caption.font.fill.color.value = sColor;
    }

    And the calls to the SetColor function would all change to this:

    SetColor(oField, sColor, bRemove);

    You’ll also need to change the “non-highlight” color, specified as white (255, 255, 255) in the “HighlightRequiredFields(oNode, bApply)” function, to black (0, 0, 0) or else your captions will all disappear when the highlight is removed. Of course, this assumes that all your captions are black (or at least the same color).

  10. Antonio Auricchio on March 4th, 2008

    Hello,
    I’am using your function PrcessAllFields in a big forms (9pages and 450 variables), i encounter performance problem.
    Every times ProcessAllFileds is called “Acrobat Professional” need more 50MB and dont restitue the memory until exit from “Acrobat Professional”.
    Have you an idea why this occurs ?

  11. Stefan Cameron on March 4th, 2008

    Antonio Auricchio,

    This is probably occurring because the “ProcessAllFields” function is recursive. Recursive functions can require a lot of memory, especially if they recurse very deep. Since you’re using it on a large form (with lots of fields and subforms, I presume), it’s no surprise that you’re seeing increased memory consumption in Acrobat.

    The function is recursive because it drills down into every “container” (i.e. subform, exclusion group, group, etc.) that might contain other form objects or containers. An alternative, I suppose, would be to use a stacking algorithm using the Array object to avoid the recursive function call but I have no idea whether that would help with Acrobat’s memory consumption or not.

  12. Antonio Auricchio on March 5th, 2008

    Hi Stefan,
    Thanks for your answer.
    To bypass this performance problem i have created a function which check explicitly all fields where could become required.

  13. Mark on April 1st, 2008

    Hi Stefan -

    I’m trying to customize your “Process All Fields” script to validate only VISIBLE fields on the form, instead of all fields, prior to submitting.

    I have a fairly large form and am using subforms and their presence property to hide or show groups of fields based on user interaction. If they are visible, they are mandatory. Since I have no way of knowing which fields will be visible at runtime, I have to make them all “User Entered – Required”. Your script works like a charm for my application EXCEPT when fields are wrapped in a subform and the subform presence property is set to “invisible”. Your script still flags the non-filled mandatory fields even though they are not displayed or visible on the form.

    I have a function that returns false if the field (the input to this function) or any of its parents is not visible:

    function isVisible(oFld)
    {
    var bVis = true;
    var nxtFld = oFld;
    while(nxtFld.name != “form”)
    {
    if(nxtFld.presence != “visible”)
    {
    bVis = false;
    break;
    }
    nxtFld = nxtFld.parent;
    }
    return bVis;
    }

    Trouble is, I don’t know how to integrate the function into your script to achieve the “visible fields only” result. Can you suggest a good approach?

  14. Stefan Cameron on April 9th, 2008

    Mark,

    I think I would just put a call to isVisible(oNode) immediately inside the ProcessAllFields function. If it returns false, then exit the function; otherwise, run through all fields. This way, if you call ProcessAllFields() with a field object and it’s visible, it’ll be validated (with your other augmentations to the function); otherwise, nothing will happen since it’s invisible. If you call ProcessAllFields() with a container of some sort and the container is invisible, nothing will happen (which is what you want) and if it’s visible, the function will go on to find all the fields it contains by doing recursive calls to ProcessAllFields, at which point each field inside the container will be tested for visibility right away and the function will abort for the fields that aren’t visible.

  15. Mark on June 2nd, 2008

    Stefan,

    I am using your script object and it is working great. The only problem i am having is its not picking up required text fields when they are within a table. It picks up dropdowns and radio buttons but just not a text field or a datatime field. These are also dynamic tables there you can add and delete rows.

  16. Stefan Cameron on June 11th, 2008

    Mark,

    I haven’t been able to reproduce the problem you’re describing with my script. I can’t understand why it wouldn’t specifically find required text fields in a table. The script is generic enough that it shouldn’t matter where the text field is or whether it’s required or optional. Have you tried placing a required text field in a regular subform to see if the script would find it? Have you made modifications to the script that could be playing a factor in this issue?

  17. Jan Hillmer on June 29th, 2008

    First I’ve got the same problems like Mark (its not picking up required text fields when they are within a table), but I could fix this issue. Your field inside the table must have something like a underline, invert or outline (object palette), then the script also with tables works well.

  18. Stefan Cameron on July 4th, 2008

    Jan Hillmer,

    Thanks for posting your solution however I’m still puzzled as to why this happens. For the benefit of other readers, what version of Designer and Acrobat are you using? I’m unable to reproduce this using Designer 8.2 and Acrobat 9.0 (using XFA 2.8) which leads me to think there may be some slight differences in older Designers that are authoring forms using an older version of XFA.

  19. Sylvia on August 12th, 2008

    Hi Stefan, I have a couple of fields and radio buttons to user required and although the other fields were highlighted, the radio buttons were not. Would you know the solution to this?

  20. Stefan Cameron on August 13th, 2008

    Sylvia,

    It’s probably because the individual radio buttons aren’t the ones that are mandatory — it’s the radio button list. The radio buttons are just there to set the value in the radio button list so the field is the radio button list, not the individual radio buttons…

  21. Megan on November 5th, 2008

    Hi Stefan,

    I am trying to understand Highlighting script. What I am trying to do with my form is when you select text from a drop down it automatically highlights certain text boxes throughout the form. For example: When you select the month of December in the drop down, it will highlight the weekend days which are (text boxes) below.

    I can’t seem to figure this one out.

    Thanks

  22. Stefan Cameron on November 10th, 2008

    Megan,

    If you know exactly what the fields are, then you would simply change their color directly depending on the value selected in the drop down list.

    My tutorial on handling list selection changes will show you how to get the new selection in your drop down list.

    From there, you would determine if it’s “December” and you would set the color of the weekend days directly:

    MonthDay6.fillColor = "255,255,0"; // yellow, I think
    MonthDay7.fillColor = "255,255,0";

    If you want to get more sophisticated and your fields are named as above, then you could call a function that determines the days of the month that are weekend days and returns them in an Array object. Then you could iterate through the Array and dynamically create the names of the fields to highlight:

    var days = GetWeekendDays(dropDownListSelection);
    
    for (var i = 0; i < days.length; i++)
    {
        xfa.form.resolveNode("#subform[0].MonthDay" + days[i]).fillColor = "255,255,0";
    }

    For each entry in the list, the pertaining "MonthDayX" field is located in your form and highlighted.

  23. Ram on February 5th, 2009

    Hi Stefan,

    You are performing nullTest in your form. Is it also possible to perform formatTest and scriptTest using javascript?

    Thanks
    Ram

  24. Stefan Cameron on February 6th, 2009

    Ram,

    You can force the validation script of a field, subform or the entire form to be executed by calling the execValidate() method on a field, subform or form (e.g. xfa.form.execValidate()). This should execute the validation scripts.

    As for the format test, that’s usually a Picture Clause that’s used to validate user input into a field. I believe you would have to manually test that one using FormCalc functions like Date2Num() to test a field’s value against its validation pattern, assuming it’s a date pattern.

  25. sblanco on April 14th, 2009

    Hi Stefan,

    Hope everything okay at your end…

    Just want to ask your help. I need to validate and check two date fields which entered by usersr using the calendar picker. The required date must be greater than the requested date. I hope you can help me…

    Thank you and best regards,
    Sandra

  26. Stefan Cameron on April 17th, 2009

    sblanco,

    There are many ways that form objects can be validated. The right course of action depends on the reason for the validation. What reason do you want to validate the dates for? What should happen if the second date is smaller or the same as the first one?

  27. Craig on April 28th, 2009

    I was hoping to obtain an example of how Antonio Auricchio (or anyone else) was able to address the memory issue when dealing with a large number of fields.

    Any help would be most appreciated.

  28. Ben on August 25th, 2010

    Hi Stefan,

    Great tutorial form, been a lot of help with my own project. However, I’m pretty new to LiveCycle and was wondering how you’ve suppressed the generic validation message that appears when, for example, the user enters some information in a field set to ‘User Entered – Required’, then has a change of heart, deletes it again, and moves on.

    In my form I always get a pop-up message saying ‘XXXField cannot be left blank’ but when I try the same in your example (e.g. on the second textfield) no message appears. I’ve checked all the settings/options I can think of and they seem identical – can you help?

    Thanks,

  29. Stefan Cameron on September 10th, 2010

    @Ben,

    You don’t see the warning on my form because I do the validation manually using my “Process All Fields” script (from this tutorial). That means all the fields are actually flagged as “optional”, getting rid of the warning — which can’t be customized, unfortunately.