Submitting crash information using Windows Error Reporting

| No Comments

Starting with Designer 8.2.1, you can submit crash information using Windows Error Reporting. When you submit crash information, it would be helpful if you could log a bug and provide the steps required to reproduce the bug as well as the crash bucket ID assigned by Windows Error Reporting. Logging a bug will go a long way in helping us find the cause of the problems.

  1. Go to www.adobe.com
  2. Click the Send feedback link at the bottom of the page.
  3. In the Adobe Products section, click Report a bug.
  4. In the Product name list, select Designer.
  5. Provide the steps to reproduce the crash.
  6. Provide the crash bucket ID.

To retrieve the Windows Error Reporting Crash Bucket ID

Windows XP

  1. Select Control Panel -> Performance and Maintenance -> Administrative Tools -> Event Viewer.
  2. In the left pane, select Application.
  3. In the Application list, you should see two log messages called "Application Error" at the time Designer crashed. One of the log messages identifies the crash as being from "FormDesigner.exe". The other message identifies the crash bucket ID that Windows Error Reporting associated with the crash. The number called "Fault Bucket" is the number you need to include in the bug report.

Windows Vista

  1. Select Control Panel -> System and Maintenance -> Problem Reports and Solution.
  2. In the Tasks list, click View problem history.
  3. Locate the section of problem history for LiveCycle Designer ES.
  4. Double-click on the event that correspond to the date and time of the crash.
  5. Click the "Copy to clipboard" link and past it into the bug report.

Windows 7

  1. Select Control Panel, search for "Problem Reports", and then click on "View all problem reports".
  2. Double-click on the event that corresponds to the date and time of the crash.
  3. Click the "Copy to clipboard" link and past it into the bug report.

Thank you
The LiveCycle Designer team

Actions and JavaScript

| 1 Comment

If you've checked out Steve's post that introduces Actions and the Action Builder, you should have a basic idea of what Actions is about. In this post, I intend to dive a bit deeper into the guts of how Actions work "under the hood" as it were and explain what happens to your form when you use Actions.

I'll start by expanding on Steve's simple "When Button1 is clicked, go to a web page" example.

This is the simple button click example in the Action Builder dialog:

ActionsBtnClick.png

If you press the "OK" button and preview your form in Acrobat, when you press the button, a web browser will open to the website provided. It's like magic!

And now I will sadly make the experience much less magical: I'm going to explain what's really happening behind the curtain to get this to work.

When an Action is created, Designer is actually generating JavaScript code for you, under the hood. Given the conditions you provide and the results you want to achieve, we figure out what event should trigger the code to run, and what JavaScript needs to be placed in that event to achieve the result desired.

How It Really Works

What really happens is that Designer generates scripts and puts them in the right events of the form for you. Each Action generates one or more script blocks (which we call "script snippets" or just "snippets".) A script block generated by Designer has a standard format:


[1] //+ The header ID line, which is also the "managed script" open line
[0-*] //+ Action parameter lines
[1-*] Lines of Javascript
[1] //- The managed script closing line

Everything between the first //+ and the //- line is a "managed script", i.e. a script that Designer created, rather than one that was created manually by you, the form author. Designer keeps track of all the managed scripts through the header blocks (all the lines that start with //+).

After creating the simple "When Button1 is clicked..." Action, if you check the Script Editor, you will see that the Button1::click event contains some script:

ActionsBtnClkScript.png

At this point, there are two very important technical details about managed script that I would like to review:

The first point is that the header block is the important data of a managed script. The actual JavaScript is incidental, from Designer's point of view. For Actions to work properly, all the information Designer needs is what is in the header block. In point of fact, the JavaScript between the //+ and the //- is routinely thrown away and regenerated by Designer.

The second point is that the Action Builder and Actions UI depend on the scripts that Designer generates not being tampered with to work correctly: if a managed script has been edited manually, it is an extremely difficult problem for Designer to figure out what has changed, and whether the changes are valid. Since it's so difficult, we don't even try: if any changes are made to a managed script, we un-manage that script. In essence, you lose your Action. This means that when the Script Editor next refreshes, the Action header block will be gone, and the script will look just like regular script you typed in manually. Also, if you open the Action Builder, the Action that was modified will no longer be there.

