LiveCycle Designer ExposedThe LiveCycle Designer Exposed team blog is a forum for information about Designer directly from the Adobe team building the product. We’ll post tips & tricks, known issues, etc.2009-08-18T15:56:43Zhttp://blogs.adobe.com/lcdesigner/feed/atomWordPressHelene Corbinhttp://blogs.adobe.com/lcdesigner/2009/08/submitting_crash_information_u.html2009-08-18T15:56:43Z2009-08-18T15:56:43ZContinue reading →]]>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.

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

Select Control Panel -> System and Maintenance -> Problem Reports and Solution.

In the Tasks list, click View problem history.

Locate the section of problem history for LiveCycle Designer ES.

Double-click on the event that correspond to the date and time of the crash.

Click the “Copy to clipboard” link and past it into the bug report.

Windows 7

Select Control Panel, search for “Problem Reports”, and then click on “View all problem reports”.

Double-click on the event that corresponds to the date and time of the crash.

Click the “Copy to clipboard” link and past it into the bug report.

Thank you
The LiveCycle Designer team

]]>Stephanie Legaulthttp://blogs.adobe.com/lcdesigner/2009/08/actions_and_script.html2009-08-06T14:38:24Z2009-08-06T14:38:24ZContinue reading →]]>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.

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:

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.

]]>1Stephanie Legaulthttp://blogs.adobe.com/lcdesigner/2009/08/an_intro_to_actions.html2009-08-06T14:34:25Z2009-08-06T14:34:25ZCheck out Steve’s blog post about the Action Builder.
]]>1Stephanie Legaulthttp://blogs.adobe.com/lcdesigner/2009/07/can_we_offer_some_assistance.html2009-07-16T14:43:08Z2009-07-16T14:43:08ZContinue reading →]]>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:

This is the new & improved Object Assist window:

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:

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:

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

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

For methods:

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.

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:

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.

]]>2Mike Bessuillehttp://blogs.adobe.com/lcdesigner/2008/10/script_dependencies_and_recalc.html2008-10-28T14:40:37Z2008-10-28T14:40:37ZContinue reading →]]>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.

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);

Delete button order of operations

Another interesting note: in the delete button click() event, the call to recalculate() must be placed before the instance manager call to removeInstance(). This seems wrong: shouldn’t that cause the total to include the about-to-be-deleted weight? It turns out that it doesn’t, because recalculate is deferred until after the current script finishes. (That’s intentional – so that multiple operations that cause a field to be recalculated don’t cause the calculation script to run several times in succession. And, it helps avoid infinite loops in script).

Why can’t I just put the call to execCalculate() after I remove the instance? It has to do with scope; the remove button (‘this’ in the button’s click event script) is removing its own parent subform. If I try to reference "TotalsSubform" after the removeInstance(), the system starts from the current location (this delete button), searching for TotalsSubform by walking up the tree of objects in the object model. But it can’t "walk the tree" because the current subform is now an orphan – it’s no longer in the tree! It was removed. The search fails, and the calculation doesn’t take place. A workaround for that problem is to put the call to execCalculate() after the removeInstance(), but use an explicit SOM expression from the root of the form.

]]>2Stephanie Legaulthttp://blogs.adobe.com/lcdesigner/2008/09/dot_leaders_feature.html2008-09-19T14:54:44Z2008-09-19T14:54:44ZIf you haven’t had the chance, go check out the video explaining the new “Dot Leaders” feature on Adobe’s Developer Connection site:

]]>Stephanie Legaulthttp://blogs.adobe.com/lcdesigner/2008/09/sharing_custom_objects_through.html2008-09-19T13:28:36Z2008-09-19T13:28:36ZContinue reading →]]>On top of all my top-secret work on Designer “Next”, this week I also had to track down the history of a feature change from Designer 7.1 to Designer 8.0 which was causing grief for a customer. After tracking down the change, I also looked into potential workarounds and re-discovered a feature in Designer that I had completely forgotten about (hey – in a tool as big and advanced as Designer, there’s lots and lots of features – it’s not that hard to lose track of the littler ones.) It was an interesting case and I thought I’d share it on this blog.

