Forms vs. Applications … and how to make them behave John Brinkman Adobe Enterprise Forms Architect
History
Several years ago we recognized the pattern where customers were developing forms with too much JavaScript, too much complexity On analysis we recognized that we needed to take two approaches 1.
Product improvements to reduce the need for JavaScript
2.
Better user education on form design patterns
http://blogs.adobe.com/formfeed (since October 2008)
History
Several years ago we recognized the pattern where customers were developing forms with too much JavaScript, too much complexity On analysis we recognized that we needed to take two approaches 1.
Product improvements to reduce the need for JavaScript
2.
Better user education on form design patterns
http://blogs.adobe.com/formfeed (since October 2008)
Outline
1.
Forms, Applications and Monsters
2.
Steps to Sanity
3.
Form Design Review (Library of Congress) Congress)
So you’ve decided to use PDF forms…
You want to:
Enforce business rules Create a really good user experience
Now you need to add script to your forms
Will you be creating a monster?
We see users create forms with: o
Tens of thousands of lines of script
o
Several megabytes megabytes in size si ze
o
Slow open time
o
Sluggish performanc per formancee
o
Big memory footprint
o
High maintenance costs
o
Susceptible to changes in new versions of Reader
o
These are our "monster forms"
Will you be creating a monster?
Nobody sets set s out to create a monster They start small and the requirements start to creep Form complexit complexityy grows incrementally After several se veral revi revisions sions of the form you have a large investment in JavaScript
The small monster
You wrote a modest amount of code Not the most elegant code … but it works
The small monster
You wrote a modest amount of code Not the most elegant code … but it works You have a manageable, small monster
The small monster
You wrote a modest amount of code Not the most elegant code … but it works You have a manageable, small monster
Your initial form is a great success!
The small monster
You wrote a modest amount of code Not the most elegant code … but it works You have a manageable, small monster
Your initial form is a great success! You copy the code and design patterns to 200 new forms in your department
The small monster
You wrote a modest amount of code Not the most elegant code … but it works You have a manageable, small monster
Your initial form is a great success! You copy the code and design patterns to 200 new forms in your department You discover a flaw in your design pattern – affecting all 200 forms…
The small monster
You are now trying to tame an army of small monsters
Bad habits escalate
Inefficient code is excusable in small forms -- does not factor into overall processing costs Small inefficiencies in small forms become big inefficiencies in big forms Design flaws repeated over many small forms become a maintenance nightmare
Two Problem Scenarios
The big monster form:
many person-years of development invested Critical to business processes Fragile to update, hard to test Susceptible to changes in Reader
The collection of small monster forms:
Collectively, many person-years invested Used in many parts of the business Common code not shared: maintenance is very expensive Re-testing is a big job
Where did we go wrong?
It is perfectly valid to develop forms with lots of script If the script is well-written the form(s) can be:
Performant Low maintenance Testable
BUT… Adopt a new mindset: You are no longer developing forms You are developing applications Are you ready for application development?
Application Development Methodology
Do your form developers have programming skills? Do you have coding standards? Do you perform code reviews? Do you have a source control system? Do you insist on documentation? Do you aggressively modularize common code patterns? Are you prepared to take a step backward and re-factor when needed? Do you have a quality assurance methodology? Do you have a form deployment methodology?
You’ve been granted custody of a monster
You’ve been asked to add an enhancement or diagnose a problem -- but don’t know the intricacies of the form How do I tame the monster? Welcome to my world
Outline
1.
Forms, Applications and Monsters
2.
Steps to Sanity
3.
Form Design Review (Library of Congress)
Steps to sanity 1.
Be an expert
2.
Bring your forms to version 9.1
3.
Share code
4.
Think Accessibility First
5.
Get to know the available tools
6.
Common problems, common solutions
Steps to sanity
Be an expert:
1.
JavaScript XML XFA
Be a JavaScript Expert
JavaScript has some very powerful constructs that (if used correctly) can greatly improve your code
Can you write a recursive function? Do you use try/catch? Do you use arrays and object literals? Do you understand JavaScript closure? Do you use regular expressions?
Be a JavaScript Expert
There are different implementations of JavaScript Acrobat/Reader uses Mozilla JavaScript (Spidermonkey) Includes E4X for manipulating XML Check out this web page: http://code.google.com/p/jslibs/wiki/JavascriptTips Server products use ExtendScript – highly compatible
Steps to sanity
Be an expert:
1.
JavaScript XML
XFA
Be an XML Expert
Can you create an XML document in notepad? Have you ever written an XSL script? Can you decipher an XML Schema? Do you know how XLIFF is used? Do you understand XHTML? You need to be familiar with the basics of each
Steps to sanity
Be an expert:
1.
JavaScript XML XFA
Be an XFA Expert
XFA Schema XFA Scripting Object Model SOM expressions XFA Events
XFA (template) Schema
Publicly documented (in detail) Visible in XML Source view
Be an XFA Expert
XFA Schema XFA Scripting Object Model
SOM expressions XFA Events
XFA Scripting Object Model
The scripting object model closely mirrors XFA grammar. e.g.:
Set field background color:
city.border.fill.color.value = "100,100,100";
or (shortcut): city.fillColor = "100,100,100";
Script Properties that do not correspond to schema:
DOM hierarchy:
Shortcuts:
boundItem, length, selectedIndex
Field values:
borderColor, borderWidth, fillColor, fontColor, formatMessage, mandatory, mandatoryMessage, validationMessage
Dropdown lists:
all, index, classAll, classIndex, className, somExpression, instanceIndex, isContainer, model, parent, parentSubform, nodes
isNull, rawValue, formattedValue, editValue
Miscellaneous:
dataNode, errorText, oneOfChild
Be an XFA Expert
XFA Schema XFA Scripting Object Model SOM expressions
XFA Events
SOM Expressions
Used in data binding Used as the parameter to resolveNode() and resolveNodes() Used for FormCalc expressions
SOM expressions and JavaScript Object Expressions
Similar, but not the same. E.g.
A.B.rawValue
Is evaluated differently from:
this.resolveNode("A.B").rawValue;
Can return a different result, but usually does not SOM has extra capabilities that object expressions do not have
SOM Expressions
item[-1] po.* item.#field[*]
// previous item // all children of po // all field children of item // predicate in FormCalc:
po.item.[subtotal > 100]
// predicate in JavaScript: po.item.(subtotal.rawValue > 100)
Be an XFA Expert
XFA XFA Schema Schema XFA Scripting Object Model SOM expressions XFA Events
Use XFA Events Effectively
Filter keystrokes keystrokes onChange onChange e.g.:
Convert input to input uppercase Prevent users from formatting telephone numbers (demo)
Use xfa.event.cancelAction inside preSub preSubmit mit / preSign preSign / prePri prePrint nt to cancel cancel if conditi conditions ons aren’t aren’t right right Use initialize to change properties properties that designer doesn’t doesn’t expose Use propagating events (details later)
Use XFA Events Effectively
Use execEvent() minimally. It is not intended as a method for sharing code Put shared code in script objects:
Better performance Better code readability
Steps to sanity
1.
Be an expert
2.
Bring your forms to version 9.1
3.
Share code
4.
Think Accessibility First
5.
Get to know the available tools
6.
Common problems, common solutions
Acrobat 9.1
Enhancements in the 9.1 release specifically addressed the issue of excessive code in forms
Full control over validation processing Propagating events field.presence = "inactive"
Acrobat 9.1 (XFA 3.0)
Historical Reader behavior was to issue one error message per validation failure Form authors wrote their own validation frameworks – in order to avoid the message boxes
Encapsulation
In this context Encapsulation means:
Keep the code that defines field behaviour inside the field Validations, calculations should be defined in field calculation, validation scripts Messages that are specific to a field defined within the field
Encapsulated validation
Numeric Field: A.B.C.D:
Encapsulation.A1.B.C.D::validate - (JavaScript, client) this.rawValue > 0;
encapsulation.A1.B.C.D::validationState - (JavaScript, client) this.borderColor = this.errorText ? "255,0,0" : "0,0,0"; this.assist.toolTip.value = this.errorText;
External Ex ternal validation validation
Numeric Numeric Field: A.B.C.D A .B.C.D Button Field: checkForm
encapsulation.v encapsulatio n.validate alidate::click ::click - (JavaScr (JavaScript, ipt, client) var field = A.B.C.D; var bValid = field.isNull || (field.rawValue > 0); if (bValid) { field.borderColor = "0,0,0"; field.assist.toolTip.value = ""; } else { field.borderColor = "255,0,0"; field.assist.toolTip.value = "The value of D must be greater than zero"; }
Why is encapsulated better?
(demo) Better (immediate) user validation feedback No need for a separate action to trigger validation Form processor will prevent submit if there are validation failures External validation is replicating functionality found in the XFA processor External validation requires writing code for mandatory processing – encapsulated encapsulated version is i s handled declaratively Less code, simpler code
Why is encapsulated better?
If any subforms are renamed/moved renamed/moved/unwra /unwrapped, pped, the field SOM expression changes Changed SOM expression causes the external validation script to break:
var field = A.B.C.D; var bValid = field.isNull || (field.rawValue > 0); if (bValid) { ...
In the encapsulated version, there are no references to field or subform names, only “this” object.
Why is encapsulated better?
When field "D" is included in a fragment: Encapsulated:
Validation logic is automatically included
Not Encapsulated:
External validation logic not automatically included in the fragment External logic needs to be knit into the validation logic of the host form
Acrobat 9.1 (XFA 3.0) Propagating events
When the same event logic appears on many fields, we can define the event once and propagate Use cases:
Field highlighting on enter or mouseEnter Change field appearance on validationState Change row color on indexChange
Designing Propagating events
ES2 designer does not allow you to define propagating field events on a subform A10 designer removes the propagating UI To use them you need to edit XML source – or use a macro demo: uniqueValues.pdf
Inactive presence
object.presence = "visible | invisible | hidden | inactive"; visible: object is rendered; events fire invisible: object is not rendered; participates in layout; events fire hidden: object is not rendered; excluded from layout; events fire inactive: objects is not rendered; excluded from layout; events do not fire
(demo)
Payment sample
Payment Type validation script:
if (this.rawValue === "Credit Card") { CreditCardDetails.presence = "visible"; } else { CreditCardDetails.presence = "inactive"; } // this isn't really a validation – // just a place to trigger on changes to this field true;
How to bring a form to 9.1
Remove the compatibility PI
Bug fixes can change the behaviour of forms We use a processing instruction to ensure compatibility between Reader releases Compatibility PI ensures you continue to get the same set of behaviours (and same set of bugs) in new releases To get the latest, from XML Source view, remove:
What if you can’t move to 9.1 yet?
It is possible to build a framework that uses encapsulation and avoids the message boxes Samples on the formfeed blog
Steps to sanity
1.
Be an expert
2.
Bring your forms to version 9.1
3.
Share code
4.
Think Accessibility First
5.
Get to know the available tools
6.
Common problems, common solutions
Share Code
Code sharing is one of the disciplines of good programming Benefits of code sharing:
Less code Faster development Lower maintenance costs Consistent behaviours within a form and between forms Simplify complex operations for use by novice form designers
Share Code
BUT … to get the benefits of code sharing you need to make an investment:
Recognize repeated patterns Generalize the repeated operation Isolate the variable parts of the operation into parameters The generalized version of functionality has higher up-front development costs Once the initial investment has been made in shared code, the ROI will more than compensate
Share Code
Code Sharing Mechanisms:
Functions within a script event Functions within a script object Script objects stored as fragments Propagating events
Shared Code Sample
Task: Copy all field data from one subform to another. Brute force code looks like:
S2.F1.rawValue = S1.F1.rawValue; S2.F2.rawValue = S1.F2.rawValue; S2.F3.rawValue = S1.F3.rawValue; S2.F4.rawValue = S1.F4.rawValue; S2.F5.rawValue = S1.F5.rawValue;
(demo)
Shared Code Sample
Before:
S2.F1.rawValue = S1.F1.rawValue; S2.F2.rawValue = S1.F2.rawValue; S2.F3.rawValue = S1.F3.rawValue; S2.F4.rawValue = S1.F4.rawValue; S2.F5.rawValue = S1.F5.rawValue;
After:
utilities.subformCopy(S2, S1);
Create a fragment from a script object
Steps to sanity
1.
Be an expert
2.
Bring your forms to version 9.1
3.
Share code
4.
Think Accessibility First
5.
Get to know the available tools
6.
Common problems, common solutions
Think Accessibility First
Even if Accessibility is not currently a requirement, make sure you know what an accessible form looks like The up-front development costs for Accessible forms are much lower than retrofitting accessibility
Think Accessibility First
Some design patterns are not accessibility-friendly Most importantly:
Use captions. Do not use separate text objects Make sure your tables have rows designated as a header Carefully define tab order Don’t rely on color to convey invalid fields
Correcting these after the fact is expensive
Steps to sanity
1.
Be an expert
2.
Bring your forms to version 9.1
3.
Share code
4.
Think Accessibility First
5.
Get to know the available tools
6.
Common problems, common solutions
Get to know the available tools
Use the JavaScript console Form Summary Tool Dump the data DOM XFA Debugger JSLint Accessibility Checker XLIFF translator Develop your own Designer Macros
Use the JavaScript console
JavaScript errors show up in the console At the end of a form session, make sure there are no errors in the console Use console.println() to trace code Better yet, leave conditional trace statements in your code permanently
Get to know the available tools
Use the JavaScript console Form Summary Tool
Dump the data DOM XFA Debugger JSLint Accessibility Checker Develop your own Designer Macros
Form Summary Tool
Effective way to get an overview of form content Understanding the details of a form report can help identify problems (demo)
Get to know the available tools
Use the JavaScript console Form Summary Tool Dump the data DOM
XFA Debugger JSLint Accessibility Checker Develop your own Designer Macros
Dump the data DOM
Many form design challenges require a good understanding of what the data looks like Easiest way to understand the data is to dump a snapshot (demo)
Get to know the available tools
Use the JavaScript console Form Summary Tool Dump the data DOM XFA Debugger
JSLint Accessibility Checker Develop your own Designer Macros
XFA Debugger
For advanced form design it helps to have an understanding of the form processing stages Opening a form: 1.
Create several DOMs
2.
Merge data and template
3.
Perform calculations and validations
4.
Perform layout (pagination)
XFA Debugger gives insight into the final DOMs and resulting layout
XFA Debugger
How it is implemented:
Acroform PDF with a button that loads and opens an XFA-PDF Once open, uses the XFA scripting object model to extract the state of the form Passes the state to an embedded flash widget Flash widget decodes state and displays it graphically
(demo)
Get to know the available tools
Use the JavaScript console Form Summary Tool Dump the data DOM XFA Debugger JSLint
Accessibility Checker Develop your own Designer Macros
JS Lint Thank you Douglas Crockford http://www.jslint.com/ (demo)
Accessibility Checker
Accessibility experience is only as good as the effort made by the form author Accessibility Checker is a Designer Macro that reports on a few basic properties throughout your form Does not check everything e.g. low contrast colors
(demo)
XLIFF Translator
Set up designer to embed xliff id’s in your form template XLIFF translator sample is a form whose data schema is the XLIFF schema Translator sample updates the visible form when translating text
Create your own Designer macros
The scripting object model is the same as the model used by the runtime Several samples available to get started Lots of possibilities
Enforce your own design checks Apply bulk updates Generate reports ...
Steps to sanity
1.
Be an expert
2.
Bring your forms to version 9.1
3.
Share code
4.
Think Accessibility First
5.
Get to know the available tools
6.
Common problems, common solutions
Common problems and probable causes
Large PDF size Slow open time Sluggish performance Big memory footprint Layout issues (blank pages)
Large PDF Size
Embedded fonts Embedded images Too many objects
Embedded fonts
If you need to embed fonts:
Use as few fonts as possible More control over font embedding on server:
Specify which fonts are embedded and which are not Specify thresholds for font subsetting
Fonts used by interactive form fields may not be subset Don’t need to embed fonts installed by Adobe Reader
Embedded Images
Embedded Image
The image is *always* embedded in the PDF "Embedded" refers to whether it is embedded in the form design Whether the image is embedded in the template or not has a big impact on how it is stored in the PDF and how it is processed
Linked image
. . .
Embedded Image /9j/4S5+RXhpZgAASUkqAAgAAAAHAA8BAgAGAAAAYgAAABABAgAOAAAAaAAAABoBBQABAAAAdgAA ABsBBQABAAAAfgAAACgBAwABAAAAAgAAADIBAgAUAAAAhgAAAGmHBAABAAAAmgAAAKoCAABDYW5v bgBDYW5vbiBFT1MgNjBEAPAAAAABAAAA8AAAAAEAAAAyMDExOjAyOjA5IDIyOjA2OjIwAB0AmoIF AAEAAAD8AQAAnYIFAAEAAAAEAgAAIogDAAEAAAABAAAAJ4gDAAEAAACQAQAAMIgDAAEAAAACAAAA MogEAAEAAACQAQAAAJAHAAQAAAAwMjMwA5ACABQAAAAMAgAABJACABQAAAAgAgAAAZIKAAEAAAA0 AgAAApIFAAEAAAA8AgAABJIKAAEAAABEAgAABZIFAAEAAABMAgAAB5IDAAEAAAAFAAAACZIDAAEA AAAJAAAACpIFAAEAAABUAgAAkZICAAMAAAA1MgAAkpICAAMAAAA1MgAADqIFAAEAAABcAgAAD6IF AAEAAABkAgAAEKIDAAEAAAACAAAAAaQDAAEAAAAAAAAAAqQDAAEAAAABAAAAA6QDAAEAAAAAAAAA BqQDAAEAAAAAAAAAMaQCAAsAAABsAgAAMqQFAAQAAAB4AgAANKQCAAYAAACYAgAANaQCAAsAAACe AgAAAAAAAAEAAACgAAAAIwAAAAoAAAAyMDExOjAyOjA5IDIxOjU1OjU3ADIwMTE6MDI6MDkgMjE6 NTU6NTcASLlvAEBCDwD/gwUAoIYBAAAAAAABAAAAAwAAAAEAAABpAAAAAQAAAAAaTwCJAwAAALw0 AFMCAAAwNTcwMzA5MTI0AABpAAAAAQAAAGkAAAABAAAAAAAAAAAAAAAAAAAAAAAAADEwNW1tADAw MDAwMDAwMDAAAAYAAwEDAAEAAAAGAAAAGgEFAAEAAAD4AgAAGwEFAAEAAAAAAwAAKAEDAAEAAAAC AAAAAQIEAAEAAAAIAwAAAgIEAAEAAABuKwAAAAAAAEgAAAABAAAASAAAAAEAAAD/2P/uAA5BZG9i ZQBkAAAAAAH/2wCEAAYEBAQFBAYFBQYJBgUGCQsIBgYICwwKCgsKCgwQDAwMDAwMEAwMDAwMDAwM DAwMDAwMDAwMDAwMDAwMDAwMDAwBBwcHDQwNGBAQGBQODg4UFA4ODg4UEQwMDAwMEREMDAwMDAwR DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDP/AABEIAKsBAAMBEQACEQEDEQH/3QAEACD/xAGi AAAABwEBAQEBAAAAAAAAAAAEBQMCBgEABwgJCgsBAAICAwEBAQEBAAAAAAAAAAEAAgMEBQYHCAkK CxAAAgEDAwIEAgYHAwQCBgJzAQIDEQQABSESMUFRBhNhInGBFDKRoQcVsUIjwVLR4TMWYvAkcoLx
Embedded Image
Images embedded in the template are stored in base64 format Causes very large templates: base64 is 4/3 bigger than binary Forces Designer and Reader to keep the image in DOM memory Slower open times, higher memory footprint, slower performance in Reader and Designer Same image used times is stored times
Linked Images in PDF
Linked images are stored in a PDF names tree Linked images are all resolved to a single copy of the image
Embedded Image storage in PDF
PDF
XDP (Template)
Base64 Image Base64 Image
Linked Image storage in PDF
PDF
XDP (Template)
Names Tree
Binary Image
Too many objects
Your form may be too large if you have:
Text labels instead of captions Unnecessary wrapper subforms Spacing objects Rectangles instead of borders Rich text instead of plain text Duplicated subform instead of repeated subform
Slow open time
Forms with certification and encryption take longer to open
(Rights enabling uses encryption) Large form open time degrades more quickly with decryption
Too many pages!? Tortured tables – complex row/cell definitions Fix your binding warnings
Sluggish Performance
Form too large Too much script Circular script references Forced re-layout or re-merge
Big memory footprint 1.
Use strict scoping
2.
Use strict scoping
3.
Use strict scoping
4.
Don’t use Acroforms XMLData object (use E4X instead)
Layout issues
Bring your form ahead to 9.1 and re-test
Many layout bug fixes in 9.0 and 9.1 Even if you know you can’t use 9.1, you at least will know if it is a bug or a user error
Use XFA Debugger to check for layout warnings
Outline 1.
Forms, Applications and Monsters
2.
Steps to Sanity
3.
Form Design Review (Library of Congress)
Form Review
Library of Congress Registration Form
Review Step 1
Form Report:
Target: XFA 2.5 (Reader 7.05) Strict Scoping Off
Bring form version to 9.1 Turn on strict scoping Start size: 1.66MB New size after moving to 9.1: 938KB
Step 1b) Check for errors
Conversion to strict scoping and moving to a newer version can expose script errors Test the form and watch the script console With the LOC form, we needed to fix 3 scripting issues
Review Step 2
From the report: Fonts are embedded
1 instance of "Times New Roman" 9 instances of "Georgia" 15 instances of "Verdana" 366 instances of "Myriad Pro"
Step 2: Reduce Fonts
Change 1 instance of "Times New Roman" to "Myriad Pro" :
Change 9 instances of "Georgia" to "Myriad Pro" :
New size: 505KB
Change 15 instances of "Verdana" to "Myriad Pro" :
New size: 703 KB (From 938KB)
New size: 321KB
(demo)
Step 3: Embedded Images
Two embedded images are 136KB and 26KB Replace with links
New size: 312KB (from 321 KB)
Step 4: Country Drop Down Lists
Seven address blocks with a country drop down list
259 countries in each list 1813 total elements for drop down lists (15% of form definition)
Load the lists from a macro on preOpen event:
function load(countryField) { var countries = ["Afghanistan",… "Zimbabwe"]; countryField.setItems(countries.join(",")); }
New size: 299KB (from 312KB)
Check in XFA Debugger
Many objects marked as growable that do not need to be growable Growable objects are more expensive than fixed size objects for layout Not a critical problem for this form, but on a large scale could become noticeable Likely an artefact of early version of Designer
Review Step 5: Code Review
ACR.details.AI.f2af::initialize - (JavaScript, client) if(this.rawValue==null) this.rawValue="";
ACR.details.Cert.FID::initialize - (JavaScript, client) if(this.rawValue=="" || this.rawValue==null) this.rawValue=ACR.WBRT.FID.rawValue;
Empty fields are always null
ACR.details.AI.f2af::initialize - (JavaScript, client) if(this.rawValue==null) this.rawValue="";
ACR.details.Cert.FID::initialize - (JavaScript, client) if(this.rawValue=="" || this.rawValue==null) if(this.isNull) this.rawValue=ACR.WBRT.FID.rawValue;
If you want a string…
field.rawValue
– data type according to field value
field.formattedValue
– always returns string
field.editValue
– always returns string
Validation on exit ACRegistration.details.Author_Information.f2gpseu::exit - (JavaScript, client) if(pseudo_2g.rawValue=="Yes" && this.rawValue==null || pseudo_2g.rawValue=="Yes" && this.rawValue=="") { xfa.host.messageBox("You must enter a Pseudonym"); xfa.host.setFocus(this); }
(demo 2g) Exit event is not a good place to perform validations (save/close/reopen sequence will leave the field invalid – but not detected) Exit validation traps the user in the mandatory field Validation logic is repeated in global script Should use presence="inactive" and mandatory setting
Alternative: Design f2gpseu as "required"
ACR.Author.pseudo_2g::change - (JavaScript, client) if(this.rawValue=="Yes") { f2gpseu.presence = "visible"; TextField2.presence = "visible"; anon_2g.rawValue = ""; } else {
f2gpseu.presence = "invisible inactive"; f2gpseu.rawValue = ""; TextField2.presence = "invisible"; }
Validate numeric ACR.Cert.f8dacc::exit - (JavaScript, client) formTools.isNumeric(this);
isNumeric() – if not all digits, message box error and resets focus back in the field Alternative is to prevent alpha input via the change event
Code to copy subforms... if(this.rawValue==1) { xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_same_as_rights").rawValue= 0; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_first").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3af").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_middle").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3am").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_last").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3al").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_org").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3b").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_street").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_street2").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c2").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_city").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_cit").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_st").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_st").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_postal").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_pos").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_coun").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_cou").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_email").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_email").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_phone").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_phone").rawValue; } if(this.rawValue==1){ xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_same_as_claimant").rawValue= 0; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_first").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_first").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_middle").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_middle").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_last").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_last").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_org").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_org").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_street").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_street").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_street2").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_street2").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_city").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_city").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_st").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_st").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_postal").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_postal").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_coun").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_country").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_email").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_emai").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_phone").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_phone").rawValue; } if(this.rawValue==1){ xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_same_as_rights").rawValue= 0; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_same_as_correspondance").rawValue= 0; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_first").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3af").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_middle").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3am").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_last").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3al").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_org").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3b").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_street").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_street2").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c2").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_city").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_cit").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_sat").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_st").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_postal").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_pos").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_coun").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_cou").rawValue; } if(this.rawValue==1){ xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_same_as_claimant").rawValue= 0; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_same_as_rights").rawValue= 0; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_first").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_first").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_middle").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_middle").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_last").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_last").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_org").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_org").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_street").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_street").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_street2").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_street2").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_city").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_city").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_sat").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_st").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_postal").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_postal").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_coun").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Correspodence_Contact.f6_coun").rawValue; } if(this.rawValue==1){ xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_same_as_claimant").rawValue= 0; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_same_as_correspondance").rawValue= 0; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_first").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_first").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_middle").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_middle").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_last").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_last").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_org").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_org").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_street").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_street").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_street2").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_street2").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_city").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_city").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_sat").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_st").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_postal").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_postal").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Mail_Certificate_To.f7_coun").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_country").rawValue; } if(this.rawValue==1){ xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_first").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3af").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_middle").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3am").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_last").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3al").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_org").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3b").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_street").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_street2").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c2").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_city").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_cit").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_st").rawValue=xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_st").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_postal").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_pos").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_country").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_cou").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_emai").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_email").rawValue; xfa.resolveNode("Application_for_Copyright_Registration.details.Rights_and_Permissions_Contact.f5_phone").rawValue= xfa.resolveNode("Application_for_Copyright_Registration.details.Copyright_Claimain_Information.f3c_phone").rawValue;
Code needed when subform copy is shared code… if (this.rawValue === 1) { f6_same_as_rights.rawValue = 0; util.SF_Copy(Correspodence_Contact, Copyright_Claimain_Information); } if (this.rawValue === 1) { Correspodence_Contact.f6_same_as_claimant.rawValue = 0; util.SF_Copy(Correspodence_Contact, Rights_and_Permissions_Contact); } if (this.rawValue === 1) { f7_same_as_rights.rawValue = f7_same_as_correspondance.rawValue = 0; util.SF_Copy(Mail_Certificate_To, Copyright_Claimain_Information); } if (this.rawValue === 1) { f7_same_as_claimant.rawValue = f7_same_as_rights.rawValue = 0; util.SF_Copy(Mail_Certificate_To. Correspodence_Contact); } if (this.rawValue === 1) { f7_same_as_claimant").rawValue = f7_same_as_correspondance").rawValue = 0; util.SF_Copy(Mail_Certificate_To, Rights_and_Permissions_Contact); } if (this.rawValue === 1) { util.SF_Copy(util.SF_Copy(Rights_and_Permissions_Contact, Copyright_Claimain_Information); }
Seldom (if ever) need to construct a SOM expression var numberOfTitles = 0; numberOfTitles = ACR.details.WBR.instanceManager.count; for(x=0;x
resolveNode() vs resolveNodes()
Both functions accept a SOM expression argument and search from the context of the node where the call originates resolveNode() expects to return a single node and returns either a node
or null
resolveNodes() expects to return multiple nodes and returns a nodelist
SOM expressions that include either "[*]" notation or a predicate expression will return a list Calling resolveNode() with an expression that returns a list will cause a runtime error
Seldom (if ever) need to construct a SOM expression var numberOfTitles = 0; numberOfTitles = ACR.details.WBR.instanceManager.count; for(x=0;x
Preferred: var titles = this.resolveNodes ("WBR[*].f1b"); for (var i = 0; i < titles.length; i++) { var vTitleValue = titles.item(i).rawValue; . . . }
prePrint validation
367 lines of script to validate the form contents
if(Work_Being_Registered_Type.f1a.rawValue=="" || Work_Being_Registered_Type.f1a.rawValue==null) { vRequiredFieldsNotFilledFlag = true; errorMessages+="\r1a. - You must select the Type of Work..."; formTools.markFieldRequired(Work_Being_Registered_Type.f1a); } else { formTools.markFieldNotRequired(Work_Being_Registered_Type.f1a); }
Many blocks of code similar to this – can be wholly eliminated if using mandatory field processing
prePrint validation
Need to push the validations out to the individual fields for encapsulated design
Too much script
Form currently has over 1200 total lines of script In 9.1 the same functionality can be implemented in less than half the amount of script – and with a better user experience