This isn't as bad as it may seem. In fact, we designed this entire feature with the idea that people would eventually want to deliberately un-manage scripts: maybe you just want to use the Action Builder to get you started, but you want to do more complicated script on your own: so you create a "starter" Action and then go manually edit the action to make it do more complex things. So it's not necessarily a bad thing to un-manage your Action - you should just be sure you know what you're doing and don't un-manage scripts accidentally.

I guess I'll leave off here on the introduction to the innards of Actions. I have another post planned where I'll explain the Action header block in more detail.

An Intro to Actions

| No Comments

Check out Steve's blog post about the Action Builder.

Can We Offer Some Assistance?

| No Comments

Improving the scripting experience has been a major theme for the next release of Designer. While the core focus of development work on improving the scripting experience has been around the action builder and the validation functionality, I happily was able to find a bit of time to improve the Object Assist functionality in the Script Editor. I thought I would share some of the improvements that you can look forward to in the next version of Designer.

This is the current Object Assist experience:
ObjectAssist-Old.bmp

This is the new & improved Object Assist window:
ObjectAssist-New.bmp

I'll outline the major changes below.

New Icons

The Object Assist dialog now displays icons next to each entry. There are four possible icons:

ObjectAssist-Icons.bmp

The first icon is used to denote methods.
The second icon is used to denote attributes.
The third icon represents a deprecated method.
The fourth icon is used for deprecated attributes.

This functionality is useful to tell "at a glance" what the various items in the list mean.

Note that we no longer italicize any of the entries in the listbox. The italics were meant to denote methods and attributes that are XFA Plugin (i.e. HTML) compatible. That information has now moved into the help text for each entry.

Improved Help

The help box that used to be gray and contain very brief descriptions of the various APIs has had a huge facelift. The help box is now a rich text control and can therefore be used to show information in a richer way. The box is also bigger, since we now have much more information to display.

I hadn't realized how cumbersome it must be to get the API information for the XFA scripting model... Internally, we have a Flex application that acts as an XFA API reference. It's pretty cool, and fairly easy to use. While not as practical as inline help, the Flex XFA API tool is quite an acceptable way to get API help easily. However, when I did a bit of research, I discovered that we don't publicly release that tool (it was built by one of our great coop students.) I was horrified to think that everyone has to go to the script reference PDF every time they want to know more about an API call! As a programmer myself, I can imagine how inconvenient that must be.

It turns out that the Flex API application hooks into the same code that the Object Assist does to query the API data. So all the information was there, we just had to pull it out and format it correctly. So that's what we did. Here's a description of the information the improved Object Assist will be showing:

For all entries:

  • The description text of the entry (this is all that we used to show).

  • The version of XFA for which the entry is supported (i.e. 2.1, 2.6, etc.)

  • The availability of the entry (Core XFA, Acrobat, XFA Subset (HTML), XFAF, Dynamic Documents or deprecated.) Note that the availability can be a combination of options.

For attributes:

ObjectAssist-Attribute.bmp

  • The attribute type (string, int, object, bool, etc.)

  • The attribute access (get, set or get and set).


For methods:

ObjectAssist-Method.bmp

  • The complete method signature

  • Description text for each parameter

  • Description text for the return value

  • Noting of optional parameters

Function Completion

We've also added functionality that will auto-insert the parameter brackets and parameter arguments into the Script Editor when you choose a method from the list. Our Function button already does this, so it's not very different from how some stuff already works.

For example, choosing "deleteItem" from the Object Assist list will insert deleteItem(n1) into the editor.

Choosing "assignNode" will insert assignNode(s1[, s2][, n3]).

The parameter names are actually type abbreviations. We use "s" for string, "n" for int, "d" for double, "b" for bool, "e" for exception and "o" for object. In the examples above, deleteItem expects an integer, and assignNode expects a string and optionally a second string and an integer.

If you absolutely hate this functionality, and want the old way back, we've added a checkbox to Tools | Options | Worskpace called "Add Statement Completion Method Signatures". Just uncheck that box, and the signatures will not be auto-inserted.

ObjectAssist-Options.bmp

Improved Usability

We've essentially re-written the keyboard and mouse handling for the Object Assist from scratch. Note that the Object Assist no longer has an edit control:

ObjectAssist-WithEdit.bmp

ObjectAssist-WithoutEdit.bmp

The edit control was complicating the keyboard handling and generally impeding the implementation of several more "natural" or "usable" keyboard shortcuts.

We've also made lots of little changes to the how various keys (like HOME, END, PAGE_DOWN, PAGE_UP, etc.) behave and improved the functionality for "searching" in the function list while typing.

Script Dependencies and "recalculate()"

| 2 Comments

For older versions of Acrobat, there were a lot of forms which would call xfa.form.recalculate() in various places.  This was to ensure that fields will get updated which depend on other fields that may have changed.  Newer versions of Acrobat (8.1 and higher) are designed to not require so many calls to recalculate(), because the system is smart enough to evaluate your calculate script and figure out what fields it depends on.  The system puts "listeners" on those other fields so that whenever they change, my calculate script gets called automatically.  I don't have to declare the dependency.

For example, I have a Total field that calculates its value from several other fields (Field1, Field2, Field3).   Any time Field2 changes (due to either a calculation or to the user typing something in Field2), the Total calculate script will be called automatically.

But now make this dynamic:  add a repeating subform with Add and Remove buttons so the user can create new instances of the subform.  For example, I have a repeating subform containing a Weight field.  Outside the repeating subform, a Total field has a calculate script which sums up all the instances of that Weight field.  Pretty simple.  

clip_image001

But the listeners aren't correctly added when a new subform instance is created.  My Totals field is listening to the first instance of RepeatingSubform[0].Weight, but when RepeatingSubform [1] is created, Totals isn't listening to changes to RepeatingSubform [1].Weight.  Stefan Cameron talks about this in an older blog post:  http://forms.stefcameron.com/2006/05/20/add-recalculate/

Interestingly, look at the calculate script on Total:

var sum = 0;

var columnArray = xfa.resolveNodes( "RepeatingSubform1[*].Weight1");

for( var i = 0; i<columnArray.length; i++)

{

    sum += columnArray.item(i).rawValue;

}

this.rawValue = sum;

The call to xfa.resolveNodes() happens to cause the listeners to be updated!  This leads to very odd behavior:  if I change RepeatingSubform [1].Weight, it won't update Totals, until I change RepeatingSubform[0].Weight.  Then any additional Weight field changes will cause Total to update correctly!

So if I start with one weight field (W0) and add 3 more, I end up with weight fields like this:

                W0 (RepeatingSubform[0].Weight)

                W1

                W2

                W3

                Total

Then changes to the added ones (W1, W2, W3) won't update the Total - yet.  Changing W0 will update the total, and once you do that, now changes to W1, W2,W3 will work!

Then if I add a W4:

                W0

                W1

                W2

                W3

                W4

                Total

Now changes to W0, W1, W2, W3 will all continue to work but my newly-added W4 won't work (until I change one of W0-W3).

Workaround:

Add script to the indexChange event of RepeatingSubform, which will take care of all newly-added instances; Totals will be recalculated and will now be "listening to" the new instances.  This is more efficient than calling recalculate() on the entire form - it just recalculates that particular field or subform.

Total.execCalculate();   // Note: you can call this on a subform too:  TotalsSubform.execCalculate();

Add the same script to the delete button click() event so that the Total is recalculated when an instance is deleted.  The important part of that code is:

TotalsSubform.execCalculate();  // this avoids having to call the entire form's recalculate() method.

oTargetSubform.instanceManager.removeInstance(oTargetSubform.index);

Find recent content on the main index or look in the archives to find all content.

Recent Comments

  • Mike: Can't wait to try the Action Builder - it's exactly read more
  • Kelly Apollo: I need a tip! My customer wants the PDF form read more
  • JORGE F. VALENZUELA-PARMA: This information is truly valuable. Thank You! read more
  • Adam: Thanks for posting this. I've been looking for this answer read more
  • Duarte Cunha Leão: Showing an error message when there is a syntax error read more
  • Mike Bessuille: Thanks John! Note that John's fix removes the need for read more
  • John Brinkman: Mike: A couple comments: 1) Dependency tracking actually goes back read more
  • Helen Dyksley: Good Afternoon, after reading this article, I checked Version 7.1.2. read more
  • Mike: Good explanation, thanks read more
  • Alessio: Wow, thank you very much! read more

Recent Assets

  • ActionsBtnClkScript.png
  • ActionsBtnClick.png

Categories

Pages

Powered by Movable Type 4.261