Our story starts with an email from a customer (that came to R&D through the Technical Account Manager and our internal eTech group) saying that when they upgraded from Designer 7.1 to Designer 8.2, a feature that they depended on for their workflow was no longer available. Here’s an extract of the email:

They are looking to create 3 different types of Object Libraries:

Libraries accessed by the entire office

Team-specific libraries

Individual libraries

They just recently moved to LiveCycle Designer 8.2 and when an end user removed a category from the Object Library palette, it actually deleted the files from the drive (folder) it was located in, which then caused everyone to lose access to the library. A particular example, the end user added the Administration category to her Object Library palette for a specific project. Once she was done with that project, she removed the category from her Object Library palette as she didn’t want to see it or need it anymore. At this point, everyone lost access to the Administration category when she removed it from her Designer client because it deleted the objects from their team’s shared folder (M: drive). They want to be able to add and remove categories without affecting other users as their team work on different projects. With Designer 7 we could do this as they would chose the Remove the group option as shown below:

In Designer 8.0 and above, you now get the following pop-up. The end user had instinctively clicked on the first entry which subsequently removed the group and all its objects as it states.

Anyone know why this behavior changed and what if any other alternatives they have going forward?

This is an interesting scenario. Anyway, the first order of business was to try to track down that particular change, to find clues as to why we would have removed the original “Remove [but don’t delete] Group” option. A quick search through our source code repository found the history of this change, which I will share for people who are interested in the gory details of development work:

I believe that when the “Restore Standard Objects” feature was implemented, we only had one “factory installed” library tab. We now have three (standard, barcodes and custom; four if you count the potential SAP.) The restore standard objects did not really work correctly anymore, as it has not been updated in a long time and the library itself has changed a lot in that time.

In order to make the restore objects feature more universal and more easily maintainable I have put in place the following changes:

– The application now considers the object libraries installed in the app folder (taking language into account of course) to be the “factory installed default” objects. The application now takes these libraries as being default and will restore the objects in any one of them. In the past, the mechanism was to embed the object files into our resources and query there for the defaults. The old method required a lot more maintanance (which I note has not been done in the intervening time), requires more complex code for managing and does not really offer any more benefit than using the installed files.

– When removing groups, there are now 2 options instead of three: delete and move & delete. The deletion now removes the underlying data directory from the file system. (Leaving the directory there was causing problems with the file restore algorithm.)

I bolded the last paragraph, because it contains the key information about why this change was made in the first place: just removing the group but leaving a directory there was breaking the “restore defaults” functionality.

After first reading this, then thinking about the above customer problem, I thought “Uh-oh. We goofed and unthinkingly destroyed a customer workflow without providing an alternative.” However, this didn’t feel right to me off the bat – the development team is usually very hesitant to remove any features/options/commands from Designer for exactly this type of reason – once it’s in place, odds are someone, somewhere depends on the feature and will be unhappy with the change.

I’m the person who made the change described in the change list text above: when I started nosing around the code, lots of the details came back to me and I remembered more about the whole “Object Library Group Management” feature. And it turns out that there’s a specific feature to manage the scenario this customer is describing. The feature isn’t as fully-developed as I would like, but even without full UI support, it’s the way you are supposed to use shared Object Libraries.

So the Object Library has two kinds of groups: “Groups” and “Shared Library Locations”.

This is the Object Library’s menu. The options we care about here are “Add Group…” and “Shared Library Location…”

In this customer’s scenario, individual libraries should be created and managed by “Add Group”; shared libraries should use the “Shared Library Location”. Some notes about the “Shared Library”: the shared library is configured by one XML file; you can have lots of shared “groups” but they’re all managed by one library. Also you can’t, in Designer, remove just one shared group – you’ll disconnect the whole library if you try (although you won’t delete it or the files – just disconnect).

