8 Replies Latest reply: Feb 8, 2012 11:30 AM by frameexpert RSS

    Deleting anchored frames

    4everJang Community Member

      Hello all,

       

      What happens with a linked list of objects when I use the Delete method on one of these objects ? The FrameMaker Scripting Guide does not say much about this, nor does the FDK reference guide. I have tried the following but it does not work as I expected:

       

      doc = app.ActiveDoc;

      theGraph = doc.FirstGraphicInDoc;

      n = 0;

       

      while ( theGraph.ObjectValid() ) {

                tobedeleted = false;

                if ( theGraph.constructor.name == "AFrame" ) {

          theObject = theGraph.FirstGraphicInFrame;

          if ( theObject.ObjectValid() )

            if ( theObject.constructor.name == "TextFrame" )

              tobedeleted = true;

          }

          if ( tobedeleted ) {

            nextGraph = theGraph.NextGraphicInDoc;

            theGraph.Delete();

            n++

            theGraph = nextGraph;

          } else

              theGraph = theGraph.NextGraphicInDoc;

      }

      alert ( n );

       

      The document has 18 of the specified anchored frames (with embedded text frames), but the above code only deletes 5. If I just walk through the list and skip deleting the objects, the count goes up to 18, as expected. So there must be some crazy side effect of deleting an object from a linked list. But what exactly ?

       

      How can I walk through a linked list and delete some objects from them without disrupting the linked list ?

       

      Jang

        • 1. Re: Deleting anchored frames
          4everJang Community Member

          This is the only way I could get it to work until now. It is kind of silly to have to restart from the first graphic in the document after having deleted one graphic object from the list, but at least this one works.

           

          doc = app.ActiveDoc;

          n = 0;

          brunning = true;

           

          while ( brunning ) {

                    theGraph = doc.FirstGraphicInDoc;

                    bdeleted = false;

                    while ( theGraph.ObjectValid() && !bdeleted ) {

              if ( theGraph.constructor.name == "AFrame" ) {

                theObject = theGraph.FirstGraphicInFrame;

                if ( theObject.ObjectValid() ) {

                  if ( theObject.constructor.name == "TextFrame" ) {

                    bdeleted = true;

                    theGraph.Delete();

                    n++;

                  }

                }

              }

              theGraph = theGraph.NextGraphicInDoc;

                    } 

                    if ( !bdeleted )

              brunning = false;

          }

          alert ( n );

           

          It seems to me that there should be a more efficient way of doing this, but I have not found it yet. If anyone has good ideas, please post them. And if Adobe techies are monitoring this list: there is an obvious lack of either clarity or support from the available Delete() method here.

           

          Ciao again

           

          Jang

          • 2. Re: Deleting anchored frames
            frameexpert Community Member

            Hi Jang,

             

            You might find this tutorial useful:

             

            http://frameexpert.com/tutorials/loopsandlinkedlists.htm

             

            The code is FrameScript, but the concepts are the same in ExtendScript and the FDK. Please let me know if you have any questions or comments.

             

            Rick

            • 3. Re: Deleting anchored frames
              4everJang Community Member

              Hi Rick,

               

              The method you describe is what I tried to use in ExtendScript, as shown in my first posting, but apparently deleting an object after first saving its forward pointer still invalidates the forward pointer in some mysterious way. My expectation is that ExtendScript is fiddling with pointers to structures in the background, i.e. not copying objects but only the pointers to those objects.

               

              I found something like this when I tried to set a TextRange to contain a frame anchor.

               

              myrange = new Textrange;

              myrange.beg = myrange.end = anchor;

              myrange.beg.offset = 0;

              myrange.end.offset = 1;

               

              Believe it or not, but after these lines, both offsets are 1. So I tried to unlink the beg and end textlocs in my textrange object:

               

              myrange = new Textrange;

              myrange.beg = anchor;

              myrange.end = anchor;

              myrange.beg.offset = 0;

              myrange.end.offset = 1;

               

              Still the same result. The code that does what I expected looks like this:

               

              myrange = new Textrange;

              myrange.beg.obj = anchor.obj;

              myrange.end.obj = anchor.obj;

              myrange.beg.offset = 0;

              myrange.end.offset = 1;

               

              Isn't this total madness ? But it does tell me that some pointer juggling is going on behind the scenes. I will have another go at the linked list member deletion code and post a solution if I can find one.

               

              Ciao

               

              Jang

              • 4. Re: Deleting anchored frames
                frameexpert Community Member

                I'll have to take some time to try your code and try to understand what is going on. In the meantime, another approach is to loop through the anchored frames save the objects that you want to delete in an array. Then, you can loop through the array and delete each object. It may be a bit less efficient, but each loop can be very simple.

                 

                var doc = app.ActiveDoc;
                var graphic = doc.FirstGraphicInDoc;
                var textFrame;
                var toDelete = [ ];

                 

                while(graphic.ObjectValid()) {
                  if (graphic.constructor.name === "AFrame") {
                    textFrame = graphic.FirstGraphicInFrame;
                    if (textFrame.ObjectValid()) {
                      if (textFrame.constructor.name === "TextFrame") {
                        toDelete.push(graphic); // Store the frame in the array.
                      }
                    }
                  }
                  graphic = graphic.NextGraphicInDoc;
                }

                 

                // Loop through the array of anchored frames and delete each one.

                for (var i = 0; i < toDelete.length; i += 1) {
                  toDelete[i].Delete();
                }

                • 5. Re: Deleting anchored frames
                  4everJang Community Member

                  Hi Rick,

                   

                  I had to process another set of anchored frames and could not be certain that I could throw all of them away, so I converted the script to use the second method you indicated: push the objects into a toDelete array and then process that array at the end of the scipt. Very elegant and effective. Thanks.

                   

                  Ciao

                   

                  Jang

                  • 6. Re: Deleting anchored frames
                    frameexpert Community Member

                    Hi Jang,

                     

                    I orginally developed this for deleting certain elements in a structured document, since these are in a tree and not a linked list and this is the only way to do it reliably.

                     

                    Rick

                    • 7. Re: Deleting anchored frames
                      4everJang Community Member

                      Most of the element- and attribute level work in structured Frame I do with the FrameSLT Node Wizard Scripts now. Once you get the XPath expressions down, that is a very powerful tool. It is a little like scripting, but so much easier (because of the much smaller set of options, of course).

                       

                      Ciao

                       

                      Jang

                      • 8. Re: Deleting anchored frames
                        frameexpert Community Member

                        I agree, FrameSLT is excellent. I am sure you have seen my blog post on FrameSLT:

                         

                        http://frameautomation.com/2010/03/15/frameslt-a-great-framemaker-plugin/

                         

                        Rick