9 Replies Latest reply on Aug 4, 2010 2:58 AM by Kasyan Servetsky

    How to expand all nodes in TreeView?

    Kasyan Servetsky Level 5

      Hi all,

       

       

      I wrote a script that recreates XML structure of the active document in the dialog box, so that user could choose an XML element in TreeView. Then script creates index and adds topics from XML elements with the same name and at the same nesting level as the selected element.

      I wrote a recursive function -- ExpandNodes -- to expand all nodes.

       

      My problem is that the code works as expected on Windows,

      Windows.png

      but on Mac the nodes remain not expanded.

      Mac.png

       

      Here is the related code:

       

      #target indesign
      #includepath "/C/Program Files/Adobe/Adobe InDesign CS3/Scripts/Xml Rules/;/Applications/Adobe InDesign CS3/Scripts/Xml Rules/"
      #include "glue code.jsx"
      
      if (app.documents.length == 0) ErrorExit("Please open a document and try again.");
      var gDoc = app.activeDocument;
      var gScriptName = "Index from XML";
      var gCounter = 0;
      var gXmlPath, gSelectedElementName;
      
      var win = new Window("dialog", gScriptName);
      
      var panel = win.add("panel", undefined, "Select XML Element");
      panel.alignment = ["fill", "fill"];
      panel.alignChildren = ["fill", "fill"];
      
      var treeview = panel.add("treeview");
      treeview.preferredSize = [300, 200];
      
      var rootXmlElement = gDoc.xmlElements[0];
      var rootNode = treeview.add("node", rootXmlElement.markupTag.name);
      
      AddItems(rootNode, rootXmlElement);
      
      ExpandNodes(rootNode);
      rootNode.expanded = true;
      
      var okCancelGroup = win.add("group");
      okCancelGroup.orientation = "row";
      okCancelGroup.alignment = "center";
      
      var okBtn = okCancelGroup.add("button", undefined, "Ok", {name:"ok"});
      okBtn.onClick = function() {
           if (treeview.selection == null) {
                alert("Please select an XML element.", gScriptName, true);
                return;
           }
           win.close(1);
      }
      
      var cancelBtn = okCancelGroup.add("button", undefined, "Cancel", {name:"cancel"});
      cancelBtn.onClick = function() {
           win.close(2);
      }
      
      var showWindow = win.show();
           
      if (showWindow == 1) {
           var selection = treeview.selection;
           gSelectedElementName = selection.text;
           var xmlPathArr = [];
           
           while (selection.constructor.name != "TreeView") {
                xmlPathArr.push(selection.text);
                selection = selection.parent;
           }
      
           xmlPathArr.reverse()
           gXmlPath = "/" + xmlPathArr.join("/");
           
           $.writeln(gXmlPath);
      }
      
      //------------------------------------------ FUNCTIONS -------------------------------------------------
      function AddItems(node, theXmlElement) {
           var xmlElement, newNode;
           for (var j = 0; j < theXmlElement.xmlElements.length; j++) {
                xmlElement = theXmlElement.xmlElements[j];
                
                if (xmlElement.xmlElements.length == 0) {
                     node.add("item", xmlElement.markupTag.name);
                }
                else {
                     newNode = node.add("node", xmlElement.markupTag.name);
                     AddItems(newNode, xmlElement);
                }
           }
      }
      //--------------------------------------------------------------------------------------------------------------
      function ErrorExit(myMessage, myIcon) {
           alert(myMessage, gScriptName, myIcon);
           exit();
      }
      //--------------------------------------------------------------------------------------------------------------
      function ExpandNodes(node) {
           var theNode;
           for (var n = 0; n < node.items.length; n++) {
                $.writeln("n = " + n);
                theNode = node.items[n];
                
                if (theNode.items == undefined) {
                     theNode.expanded = true;
                }
                else {
                     theNode.expanded = true;
                     ExpandNodes(theNode);
                }
           }
      }
      //--------------------------------------------------------------------------------------------------------------
      

       

       

      Questions:

      Why the same code works differently on different platforms?

      Is there a more elegant way to expand all nodes?

       

      Thanks in advance.

      Kasyan

        • 1. Re: How to expand all nodes in TreeView?
          Peter Kahrel Adobe Community Professional & MVP


          > Why the same code works differently on different platforms?

           

          That JS scripts behave differently on the two platforms is a source of great frustration. Please report it as a bug.

           

          > Is there a more elegant way to expand all nodes?

           

          In the absence of a method like expandAll(), no, there probably isn't a more elegant way.

           

          Peter

          1 person found this helpful
          • 2. Re: How to expand all nodes in TreeView?
            Kasyan Servetsky Level 5

            Thanks for the quick reply, Peter.

             

            Kasyan

            • 3. Re: How to expand all nodes in TreeView?
              [Jongware] Most Valuable Participant

              A manual fix: hold Alt and open a node

              • 4. Re: How to expand all nodes in TreeView?
                Peter Kahrel Adobe Community Professional & MVP

                I tried that but it doesn't work (using CS5 and Win 7).

                • 5. Re: How to expand all nodes in TreeView?
                  [Jongware] Most Valuable Participant

                  It does on CS4 & Mac

                  Must be a 'native interface' thingy -- I tried it because it works like this in every Mac proggie with a tree view.

                   

                  Hey, since you are on Windows 7: what's the issue with the underlined characters in dialogs that no longer are showing? I wrote a simple dialog to quickly select common text attributes, and took great care in adding ampersands to dialog shortcut keys so I could call up the dialog and hit the correct key blindly. The keys still work under Win 7 but the underlinings don't show anymore!

                  • 6. Re: How to expand all nodes in TreeView?
                    Peter Kahrel Adobe Community Professional & MVP

                    I just tried in CS3, 4, and 5, running from the ESTK and from the Scripts panel, using all possible combinations of keys (Alt+Click, Ctrl+Click, Alt+Ctrl+click, add the Shift key, too), and it doesn't work.

                     

                    As to underline, that works fine for me in CS5/Win 7, though here, too, ESTK and Script panel differ: when run from the ESTK, you don't see the underline in buttons, when run from the Script panel, you do. An & in statictext always shows. Ah, but I notice just now that when you target the ESTK instead of InDesign, the underline does show.

                     

                    Peter

                    • 7. Re: How to expand all nodes in TreeView?
                      Kasyan Servetsky Level 5

                       

                       

                       

                      Thanks to Peter and Jongware for responding to my question.

                      So far, as a very clumsy workaround, I came to the following solution:

                       

                      if (File.fs == "Windows") ExpandNodes(rootNode);

                      rootNode.expanded = true;

                       

                      if (File.fs == "Macintosh") {

                            try {

                                  rootNode.items[0].expanded = true;

                                  rootNode.items[0].items[0].expanded = true;

                                  rootNode.items[0].items[1].expanded = true;

                                 

                            }

                            catch(e) {}

                      }

                       

                      If the script is run on Mac — try to open the first few nodes.

                      When (if) I have time, I'll explore on this further.

                       

                      Kasyan

                      • 8. Re: How to expand all nodes in TreeView?
                        Peter Kahrel Adobe Community Professional & MVP

                        There are some other problems with expanding. You can define an event handler to expand a node. But (on Windows) after expanding a node you then collapse all its children manually, the event handler doesn't work any longer. You get it to work by first collapsing each subnode before expanding it. Naturally, if you want the handler to collapse a node, you need to tell the handler what state it is in when it begins. Which leads to the counter-intuitive handler below.

                         

                         

                         

                         

                         

                         var w = new Window ("dialog");
                            var myTree = w.add ("treeview", [0, 0, 150, 250]);
                                var mammals = myTree.add ("node", "Mammals");
                                    mammals.cats = mammals.add ("node", "cats");
                                        mammals.cats.add ("item", "tabbies");
                                        mammals.cats.add ("item", "tiggers");
                                    mammals.dogs = mammals.add ("node", "dogs");
                                        mammals.dogs.add ("item", "terrier");
                                        mammals.dogs.collies = mammals.dogs.add ("node", "colly");
                                        mammals.dogs.collies.add ("item", "border");
                                        mammals.dogs.collies.add ("item", "highland");
                                        mammals.dogs.add ("item", "labrador");
                                    mammals.add ("item", "three");
                                var insects = myTree.add ("node", "Insects");
                                    insects.add ("item", "ants");
                                    insects.add ("item", "bees");
                                    insects.add ("item", "spiders");
                        
                                myTree.addEventListener("click", double_click);
                                
                            function double_click (clk)
                                {
                                if(clk.detail ==  2)  // if double-click
                                    expand_all (this.selection, this.selection.expanded);
                                }
                        
                            function expand_all (node, exp)
                                {
                                if (node.type == "node")
                                    {
                                    // This double-whammey  is necessary to make sure that on a second double-click,
                                    // after manually collapsing the selected node, the node is expanded properly
                                    node.expanded = false;
                                    // next line does not execute when we’re collapsing a branch
                                    if (!exp) node.expanded = true;
                                    var kids = node.items;
                                    for (var i = 0; i < kids.length; i++)
                                        if (kids[i].type == "node")
                                            expand_all (kids[i], exp)
                                    }
                                }
                        
                        w.show ();  
                        • 9. Re: How to expand all nodes in TreeView?
                          Kasyan Servetsky Level 5

                           

                          Thank you, Peter.

                          I used your expand_all function and now it works for me — all nodes are expanded on both platforms. The only difference I noticed between Mac and Windows so far is:

                          • Mac -- the dialog shows the top part of the XML structure (as intended)
                          • Windows -- it goes down to the bottom, for some reason

                           

                          But this is a minor issue.

                           

                          Kasyan

                           

                          P.S. Here is my revised code:

                          #target indesign
                          #includepath "/C/Program Files/Adobe/Adobe InDesign CS3/Scripts/Xml Rules/;/Applications/Adobe InDesign CS3/Scripts/Xml Rules/"
                          #include "glue code.jsx"
                          
                          if (app.documents.length == 0) ErrorExit("Please open a document and try again.");
                          var gDoc = app.activeDocument;
                          var gScriptName = "Index from XML";
                          var gCounter = 0;
                          var gXmlPath, gSelectedElementName;
                          
                          var win = new Window("dialog", gScriptName);
                          
                          var panel = win.add("panel", undefined, "Select XML Element");
                          panel.alignment = ["fill", "fill"];
                          panel.alignChildren = ["fill", "fill"];
                          
                          var treeview = panel.add("treeview");
                          treeview.preferredSize = [300, 200];
                          
                          var rootXmlElement = gDoc.xmlElements[0];
                          var rootNode = treeview.add("node", rootXmlElement.markupTag.name);
                          
                          AddItems(rootNode, rootXmlElement);
                          
                          expand_all(rootNode, rootNode.expanded);
                          
                          // Ok & Cancel buttons
                          var okCancelGroup = win.add("group");
                          okCancelGroup.orientation = "row";
                          okCancelGroup.alignment = "center";
                          
                          var okBtn = okCancelGroup.add("button", undefined, "Ok", {name:"ok"});
                          okBtn.onClick = function() {
                               if (treeview.selection == null) {
                                    alert("Please select an XML element.", gScriptName, true);
                                    return;
                               }
                               win.close(1);
                          }
                          
                          var cancelBtn = okCancelGroup.add("button", undefined, "Cancel", {name:"cancel"});
                          cancelBtn.onClick = function() {
                               win.close(2);
                          }
                          
                          var showWindow = win.show();
                               
                          if (showWindow == 1) {
                               var selection = treeview.selection;
                               gSelectedElementName = selection.text;
                               var xmlPathArr = [];
                               
                               while (selection.constructor.name != "TreeView") {
                                    xmlPathArr.push(selection.text);
                                    selection = selection.parent;
                               }
                          
                               xmlPathArr.reverse()
                               gXmlPath = "/" + xmlPathArr.join("/");
                               
                               $.writeln(gXmlPath);
                          }
                          
                          //------------------------------------------ FUNCTIONS -------------------------------------------------
                          function AddItems(node, theXmlElement) {
                               var xmlElement, newNode;
                               for (var j = 0; j < theXmlElement.xmlElements.length; j++) {
                                    xmlElement = theXmlElement.xmlElements[j];
                                    
                                    if (xmlElement.xmlElements.length == 0) {
                                         node.add("item", xmlElement.markupTag.name);
                                    }
                                    else {
                                         newNode = node.add("node", xmlElement.markupTag.name);
                                         AddItems(newNode, xmlElement);
                                    }
                               }
                          }
                          //--------------------------------------------------------------------------------------------------------------
                          function ErrorExit(myMessage, myIcon) {
                               alert(myMessage, gScriptName, myIcon);
                               exit();
                          }
                          //--------------------------------------------------------------------------------------------------------------
                          function expand_all (node, exp)
                               {
                               if (node.type == "node")
                                    {
                                    // This double-whammey  is necessary to make sure that on a second double-click,
                                    // after manually collapsing the selected node, the node is expanded properly
                                    node.expanded = false;
                                    // next line does not execute when we’re collapsing a branch
                                    if (!exp) node.expanded = true;
                                    var kids = node.items;
                                    for (var i = 0; i < kids.length; i++)
                                         if (kids[i].type == "node")
                                              expand_all (kids[i], exp)
                                    }
                               }