Here’s what you have to do:

The shared library file should have exactly the same format as the LocalLibrary.xml file which can be found in the user’s Designer data directory (i.e. c:\users\youruserid\Appdata\…\Adobe\Designer\9.0\EN\Objects)

This file can contain as many <tab> entries as required. The <tab> entries should be changed to reflect the location/names of shared object resources on the network. The directory can point to relative paths, absolute paths, absolute paths to mapped drives (like the shared “M:” drive in the example above), and network paths.

To access the shared objects, choose “Shared Library Location…” and navigate to the SharedLibrary.xml file and press OK. There should now be tabs that have a special icon denoting their “shared” status in the object library:

To get back to the example above: in this scenario, what you want is that each user has their own SharedLibrary.xml file on their own computer. Each person would add <tab> entries to their own file: one entry per shared object location they need to access. So you would have a bunch of entries for enterprise level objects and a bunch of entries for team level objects. Your own personal objects would continue to use the “Group” option, not the “Shared Library” option. If you no longer want certain groups (say you’ve changed teams), then you would edit SharedLibrary.xml and remove all the <tab> entries that you don’t want anymore.

You could also have one SharedLibrary.xml file that everyone has to use on a shared drive somewhere. That has the benefit that only one person would need to manage the ShareLibrary.xml file, but the drawback is that each user does not have a customized set of shared objects – it’s all or nothing.

I don’t know how widespread the use of shared object library resources is: if it’s very common and lots of people were relying on the same functionality as the customers in the email above, it could be worth it for us to add more UI and functionality to manage shared object libraries…

]]>1Stephanie Legaulthttp://blogs.adobe.com/lcdesigner/2008/07/advanced_typography_options.html2008-07-23T10:50:16Z2008-07-23T10:50:16ZContinue reading →]]>We’ve added some new typographical options to Designer for 8.2. We now support kerning, horizontal and vertical font scaling and letter spacing.

Kerning

Kerning is used to reduce the spacing between glyphs to make text more visually appealing. Designer supports pair kerning, a kerning algorithm that looks at pairs of glyphs and figures out whether the glyphs can be drawn closer together. Certain glyph pairs are highly prone to kerning (like “AV” where the space between the two letters is highly symmetrical) whereas other glyph pairs are not good candidates for kerning. There is no user control over which glyph pairs will be kerned – the kerning is applied based on font metrics and kerning information embedded in the font as well as other algorithmic operations undertaken by Designer.

You can choose to apply kerning to an entire object or to a selection of text – again, whether anything gets kerned is up to Designer, but it will attempt to kern the given text.

If you apply kerning to a selection of text, or if you multi-select objects that have different kerning values, the “Auto Kern” checkbox will display a square rather than a check: this indicates varying kerning states in the current selection.

Font Scaling

Font scaling is used to independently change either the horizontal or vertical sizing of glyphs. Setting the horizontal and vertical scale to the same amount is equivalent to changing the point size (i.e. for a 10pt font, setting the horizontal and vertical scale to 200% is equivalent to doubling the point size. So the result would be identical to setting the font to be 20pt in size.)

Scaling can be applied to an entire object, or to a text selection within the object.

Letter Spacing

Letter spacing is used to force glyphs to render closer together (sort of squishing the letters) or to force letters to render further apart (expanding the text). Unlike kerning, which is applied selectively to certain glyphs that are considered good candidates, letter spacing is applied uniformly to all text.

In order to make letters render closer together, a negative value should be entered. To force the text to expand, enter a positive value.

Like the other properties, letter spacing can be applied to an entire object, or to a selection of text.

