Archive for September, 2010

E4X in Form Design

Over the time that I’ve been writing blog entries I’ve made many references to E4X and have included lots of samples that make use of this technology. However I’ve recently come to understand that I probably should have done a better job of introducing E4X usage, since it isn’t necessarily well understood by the average form developer.

For those of you who are unaware, E4X is an extension to JavaScript (ECMAScipt) for manipulating XML.  The reason it is not particularly well known among JavaScript developers is that few of the browsers have implemented E4X.  The notable exception is Mozilla / Firefox. And since the JavaScript engine inside Acrobat/Reader is based on Mozilla, E4X can be used reliably in Acrobat/Reader.

To learn more about E4X, here are some links you may find useful:

http://www.xml.com/pub/a/2007/11/28/introducing-e4x.html

http://www.ecma-international.org/publications/standards/Ecma-357.htm

http://rephrase.net/days/07/06/e4x

http://wso2.org/project/mashup/0.2/docs/e4xquickstart.html

The XMLData Object

Before E4X was invented, we had recognized the need to have generic XML processing in Acrobat / Reader. Consequently, we added the XMLData object to the Acrobat object model.

However, E4X was introduced shortly afterwards, and we ended up with two XML processing engines in Acrobat/Reader. In case there is any doubt, the right answer is to use E4X. You should no longer use the XMLData object. The XMLData object remains in the product for backward compatibility, but it does not get enhanced, it does not get bug fixes.  E4X is faster and uses less memory.

Some Usage Notes

There are several common learning curve issues you might encounter when using E4X:

Oddly, E4X refuses to process the xml processing instruction at the front of an XML fragment.  If it’s there, you will get a syntax error: “xml is a reserved identifier”.

The workaround is to remove leading processing instructions with a regular expression such as:

sXML = sXML.replace(/^[\s\S]*?(<[^\?!])/, “$1″);

Processing Instructions and Comments

By default E4X ignores processing instructions and comments. You can change the default with:

XML.ignoreProcessingInstructions = false;
XML.ignoreComments = false;

If you stop ignoring comments and processing instructions and if you are processing an XML fragment that includes an outer comment or processing instruction, you need to treat it as an XMLList object instead of an XML object:

XML.ignoreProcessingInstructions = false;
var xyz = new XMLList(‘data’);
xyz.toXMLString();

JSLint

Since I just finished recommending JSLint to you, I should point out that JSLint doesn’t handle the E4X syntax extensions to JavaScript.  e.g. XML literals. It will stop processing once it encounters syntax specific to E4X. In most cases you can keep JSLint happy by using function calls instead of the syntax extensions.  e.g. instead of:

xXML..a.length();

use:

xXML.descendants(“a”).length();

Mixed namespaces

Consider this example:

var xXML = <root><one><two>abc</two></one></root>;

The expression: xXML.one.two.toString(); returns “abc”. However, if I introduce another namespace, this expression no longer works:

var xXML = <root><one><two xmlns=”foo”>abc</two></one></root>;

Instead, use: xXML.one.*::two.toString();

And for completeness, the JSLint friendly version:

var xXML = new XML(‘<root><one><two xmlns=”foo”>abc</two></one></root>‘);
xXML.one.child(QName(null, “two”)).toString();

JavaScript Lint check in Designer

Some time ago I distributed a sample form that used Douglas Crockford’s excellent JSLint script to check form JavaScript for common coding errors.  You can read about it here. The logical next step is to use macros to integrate this capability into Designer (macros introduced here).

Here is everything you need to install the macro.

One improvement I’ve made over the previous version is to automatically populate the list of global objects with all the subform and field names in the form.  Now it will flag far fewer global objects — and if it does flag a global, you really want to pay attention, since it is very likely an un-declared variable.

I really strongly recommend this tool to you. When you run this against your script you will very likely be surprised at some of the coding errors you’ve made.  I know I was.

XDP Size Matters

I have recently been involved in a couple of contexts where customers have worked hard to reduce the size of their XDP and resulting PDF files.

