Stefan Cameron on Forms
Building intelligent forms using Adobe LiveCycle Designer

Invalid Flashing Fields 2.0

A colleague of mine here at Adobe pointed-out today that the use of the AcroForm Document object’s getField method wasn’t necessary in the script I used for my original Invalid Flashing Fields sample.

There’s an alternative which uses xfa.form.resolveNode in the app.setInterval script. xfa.form.resolveNode takes a SOM Expression and returns a reference to an XFA node. What’s more is that this API call can be made from within the context of the AcroForm Scripting Object Model.

The app.setInterval script therefore changes from this:

moFlashTimerID = app.setInterval(
  "var f =  this.getField('" +
    GetAcroFormFieldName(oField) + "');  " +
  "if (color.equal(f.fillColor, color.red))" +
    "{ f.fillColor = [" + moAcroFieldFillColor.toString() + "]; }" +
  "else" +
    "{ f.fillColor = color.red; }",
500);

to this:

moFlashTimerID = app.setInterval(
  "var f =  xfa.form.resolveNode('" +
    oField.somExpression + "');  " +
  "if (f.ui.oneOfChild.border.fill.color.value == '255,0,0')" +
    "{ f.ui.oneOfChild.border.fill.color.value = '232,232,232'; }" +
  "else" +
    "{ f.ui.oneOfChild.border.fill.color.value = '255,0,0'; }",
500);

Also note the changes in the way the color values are compared and assigned (whereby the newer version uses more familiar XFA script rather than the AcroForm script from the first version).

Since the use of the AcroForm Scripting Object Model should always be secondary to using the XFA Scripting Object Model (because AcroForm objects are, after all, in a separate Object Model which may change separately from the XFA Scripting Object Model), I wanted to highlight this alternative which makes more extensive use of the XFA Scripting Object Model than the first version did.

Download Sample [pdf]

Minimum Requirements: Designer 7.1, Acrobat 7.0.5.


Posted by Stefan Cameron on August 15th, 2006
Filed under AcroForm Objects,Scripting,Tutorials
Both comments and pings are currently closed.

9 Responses to “Invalid Flashing Fields 2.0”

  1. Michael Ramirez on August 22nd, 2006

    How would you apply complex validation rules to a pdf docuemnt. For example, field A cannot be blank if fields B & C are filled or field E is checked. Can you reuse validation libraries across different forms?

  2. Stefan Cameron on August 24th, 2006

    Michael,

    Your question prompted a new post on my blog with a sample on how to do complex validations prior to submitting a form. See Complex Validations.

    As for reusing script across different forms, that’s possible by using a combination of script objects, subforms and the Library palette: Place a subform on the form and, in the Hierarchy palette, right-click on the subform you just inserted and select Insert Script Object. Then, select the script object and give it a name and use the Script Editor to write script (note that only JavaScript may be used in script objects). Once you’re finished, make the subform invisible using the Object palette’s Subform tab and drag the subform to the Library palette. That’ll create a new object in the Library that you can drag and drop onto any form. Say you named the subform “Subform1″ and the script object “ScriptObject”, you would when access the script by writing a JavaScript (on a button’s Click event, for example) with a statement like “Subform1.ScriptObject.MyFunction();”

    The problem with that approach is that if you need to modify the scripts in the script object, you’ll have to go back and fix all the forms that use it because dragging and dropping from the Library onto a form create a copy of that object — not a reference.

    Since I’m quite certain you’re looking for a reference rather than a copy, I’ll have to ask you to be a little patient because it’s possible we may address that issue in a future release.

  3. Michael on December 11th, 2008

    Hi Stefan – I’m just trying to creating a timer that will make some JavaScript code wait 3 seconds before running. Can I do this using the app.setTimeOut method? If so how?

    Thanks

    BTW Great post.

  4. Stefan Cameron on December 11th, 2008

    Michael,

    app.setTimeOut() is typically how you would do this but how easy it is and what you can do depends on the version of Acrobat/Reader you’re running. If it’s 7.0.5 or later, then the Acrobat Doc object exposes the global xfa object which is the gateway into the XFA form inside the PDF (as in the sample in this post). If you wanted to set the fill color of a field 3 seconds after clicking on a button, you would do something like this:

    app.setTimeOut('xfa.form.rootSubform.myField.fillColor = "255,0,0";', 3000);

    Note that when the timer fires, the code is executed in the context of the document from which the time-out was set.

  5. Michael on December 12th, 2008

    Thanks for the quick reply. I was attempting to access a ScriptObject which held some of my functions in them, through the app.setTimeOut method, and was unable to do so. I kept getting ‘ScriptObject’ not defined’ in the console. What is the proper syntax for using app.setTimeOut with functions in the script object?

  6. Michael on December 18th, 2008

    Ok Stefan, I really need your help here. I’ve been trying to get the app.setTimeOut method to work to no avail. I’ve tried accessing a script object that I have many functions in with no success. Then I just tried to place functions into the script where I editing thinking that maybe because the script object is part of the xfa form object I couldn’t access them through the app object,(or I was just using the wrong syntax) so that maybe if I placed the functions onto the same script and called them from there via:
    app.setTimeOut(“myFunction()”,3000);
    No dice. I’ve tried all kinds of arrangements in quotations, (single quotes, double quotes, no quotes, etc.) and nothing. What I’m trying to do is have a web service perform a query and bring back a string from the database if an object is found, then I’d like for Acrobat to wait for a prescribed time before checking if the database actually returned a string value, or if it did not and display a message indicating that either it did return something or it did not.
    I know that the app.SetTimeOut can see the function call I’m making, because when I wasn’t using quotes around the function (in the setTimeOut method) It was immediately displaying the messages. But when I put quotes around it nothing happens. Can you help me?

  7. Stefan Cameron on December 20th, 2008

    Michael,

    When you use app.setTimeOut, you should be giving a String as the first parameter. This string is the script that is to be evaluated, after the set period of time, in the context of the document (i.e. Acrobat Doc object) from which the time-out was set.

    When you simply do

    app.setTimeOut("myFunction();", 3000);

    nothing happens because the “myFunction()” is defined in the script object that’s in the XFA portion of the PDF document, not in the PDF document’s script space.

    In order to hit your script object function, you need to access it via the document’s xfa property which is the gateway into the XFA form that’s inside the PDF document. From there, you go into the Form DOM and from there, you specify the SOM expression from the root subform down to the function in your script object.

    For example, say you have a script object called “MyScripts” that’s in the root subform, named “form1″. In MyScripts, there’s a function called “foo()” which you want to execute after 1 second. You would do this:

    app.setTimeOut("xfa.form.form1.MyScripts.foo();", 1000);

    After 1 second, any code you have in foo() would be executed.

    Note: I’ve only tried this with Acrobat 9 Pro and frankly, I was surprised it actually worked because I had always thought one couldn’t postpone the execution of a script object function — I’m going to have to post about this after my break! The JavaScript for Acrobat 9 Reference claims that the xfa property is available since Acrobat/Reader 6.0.2.

  8. Xancholy on December 23rd, 2008

    Hi Stefan,

    Thanks for this great example. Please can you show me how to
    validate a RadioButtonList &
    flash it if nothing selected ?

    Thanks !

  9. Stefan Cameron on January 5th, 2009

    Xancholy,

    My colleague John Brinkman has a great 3-part series on good practices for validating exclusion groups (radio button lists).

    As far as making them flash, both the radio button lists and the fields (radio buttons) they contain have the fillColor scripting property (in XFA 2.8 at least) so you can set either the background of the entire list or just a single radio button within it if you want.