The typographical options are fairly straightforward and work like other existing typographical options. Please feel free to post any comments or questions in the comments section.

]]>1Stephanie Legaulthttp://blogs.adobe.com/lcdesigner/2008/07/hyphenation_under_the_hood_huh.html2008-07-23T10:29:27Z2008-07-23T10:29:27ZContinue reading →]]>Designer now supports automatic hyphenation of text on a form. We anticipate that this feature is going to be very popular with some clients (especially with German clients – from what I understand, German is a language that benefits a lot from auto-hyphenation.) In this post, I’ll be providing a summary of how the hyphenation feature works in Designer, along with some “under the hood” descriptions of what’s really going on when hyphenation is used.

The Nuts and Bolts

At it’s base, hyphenation instructions are really an XFA tag <hyphenation> that is a child of the <para> tag. According to the XFA grammar, any <para> tag in the whole form can have a <hyphenation> child and set specific hyphenation settings for that <para> element.

However, we did not choose to expose hyphenation in Designer as a per-<para> property. Instead, hyphenation is implemented on a per-form basis, with each individual text object either having hyphenation on or off.

The way hyphenation works is that the five different variables that control hyphenation are set at the form level and get applied to any object that has hyphenation turned on. The way we chose to implement the form level hyphenation is through the XFA <protos> mechanism. A <proto> is like a snippet of re-usable XFA; you can declare it once and then have any element “use” that proto.

How Designer Implements Form-Level Hyphenation Settings

There are actually two mechanisms that come into play when setting form-level hyphenation. The first mechanism is the application level hyphenation settings. These settings can be found under Tools | Options | Formatting. These settings control hyphenation options for new forms. So every new form created in Designer will have these hyphenation settings a a default. The goal of this menu is to allow users to customize hyphenation behavior for all forms they create, so they don’t have to constantly update the Form Properties of every new form.

The second mechanism that comes into play is to change settings on a per-form basis, in File | Form Properties | Formatting. Changing the settings here only affects the current form; new forms will still inherit the settings from the Tools | Options | Formatting menu. Changing the form-level hyphenation properties has an immediate effect on the current form: once the dialog is dismissed, all hyphenated text in the form should change to reflect the new hyphenation settings. This dialog also contains two buttons that are shortcuts for removing all hyphenation from the form and adding hyphenation to all the elements of the form. Note that these buttons have an instantaneous result – you don’t have to press “ok” on the dialog for the action to take place.

The proto hyphenation node will only be present if it is needed (i.e. some real node, somewhere in the document, is hyphenated and thus needs to use the proto.) In certain cases, if there is no proto node, but the form has hyphenation settings that differ from the default, then a Hyphenation processing instruction (PI) will be added to the document in order to save the form’s hyphenation settings.

How to Use Hyphenation in a Form

When you are actually working with your form, hyphenation is really simple to use. It’s one checkbox control on the Paragraph Inspector.

A couple of “gotchas” with hyphenation on the form:

By default, allowing hyphenation of field captions and static text is disabled. This means that the hyphenation checkbox control will be disabled on the dialog if a static text control is selected. It also means that on a control that has both caption and value text (i.e. a TextField), when the hyphenation checkbox is checked, it will fill with a square rather than a check, indicating a dual-state check (where half the control is hyphenated and the other half is not.) In order to change this behavior, enable the “Allow Hyphenation in Text and Field Captions” option in Tools | Options | Formatting (for all new forms) or in File | Form Properties | Formatting (for the current form).

Another situation where the checkbox may fill with a square rather than a check is if multiple objects are selected and some of them have hyphenation enabled and others have it disabled. The checkbox will show the “mixed” square indicator in this situation as well.

Comments on Compatibility

Hyphenation works with XFAF. However, hyphenation cannot be applied to background content.

Using hyphenation can result in target version warnings, since not all versions of Acrobat support all types of hyphenation. For the most part, hyphenation in value text is not supported in earlier versions of Acrobat (< 9.0). Hyphenation in boilerplate text is supported in older version of Acrobat for static forms. If the form is dynamic, then hyphenation of boilerplate will not be supported in older versions of Acrobat (< 9.0).

One last note on compatibility: there is a risk that using hyphenation could cause text shifting in newer versions of Acrobat. Hyphenation depends on hyphenation dictionaries to figure out where to hyphenate text. Hyphenation dictionaries can change over time: it is conceivable that new dictionaries could be introduced that would change where hyphenation points occur, leading to changes in text layout for hyphenated text. These changes would probably be very minor, but it could lead to a difference of adding/losing a line of text. The risk is fairly small, but it does exist. We strongly urge customers who have forms that are sensitive to text shifting not to make use of hyphenation.

Hyphenation and Fragments

(The following is straight from the functional specification for hyphenation:)

Hyphenation in fragments works in the same way as hyphenation in regular forms. That is, any object that is hyphenated in a fragment will have a <hyphenation use=“designer__defaultHyphenation.para.hyphenation”/> child defined under the appropriate <para> element.

When a fragment is created in a separate XDP file, if any object in the fragment contains hyphenation instructions then the fragment will be created with a <proto> element on the root subform that contains a <hyphenation> child inside a named field that is a copy of the <hyphenation> definition from the original form. The use attribute does not need to be updated, since the SOM of the hyphenation proto is the same in the fragment as it was in the original document.

If a fragment is defined within an existing XDP, nothing changes in regards to hyphenation; the <hyphenation use=“designer__defaultHyphenation.para.hyphenation”/> elements are still valid, and continue to point to the root subform’s <proto><hyphenation> element.

In both of the cases above, when a fragment is referenced from another form, it (potentially) has different hyphenation settings than the form that is referencing the fragment. The fragment’s hyphenation settings are self-contained within the fragment and separate from the referencing form’s fragment settings.

When a referenced fragment is embedded within a form, it loses its unique hyphenation settings; any <hyphenation use=“designer__defaultHyphenation.para.hyphenation”/> elements will be changed so that the use attribute points to the SOM of the root subform’s <proto> hyphenation node. Or, in other words, the fragment will now inherit the form’s hyphenation settings, rather than having different hyphenation settings that are defined in the fragment. This could potentially lead to a change in appearance and layout when a fragment is embedded.

If a hyphenated fragment is embedded within a form that does not have any hyphenation, then the fragment’s hyphenation will be lost (i.e. it still inherits the form’s hyphenation settings, namely “no hyphenation”).

To Conclude

This was an overview of the Hyphenation feature from an “under the hood” perspective. For details on how the feature works from a functional point of view, please read Designer’s Help documentation.

]]>1Stephanie Legaulthttp://blogs.adobe.com/lcdesigner/2008/07/an_example_of_splitting_text_a.html2008-07-09T17:21:20Z2008-07-09T17:21:20ZContinue reading →]]>I went on a customer visit and was asked to solve an interesting problem. Basically, this customer had a regulatory PDF form. The form’s layout couldn’t change, and at the end of a workflow process, the form was printed as a document of record. This form was very complicated, with lots of special logic (i.e. “if field 2b is filled, then options 7a, b, and d are no longer available”.) The customer opted to try out Adobe’s Form Guide technology to make the form filling experience better, but once the Guide was complete, we had to take the data from the Guide and push it back to the PDF form (using LiveCycle) and then print the PDF form to paper.

This form had many small fields with instructions indicating that if the field couldn’t contain all the info, to add an appendix page with the rest of the text. Now, in most cases, we would encourage clients to make fields growable, so that they will just expand to fit the text put in them and all the subsequent form content will move down. However, in this case, due to the need for the form to preserve it’s original layout for printing, we couldn’t do that.

It was actually hard to solve this problem: we tried many different scenarios, but most of them were dead ends. The essential problem we kept running into was that the XFA model just doesn’t provide the information you would need to calculate or extrapolate how much text can fit in a given field.

The only solution we came up with that worked fairly well is in the form below. It involves using a fixed-width font in the fixed field, so that reasonable assumptions can be made about how much text can fit into a given field. There’s script that parses text and splits it between two fields. The script is heavily commented, so hopefully readers can figure out what’s going by reading the code.