We know that size matters.  The smaller the better.  We want small PDF files for downloading.  We know that encryption-based technologies such as certificates and rights enabling perform faster when the form definition is smaller.  Today’s discussion is a couple of tips for reducing the size of your XDP and PDF.

When concerned about size, the first two places to look are fonts and images.  I’ve covered images a couple times.  Check out: Linked vs Embedded Images and also the sample in Parameterize your SOAP address.

Fonts are a simple discussion.  Your PDFs are much smaller when the fonts are not embedded. If you need to embed fonts, use as few as possible.  To see which fonts are referenced by you form, you can check out the form summary tool here.

But the main topic for today is syntax cleanup.  The elements and attributes in the XFA grammar all have reasonable default values.  We save lots of space by not writing out the syntax when the value corresponds to the default.  For example, the default value for an ordinate is "0". If your field is at (0,0), we will not write out the x and y attributes. 

However, there are a couple of places where the syntax cleanup could use some help. Specifically: borders (edges and corners) and margins. There are scenarios where these elements can be safely deleted from your form.

Today’s sample is a Designer macro (with the sample form) for eliminating extra syntax. If you don’t want to understand the gory details, you can just download and install the Designer macro.  (If you haven’t already, please read this regarding Designer macros).  After running the macro, look in Designer’s log tab for a summary of the cleanup.  Then double check the rendering of your form and make sure it hasn’t changed.

If you want to understand a bit more, I’ll explain what is going on.  There are three instances of syntax bloat that the macro will clean up:

Extra corners

In the attached form there are two fields: border1 and border2. 

The border definition for border1 looks like:

<border>
  <edge thickness="0.882mm"/>
  <corner thickness="0.882mm"/>
  <edge thickness="0.3528mm"/>
  <edge thickness="0.3528mm"/>
  <edge thickness="0.3528mm"/>
  <corner thickness="0.353mm"/>
  <corner thickness="0.353mm"/>
  <corner thickness="0.353mm"/>
</border>

When you modify edge properties, designer will inject <corner> definitions. However, the only time a corner definition has any impact on the rendering is when the radius attribute is non-zero.  In this example, the <corner> elements may all be safely removed without changing the rendering of the form.

Hidden Borders

The border definition for border2 looks like:

<border>
  <edge thickness="0.882mm" presence="hidden"/>
  <corner thickness="0.882mm" presence="hidden"/>
  <edge thickness="0.3528mm" presence="hidden"/>
  <edge thickness="0.3528mm" presence="hidden"/>
  <edge thickness="0.3528mm" presence="hidden"/>
  <corner thickness="0.353mm" presence="hidden"/>
  <corner thickness="0.353mm" presence="hidden"/>
  <corner thickness="0.353mm" presence="hidden"/>
</border>

I’m not sure how I ended up with this configuration, but as you can see, all the edges and corners are hidden.This would be be represented more efficiently as <border presence="hidden"/> or better yet, no border element at all. But before cleaning up this syntax, bear in mind that there can be a useful purpose here.  If you have script that toggles the presence of border edges, it is useful to have the edge properties (e.g. thickness, color) defined in the markup.  If you remove the markup, you will need to set those properties via script.

Zero Margins

If you have edited object margins, you could end up in a situation where your margin element looks like:

<margin topInset="0mm" bottomInset="0mm" leftInset="0mm" rightInset="0mm"/>

Since the default margin insets are all zero, this element can be safely removed.

How frequently this syntax bloat occurs in your forms depends on your editing patterns. In my testing against several customer forms, I saw size reductions of 10 – 15% by removing these elements.

 

Editable Floating Fields V3

I had a user report a bug in the floating field sample  — the sample described in these blog entries: Version1   Version2

I’ve updated the code again.  The specific problems fixed were:

  1. The editing field can now be unbound (binding="none"). This is important in cases where you are using an xml schema and there isn’t data that you can bind to the editor field.
  2. There was a problem with preserving trailing spaces in edited values.  The easiest fix was to strip trailing spaces from the edited values.

Here is the updated form.  And the updated fragment.