Expand my Community achievements bar.

Dive into Adobe Summit 2024! Explore curated list of AEM sessions & labs, register, connect with experts, ask questions, engage, and share insights. Don't miss the excitement.

resolveNodes doesn't find all nodes

Avatar

Level 4

Hi there,

I would like to find all text fields with a specific name in my form (and do things with them...).

Funny thing is: I sometimes get only one hit or no hits at all. I never managed to get the correct whole list of fields. Am I doing something wrong?

My code is (here in the form-ready event):

var arrayFields = xfa.resolveNodes("myField[*]");
if (arrayFields == null) {
    xfa.host.messageBox("nothing found");
}
else {
    xfa.host.messageBox(String("Number of Fields found: " + arrayFields.length));
    for (var iFieldCounter = 0; iFieldCounter < arrayFields.length; iFieldCounter++) {
        xfa.host.messageBox( arrayFields.item(iFieldCounter).somExpression);
    } // for iFieldCounter
} // else some result

PS. I have a little sample form ready. Yet I don't find a way to upload it to the forum.

Uli

6 Replies

Avatar

Level 4

e-mail the form to me and I'll take a look: alex.kloft@gmail.com

Avatar

Level 4

As I cannot mail my form

to everybody who reads this, I sketch my example form. The hierarchy is:

form

     masterpage

          ...

     myPage

          mySubform1

               myField

          mySubform2

               myField

With an expression like

var arrayFields = resolveNodes("xfa.form..myField[*]");

I don't get but the first "myField". Yet I expect to find both "myField" in arrayFields.

Avatar

Former Community Member

The documentation for resolveNodes comes with the following reservation:

Note: The search could return unexpected results if the form contains several objects that use the same
name. It returns the value of the first object that it finds.

As resolveNodes has an issue with returning objects located in subforms below $template.#subform.#subform[*], you're left with traversing the dom tree yourself.

A recursive iteration over Tree.nodes.item(i) is a good place to start.

Avatar

Level 4

Thanks for that information. Saved me from trying things for ever.

I wrote this function "resolveNodesFixed()" instead. Whoever has the same problem in the future may try it this way:

var arrayFields = resolveNodesFixed("myField");
if (arrayFields == null) {
    xfa.host.messageBox("nothing found");
}
else {
    xfa.host.messageBox(String("Number of Fields found: " + arrayFields.length));
    for (var iFieldCounter = 0; iFieldCounter < arrayFields.length; iFieldCounter++) {
        xfa.host.messageBox( arrayFields[iFieldCounter].somExpression);
    } // for iFieldCounter
} // else some result

function resolveNodesFixed(sObjectName) {
    // Finds all objects by the name of sObjectName starting from the top.
    // Parameters:
    //        sObjectName: Name of the searched for object
    // Result:
    //         returns an array of found objects. It may be empty.
    arrayHits = new Array();
    traverseForm(xfa.form, arrayHits, sObjectName);
    return arrayHits;
   
} // function resolveNodesFixed()

function traverseForm(oFormNode, arrayHits, sObjectName) {
    // runs thru all nodes of the form and adds every node with the name "sObjectName" to arrayHits
    // Parameters:
    //        oFormNode:   starting node. From this node downwards this function searches for nodes.
    //        arrayHits:   array to add the found nodes to
    //        sObjectName: Name of the searched for object
    // Result:
    //         returns true if everything is all right
    try {
        //xfa.host.messageBox(oFormNode.somExpression + " - " + oFormNode.nodes.length);
        for (var iIndexChildObject = 0; iIndexChildObject < oFormNode.nodes.length; ++iIndexChildObject) {
            var oChild = oFormNode.nodes.item(iIndexChildObject);
            if (oChild.name == sObjectName) {
                arrayHits.push(oChild);
            }  // if oChild.className == sObjectName
           
            if (oChild.isContainer) {
                // this node appears to be a subform. Recursivly we check this subform's sub nodes.
                traverseForm(oChild, arrayHits, sObjectName); // if the node contains subnodes make a recursive call to the function
            } // if oChild.isContainer
        } // for iIndexChildObject
    } // try
    catch (e) {
      console.println("Error: " + e);
      return false;
    } // catch
    return true;
} // function traverseForm()

Avatar

Former Community Member

Here's a more direct approach (blazingly fast, about 6 ms on my machine, since we're avoiding recursion by using internal methods instead):

function ResolveAll(str) {
var nn = [];
for (var p = 0; p < xfa.layout.pageCount(); p++) {
  var ss = xfa.layout.pageContent(0);
  for (var i = 0; i < ss.length; i++) {
   if (ss.item(i).name == str) nn.push(ss.item(i));
  }
}
return nn;
}
var p = ResolveAll("fieldname");

Keep in mind that it doesn't search items inherited from master pages.

Avatar

Former Community Member

Here's a slightly slower, recursive version (about 30 ms on my machine), operating on xfa.form. Note that it skips exclGroups and area objects.

var getAll = function() {
var needle;
var nn = [];
return {
  token: function(token) {
   needle = token;
   this.traverse(xfa.form);
   return nn;
  },
  traverse: function(haystack) {
   for (var i = 0; i < haystack.nodes.length; i++) {
    var n = haystack.nodes.item(i);
    if (n.name == needle) nn.push(n);
    if (n.className == "subform") {
     this.traverse(n);
    }
   }
  }
}
}();
getAll.token(str).length;