15 Replies Latest reply on Mar 24, 2009 2:26 PM by Harbs.

    (JS) Find Page of Object

    Level 1
      While preparing a presentation I'm going to be giving in a couple of months, I took a good hard look at my findPage(theObj) function and I think that this is as good as it gets:
      function findPage(theObj) {
      
        if (theObj.hasOwnProperty("baseline")) {
          theObj = theObj.parentTextFrames[0];
        }
      while (theObj != null && theObj.constructor != Page) {
          var whatIsIt = theObj.constructor;
          switch (whatIsIt) {
            case null : return null;
            case Character : theObj = theObj.parentTextFrames[0]; break;
            case Cell : theObj = theObj.insertionPoints[0].parentTextFrames[0]; break;
            case Application : return null;
          }
          if (theObj == null) return null;
          theObj = theObj.parent;
        }
        return theObj
      } // end findPage
      The previous versions posted in various threads here reflected various degrees of needless caution about what might happen, for example if the object were anchored to text in a cell in an overset table. The above returns null in that case with no need for try/catch.

      Notice the use of objects rather than their names. Works! This is similar to the instanceof construction but it's easier to test the negative.

      If anyone can knock a hole in the above script, I'd be very interested in hearing about it.

      Dave
        • 1. Re: (JS) Find Page of Object
          Level 1
          I think I've already knocked a hole in it -- nothing like exposing stuff to public view for finding problems! With the test in the while statement for null, the null case is not possible in the switch.

          Indeed, the only time that null test at the top of the loop kicks in is if the original object is overset text because of the test for null after the switch -- necessary because null doesn't have a parent.

          Dave
          • 2. Re: (JS) Find Page of Object
            Level 1
            Hi Dave,

            Objects on the pasteboard return Spread--or, at least, they used to. If your intent was to have this handled by Application, then never mind.:-)

            Thanks,

            Ole
            • 3. Re: (JS) Find Page of Object
              Level 1
              Ole,

              For this script, yes. If an object is on the pasteboard then it's not on a page.

              Dave
              • 4. Re: (JS) Find Page of Object
                Level 1
                I think I see why I used to include the case of Story (which returned null). If the object is a table that is overset, then its parent is the story. That winds its way up through Document and Application to get to the correct null result, so I think I'll leave it like that.

                Dave
                • 5. Re: (JS) Find Page of Object
                  Harbs. Level 6
                  > If anyone can knock a hole in the above script, I'd be very interested in hearing about it.
                  >

                  What a fun challenge! ;)

                  Besides the unnecessary case (which you mentioned already):

                  1) AFAIK, every object has a valid parent, even the app itself has
                  itself as a parent -- itself. There's no way to get through the loop a
                  second time with "null".

                  I would do a while(theObj) without any conditions because once you made
                  it in, you can't get out without either returning null or getting your
                  page. I'd just add a case of Page and return theObj and at the end of
                  the function return null

                  2) Also, "if (theObj == null)" is probably not technically correct. "if
                  (theObj == undefined)" is more accurate (since the only way to get there
                  is with an undefined text frame). (Although I'd just use if(!theObj) for
                  the sake of brevity...)

                  3) It does not deal with references to Footnotes (although it will work
                  if given a reference to the text inside a footnote).

                  4) Your function does not deal with notes. It will not find the page a
                  note is on, and will error if given a reference to text inside a note.

                  5) You can make the function infinitely more useful by adding a second
                  argument which could accept any InDesign object which can contain
                  objects (like Spread, MasterSpread, TextFrame, etc.) I usually want to
                  find the location of the last text frame on overset text, so I prefer to
                  use (a variation of) jxswm's version of the function (which finds the
                  last text frame).


                  --
                  Harbs
                  http://www.in-tools.com
                  • 6. Re: (JS) Find Page of Object
                    Level 1
                    Thanks Harbs, interesting points.

                    1. I've resisted the use of while(theObj) because it just feels unnatural from a readability point of view. It might be worth setting up a timing test to compare the speed of it with while(theObj != null).

                    Your idea of moving the catch for Page into the switch is interesting. That would actually make it impossible to drop out the bottom of the while loop.

                    2. A test for null catches undefined values. I've always used that test, so I'm going to stay with it. Again, the form if(!theObj) strikes me as something I'd have to pause and think about for a moment each time I read it, so I tend not to use that construction.

                    3 & 4. Aha, I never thought about footnote references and notes. They hardly ever come up in my scripts so I hadn't had the need to think about them.

                    5. "infinitely"?

                    At one point, my version of this function did indeed return the last text frame of a story if the object were in overset text, but I ended up realizing that this was rarely useful and indeed misleading. But it is an option that is occasionally needed.

                    Thanks for the feedback.

                    Dave
                    • 7. Re: (JS) Find Page of Object
                      Harbs. Level 6
                      Dave_Saunders@adobeforums.com wrote:
                      > Thanks Harbs, interesting points.
                      >
                      > 1. I've resisted the use of while(theObj) because it just feels unnatural from a readability point of view. It might be worth setting up a timing test to compare the speed of it with while(theObj != null).
                      >
                      >

                      I find (theObj) more readable, but that's probably because I have a
                      funny way of thinking, and don't like reading anything extra... ;)

                      I remember the first time I saw Kris use "0" instead of false and "1"
                      instead of true, it looked so odd to me, but I've gotten so used to the
                      short-hand way of writing everything that the long-hand way looks clumsy!

                      My point here was that "theObj.constructor != Page" was not necessary.
                      > Your idea of moving the catch for Page into the switch is interesting. That would actually make it impossible to drop out the bottom of the while loop.
                      >
                      >

                      Exactly. Here's (approximately) what I meant: (It should work in CS3 and
                      later -- in CS2 and earlier, storyOffset was a number and not a
                      character) Also, Notes can have a lot of nesting, and this will not
                      catch that...

                      function FindWhere(theObj,where) {
                      var err;
                      if(where==undefined){where=Page}
                      if (theObj.hasOwnProperty("baseline")) {
                      try{theObj = theObj.parentTextFrames[0];}
                      catch(err){}
                      }
                      while (theObj != undefined) {
                      var whatIsIt = theObj.constructor;
                      switch (whatIsIt) {
                      case where : return theObj;
                      case Note:
                      case Footnote: theObj = theObj.storyOffset;break;
                      case Character : theObj = theObj.parentTextFrames[0]; break;
                      case Cell : theObj =
                      theObj.insertionPoints[0].parentTextFrames[0]; break;
                      case Application : return null;
                      }
                      if (theObj == undefined) return null;
                      theObj = theObj.parent;
                      }
                      return null;
                      }

                      > 2. A test for null catches undefined values. I've always used that test, so I'm going to stay with it. Again, the form if(!theObj) strikes me as something I'd have to pause and think about for a moment each time I read it, so I tend not to use that construction.
                      >
                      >

                      Yes, I know "==null" works. My point was that if you want the
                      readability factor, "==undefined" is more correct -- the text frame is
                      undefined and not null. To illustrate this point theObj === undefined
                      will return true, while theObj===null returns false.
                      > 3 & 4. Aha, I never thought about footnote references and notes. They hardly ever come up in my scripts so I hadn't had the need to think about them.
                      >
                      > 5. "infinitely"?
                      >
                      >

                      Okay. "Infinitely" might be a bit of an exaggeration, but I do use
                      "FindWhere" on a lot of different levels. For example, it's very useful
                      for finding if an object is on a MasterSpread.

                      > At one point, my version of this function did indeed return the last text frame of a story if the object were in overset text, but I ended up realizing that this was rarely useful and indeed misleading. But it is an option that is occasionally needed.
                      >
                      >

                      I find it very useful indeed. I have a separate function to verify
                      oversets if necessary.
                      > Thanks for the feedback.
                      >
                      > Dave
                      >

                      --
                      Harbs
                      http://www.in-tools.com
                      • 8. Re: (JS) Find Page of Object
                        Level 1
                        So there I am in Sydney with this function up on the screen and it hits me that it fails to check for the possibility that the object whose page is being sought is overset text.

                        "As good as it gets" my foot! (Being polite for a change.)

                        Dave
                        • 9. Re: (JS) Find Page of Object
                          Harbs. Level 6
                          Well, it depends whether you want the page of the last text frame or
                          not. This is what I usually want, but I assumed you had wanted to return
                          null for overset text (as it doesn't have a page). I seem to recall
                          discussing this point...

                          --
                          Harbs
                          http://www.in-tools.com
                          • 10. Re: (JS) Find Page of Object
                            Level 1
                            The second line of code of the function is the problem. In fact, I wonder if I need that initial if statement at all. But the case Character line has the same problem. It must be protected by a try/catch otherwise it will fail if the text has no parentTextFrames.

                            Dave
                            • 11. Re: (JS) Find Page of Object
                              Level 1
                              Hmm. Maybe I should go back to the drawing board because I discussed this in the topic.

                              Dave
                              • 12. Re: (JS) Find Page of Object
                                Harbs. Level 6
                                No, it won't fail. If the text is overset, the parentTextFrames[0] is
                                undefined. It will not fail. I was rather surprised myself when I first
                                noticed this, but it's very handy...

                                --
                                Harbs
                                http://www.in-tools.com
                                • 13. Re: (JS) Find Page of Object
                                  Level 1
                                  OK, here's why it works:

                                  array = new Array()
                                  array[0] === undefined;

                                  this results in true.

                                  And, as we all know:

                                  undefined == null!

                                  Dave
                                  • 14. Re: (JS) Find Page of Object
                                    Harbs. Level 6
                                    Ah. I didn't realize it was an array. I thought parentTextFrames was a
                                    collection...

                                    Yes. With Arrays it makes a lot of sense...

                                    Thanks.

                                    --
                                    Harbs
                                    http://www.in-tools.com
                                    • 15. Re: (JS) Find Page of Object
                                      Harbs. Level 6
                                      Now that I think about it, it really couldn't have been a collection...

                                      --
                                      Harbs
                                      http://www.in-tools.com