• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Deleting anchored frames

Advocate ,
Feb 07, 2012 Feb 07, 2012

Copy link to clipboard

Copied

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

TOPICS
Scripting

Views

2.5K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Feb 07, 2012 Feb 07, 2012

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 === "AFr

...

Votes

Translate

Translate
Advocate ,
Feb 07, 2012 Feb 07, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 07, 2012 Feb 07, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 07, 2012 Feb 07, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 07, 2012 Feb 07, 2012

Copy link to clipboard

Copied

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.Delete();
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 08, 2012 Feb 08, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 08, 2012 Feb 08, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Feb 08, 2012 Feb 08, 2012

Copy link to clipboard

Copied

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 08, 2012 Feb 08, 2012

Copy link to clipboard

Copied

LATEST

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

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines