9 Replies Latest reply on Jan 18, 2010 11:28 PM by Harbs.

    [CS4, JS] Adding ".parent" with a while loop

    Murral

      Hello,

       

      I'm trying to find out the page side of a text frame, however the text frame may be grouped. I am currently using a few if and else if statements to get to the text frame's page parent - each statement adds another ".parent", e.g.

       

      myTextFrame = app.activeDocument.stories[i].paragraphs[j].parentTextFrames[0]

      if (myTextFrame.parent.constructor.name == "Page")

          mySide = myTextFrame.parent.side

      else if (myTextFrame.parent.parent.constructor.name == "Page")

          mySide = myTextFrame.parent.parent.side

      etc.

       

      Is there a more elegant way to do this? I tried to construct a while loop, e.g.


      while (myTextFrame.constructor.name !== "Page")

      myTextFrame = myTextFrame + ".parent"


      But as I quickly found out, that concatenation won't work (I've only been using JS for about 2 months...I know, it's no excuse)!

      Is there a way to do that loop correctly, i.e. add ".parent" to the myTextFrame variable until myTextFrame.constructor.name == "Page"?

       

      Thanks in advance for any help :-)

        • 1. Re: [CS4, JS] Adding ".parent" with a while loop
          [Jongware] Most Valuable Participant

          while (myTextFrame.constructor.name != "Page")

            myTextFrame = myTextFrame.parent;

           

          (also note: != instead of !==)

           

          If the frame is on the pasteboard, its parent will be "Spread", and if the frame is on the pasteboard of a master page, it'll be "MasterSpread".

          You might want to check for these cases as well to exit gracefully:

           

           

          while (myTextFrame.constructor.name != "Page")

          {

            if (myTextFrame.constructor.name == "Spread" ||

              myTextFrame.constructor.name == "MasterSpread")

            {

               alert ("Exit with grace.");

              exit(0);

            }

            myTextFrame = myTextFrame.parent;

          }

           

           

          Checked with this mini-script; select something with the pointer and run it to see what its parent looks like:

           

          alert (app.selection[0].constructor.name+"\n"+app.selection[0].parent.constructor.name);

          • 2. Re: [CS4, JS] Adding ".parent" with a while loop
            Marc Autret Level 4

            Here is a generic OOP approach:

             

            TextFrame.prototype.getPage = function()
            // -----------------------------------------------
            // Returns the containing Page of this TextFrame
            {
            var p = this.parent,
                 pc;
            while( pc=p.constructor )
                 {
                 if( pc == Page )
                      return p;
                 if( pc == Spread || pc == MasterSpread )
                      throw Error("The textframe is placed on a spread!");
                 if( 'parentTextFrames' in p && !(p=p.parentTextFrames[0]) )
                      throw Error("The textframe's container overflows!");
                 p=p.parent;
                 }
            }
            
            // Sample code (assuming a text frame is selected)
            // -----------------------------------------------
            var tf = app.selection[0],
                 pg;
                 
            try {
                 pg = tf.getPage();
                 alert( "Page: " + pg.name + " Side: " + pg.side);
                 }
            catch(e)
                 {
                 alert( e );
                 }
            
            

             

            @+

            Marc

            • 3. Re: [CS4, JS] Adding ".parent" with a while loop
              Marc Autret Level 4

              However, the code above does not answer to the 'Group problem'.

               

              If the target text frame is embedded within a Group, the getPage() method will return the containing Page of the group itself (i.e. the containing page of the center point of the group). In this case, how to get the page wich apparently owns the text frame subobject? Interesting challenge...

               

              @+

              Marc

              • 4. Re: [CS4, JS] Adding ".parent" with a while loop
                Harbs. Level 6

                Marc Autret wrote:

                 

                Interesting challenge...


                Yes, it is...

                 

                I think the only way to take care of that, would be to compare the bounds of the text frame with that of the resulting page...

                 

                Harbs

                • 5. Re: [CS4, JS] Adding ".parent" with a while loop
                  Marc Autret Level 4

                  Harbs. wrote:

                   

                  I think the only way to take care of that, would be to compare the bounds of the text frame with that of the resulting page...

                   

                  You're right! So we need a subroutine in the getPage method. If the resulting page doesn't contain this (comparing page.bounds and this.visibleBounds), then we request the page.parent spread and we loop in spread.pages to find the page wich matches this. Not so hard.

                   

                  @+

                  Marc

                  • 6. Re: [CS4, JS] Adding ".parent" with a while loop
                    Marc Autret Level 4

                    Now the code:

                     

                    Page.prototype.intersects = function(/*PageItem bounds*/pib)
                    // -----------------------------------------------
                    // Return true if this page intersects the bounds pib
                    {
                    var b = this.bounds;
                    return b[0]<=pib[2] && pib[0]<=b[2] && b[1]<=pib[3] && pib[1]<=b[3];
                    }
                    
                    TextFrame.prototype.getPage = function()
                    // -----------------------------------------------
                    // Returns the containing Page of this TextFrame
                    // [Works also with grouped/embedded frame]
                    {
                    var p = this.parent,
                       b = this.visibleBounds,
                       pc, pgs, i;
                    while( pc=p.constructor )
                       {
                       if( pc == Page )
                          {
                          if( p.intersects(b) ) return p;
                          pgs = p.parent.pages; // spread pages
                          for( i=pgs.length-1 ; i>=0 && p=pgs[i] ; i-- )
                             {
                             if( p.intersects(b) ) return p;
                             }
                          pc = Spread;
                          }
                       if( pc == Spread || pc == MasterSpread )
                          throw Error("The textframe is placed on a spread!");
                       if( 'parentTextFrames' in p && !(p=p.parentTextFrames[0]) )
                          throw Error("The textframe's container overflows!");
                       p=p.parent;
                       }
                    }
                    
                    // Sample code (assuming a text frame is selected)
                    // -----------------------------------------------
                    var tf = app.selection[0],
                       pg;
                       
                    try {
                       pg = tf.getPage();
                       alert( "Page: " + pg.name + " Side: " + pg.side);
                       }
                    catch(e)
                       {
                       alert( e );
                       }
                    

                     

                    @+

                    Marc

                    • 7. Re: [CS4, JS] Adding ".parent" with a while loop
                      John Hawkinson Level 5

                      Hey, Marc, shouldn't the second part of this test:

                       

                      if( 'parentTextFrames' in p && !(p=p.parentTextFrames[0]) )
                      
                      

                       

                      Be "p==" rather than assignment ("p=")? Either that or I guess I'm not sure what the purpose of the assignment is...

                      • 8. Re: [CS4, JS] Adding ".parent" with a while loop
                        Marc Autret Level 4

                        Hi John,

                         

                        I agree the syntax looks weird but we really need that surprising assignment.

                         

                        My code:

                         

                        if( 'parentTextFrames' in p && !(p=p.parentTextFrames[0]) )
                           {
                           /* do something */
                           }
                        

                         

                        is actually a shortcut for:

                         

                        if( 'parentTextFrames' in p )
                           {
                           p = p.parentTextFrames[0];
                           if( !p )
                              {
                              /* do something */
                              }
                           }
                        

                         

                        The interesting fact to notice is that the parentTextFrames property of a Text object returns an empty collection when the text falls out of range within an overflowing frame.

                         

                        @+

                        Marc

                        • 9. Re: [CS4, JS] Adding ".parent" with a while loop
                          Harbs. Level 6

                          The interesting fact to notice is that the parentTextFrames 

                          property of a Text object returns an empty collection when the 

                          text falls out of range within an overflowing frame.

                           

                          No. It's an empty Array. parentTextFrames is an Array -- not a 

                          collection. That's why you can check for parentTextFrames[0] without 

                          getting an error.

                           

                          Harbs