Expand my Community achievements bar.

Can you define an event programmatically?

Avatar

Level 2

Does anyone know how to define an event programmatically for a form object using JavaScript? My example is this:

I am passing form fields to a validation function in a JavaScript object by calling scriptObj.addToValidation(this); from the field initialize event.

The field object is added to a JavaScript array so I can check for null values of potentially hundreds of fields with one block of code. What I also want to do is define the click and enter events for each object programmatically from the addToValidation(obj) function while iterating through the array. This way I wont need to add code in each field in the design view, my goal is to take as much code out of the form fields as possible and put it into a script object using an object-oriented approach.

A path I was looking down was trying to access the event by: fieldObject[i].event__change = ... If you print the event__change or event__enter to the javascript console you can see it is an XFAObject but I cant find any doco about these objects and dont know if Im on the right track.

Hopefully this makes sense, please talk to me LC gurus!!

12 Replies

Avatar

Level 10

Hi,

Not sure exactly what you are trying to achieve. LC Designer ES2 provides better in-built ways of dealing with validation. The latest version allows you to group validation in the File > Form Properties > Validation tab. You would still need to define what input is valid in each object.

However it looks like you want to pass the name of the object through to your function. You can declare a variable and then pass this (fieldObj) through:

var fieldObj = this.somExpression;

However in the function you would need to resolve the node before adding it to the array:

var fieldObj = xfa.resolveNode(fieldObj);

Hope that helps (???)

Niall

Avatar

Level 2

Hi Niall,

Thanks for having a look at my post. Yes LC has some good validation built-in but what I'm doing goes much further than the standard functionality provided. Another example of what Im doing:

I am passing a reference to the object itself, not just its som expression. This way I can access all its properties programmatically. When an object is added to the mandatory field array I can add an asterisk ( * ) to the end of the field caption. When the user hits the submit button, any mandatory fields that were missed are listed in a list box at the end of the form with specific validation messages. The user can then select a field from the list and the focus is set to the field.

All this and more is up and running now. My goal is for other forms developers to be able to drag fragments from a shared library onto the page, add 1 function call to the initialize event and have all this functionality working black-box style. The only part left is to define other events for the field objects programmatically through the script object so you dont need to add other function calls to other events of the object. It would make dev faster, much more consistent, easier for less experienced developers and much more maintainable for large forms.

Avatar

Former Community Member

I'm struggling on the same topic. I want the audience to be able to navigate a 50x50 field matrix using the arrow keys. There's no way I'm implementing function calls in 2500 fields.

I thought I might take advantage of LC Designer 9's Event Propagation, although it seems this function has been removed from LC Designer 9.0.0.2. At least the checkbox won't turn up in the script editor. Any insights?

I've browsed through Adobe's JS docs and it seems there are functions for hooking up action triggers to plug-in (media player) events, although not to fields.

Avatar

Level 4

Manually placing 2500 fields must be a pain in the butt as well.  I have a suggestion that will make things easier.  Create one field with all the code you need for navigating.  Then place this field in repeatable subforms in such a way that the 50x50 array is automatically built.  The code would of course have to be created in a generic way so that it used the parent subform indexes to automatically detect it's location in the array and do the appropiate thing.

Thom Parker
The source for PDF Scripting Info
pdfscripting.com

The Acrobat JavaScript Reference, Use it Early and Often
http://www.adobe.com/devnet/acrobat/javascript.html

Then most important JavaScript Development tool in Acrobat
The Console Window (Video tutorial)
The Console Window(article)

Avatar

Level 4

Unfortunately the XFA event structure is mostly fixed.  Events can't be added at runtime like it's done in many other JavaScript models.  That's not to say that you can't dynamically create the event structure in the Form model using the XFA node operations. You can.  It's just that the model won't respond to it.

The proper way to do things is to in XFA is to setup all the structures in designer.  If you need multiple repeated structures then you setup repeated subforms.  This model is not designed for created new things at runtime.  Instead you need to think of it as creating a library of the stuff in the form template that you'll need at runtime.

Now, that's runtime, designer is a different story.  You can create add-ins to designer that will dynamically build structures into the form, which is what I think you're looking for.  Designer has a flash interface and Adobe provides an SDK for adding your own tools.  This was tenetivly introduced earlier this year. I don't have a link right now, but I think Mike Potter was the Adobe guy who wrote about it.

Thom Parker
The source for PDF Scripting Info
pdfscripting.com

The Acrobat JavaScript Reference, Use it Early and Often
http://www.adobe.com/devnet/acrobat/javascript.html

Then most important JavaScript Development tool in Acrobat
The Console Window (Video tutorial)
The Console Window(article)

Avatar

Former Community Member

Hi Thom,

Thanks for your insights. Adding 2500 scripts through field duplication would be a solution, in which each field call a generic function according to:

scriptObject.DoStuff(this, xfa.event);

It's doable, although it's against my religion. :>

I found out I can still propagate events down the object chain (or "up" according to Adobe's documention, a metaphor I find counter-intuitive) by manually adding the tag

listen="refAndDescendents"

to an event tag of the parent subform. To my relief, even though subforms don't listen to Change activities, the event does get propagated to children who do.

On add-ins to Designer - are you referring to the experimental macro feature introduced in ES2?

http://blogs.adobe.com/formfeed/2010/01/designer_es2_macros.html

Avatar

Level 4

The "listen" property is a good find.  I didn't know that one. Seems like it could be a solution.   And yes, I did mean the ES2 Macros.  Seems that if you need to add a feature to a lot of fields at once, then this would be a good way to do it.

Thom Parker
The source for PDF Scripting Info
pdfscripting.com

The Acrobat JavaScript Reference, Use it Early and Often
http://www.adobe.com/devnet/acrobat/javascript.html

Then most important JavaScript Development tool in Acrobat
The Console Window (Video tutorial)
The Console Window(article)

Avatar

Level 2

You can read a little more about the listen property here:

http://help.adobe.com/en_US/livecycle/9.0/designerHelp/index.htm?content=001150.html

That is a nice find, should come in handy!

Avatar

Level 10

Based on an older post by John Brinkman in his Formfeed blog, I can say, you can use a script in the initialize:event of subform to add scripts to any event to all form fields in one go.

Just add a blank subform to your form, and put this script into its initialize:event.

Save your form, close it and then reopen it in Designer.

Designer will execute the script and modify the template DOM.

You will recognize, that the subform has gone and all form fields have a script in their click:event.

In this example a messagebox appears which shows the SOM Expression of the current field.

// Design-time script to modify the click events

if (true)

{

try

{

var nCount = updateScripts(xfa.template);

xfa.log.message(0, "Updated " + nCount + " scripts");

// remove this script once completed

var vTemplateThis = xfa.template.resolveNode("$.." + this.name);

vTemplateThis.parent.nodes.remove(vTemplateThis);

} catch (err)

{

scMessage.handleError(err);

}

}

function updateScripts(vNode)

{

var nCount = 0;

if (!vNode.isContainer)

return 0;

if (vNode.className == "field")

{

// Don't touch buttons

if (vNode.ui.oneOfChild.className != "button" && vNode.ui.oneOfChild.className != "checkButton")

{

// add click event and its script

if (vNode.nodes.namedItem("event__click") == null)

{

var vScript = xfa.template.createNode("script");

vScript.contentType="application/x-javascript";

// add a script to click:event

vScript.value = "xfa.host.messageBox(this.somExpression, \"SOM Expression\", 3, 0);";

var vEvent = xfa.template.createNode("event", "event__click");

vEvent.activity = "click";

vEvent.nodes.append(vScript);

vNode.nodes.append(vEvent);

}

return 1;

}

} else

{

// iterate over all child nodes.

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

{

nCount += updateScripts(vNode.nodes.item(i));

}

}

return nCount;

}

Avatar

Level 4

Very good stuff!!  Do you know if this only works on initialization.  I wrote similar code for modifying the template at runtime and it threw a security exception.  But I was able to add event nodes with exactly the same code to the form model, not that it did any good.  I could see the newly added event in the form model, but it did nothing.

Avatar

Level 10

Hi Thom,

John Brinkman described it detailed in this blog post.

http://blogs.adobe.com/formfeed/2009/05/template_transformation.html

In the paragraph "Scripting the Template" he says, you cannot modify the template DOM in Reader during runtime (a security restriction) but in Designer during design time.

But I think the method is still very useful when designing large forms especially for older target version (8.x), where you have to add own validation scripts manually to the fields for example.

Avatar

Level 8

I have same requirements. I have added a reply here:

Re: Create and Attach Event to Button via JavaScript

I appreciate your help.

Tarek