12 Replies Latest reply on Nov 5, 2010 7:10 PM by Haakenlid

    Moving threaded text frames CS3 (JS)

    jmw107

      Hi -- I have a script that, among other things, searches via GREP and moves any text frame that has a true result.

       

      The question: Is there anyway to have the script move any text frames that are threaded to that text frame as well?

       

      Thanks in advance

       

      Below is a snippet:

       

      var my_doc = app.activeDocument;

      app.findGrepPreferences = NothingEnum.nothing;

      app.changeGrepPreferences = NothingEnum.nothing;
      app.findChangeGrepOptions.includeFootnotes = false;
      app.findChangeGrepOptions.includeHiddenLayers = false;
      app.findChangeGrepOptions.includeLockedLayersForFind = false;
      app.findChangeGrepOptions.includeLockedStoriesForFind = false;
      app.findChangeGrepOptions.includeMasterPages = false;
      app.findGrepPreferences.findWhat = "This is my text I am searching for";
      var found = my_doc.findGrep();

       

      for (i= my_doc.textFrames.length-1; i >= 0; i--) {
      if (my_doc.textFrames[i].contents !== ""){   
          var myResult = my_doc.textFrames[i].findGrep(true);
      if (myResult.length >> 0){
               my_doc.textFrames[i].move(undefined, [0,-22]);

       

      app.findGrepPreferences = NothingEnum.nothing;

      app.changeGrepPreferences = NothingEnum.nothing;

      }}}

        • 1. Re: Moving threaded text frames CS3 (JS)
          [Jongware] Most Valuable Participant

          Given a pointer to a text frame, my_doc.textFrames[i], it has two properties that point to its previous and next frames, appropriately called "previousTextFrame" and "nextTextFrame". Each of those also may have a 'previousTextFrame' and 'nextTextFrame' (one of which is your starting frame), so you have to 'walk left' and move all of the 'previous' text frames, then 'walk right' and move all of the 'next' frames.

           

          The first and last text frame will contain 'null' for previous/next.

           

          How are you going to do this when you find your text in two frames that are threaded into the same story? The entire set would be moved twice, wouldn't it? (Since your Move is relative to their current position.)

           

          Perhaps you should not search the entire document for the text string, but go over each story instead. Only if the story contains your string (at least once), you can move the entire thread -- Story has an array of "textFrames", so no need to muck about with the previous/nextTextframe stuff.

          • 2. Re: Moving threaded text frames CS3 (JS)
            jmw107 Level 1

            Thanks.

             

            Could you please help me with the story aspect?

             

            var myStory = app.activeDocument.stories;
            for (i= myStory.length-1; i >= 0; i--) {
            if (myStory[i].contents !== ""){       
            var myResult = myStory[i].findGrep(true);
            if (myResult.length >> 0){
                        var myFrames = myStory[i].textFrames;
            for (i= myFrames.length-1; i >= 0; i--) {       
                    myFrames[i].move(undefined, [0,-22]);
                    
                    
                     }}

             

                 }}

             

            The above is not moving the text frames (nor is it generating any errors).  Could you help me fix this up?

             

            Thanks again for all the help.

            • 3. Re: Moving threaded text frames CS3 (JS)
              [Jongware] Most Valuable Participant

              (Without trying the rest) Could you change this line?

               

              if (myResult.length >> 0){

              to this?

               

              if (myResult.length > 0){

              It might make it work. The rest seems okay to me!

              • 4. Re: Moving threaded text frames CS3 (JS)
                jmw107 Level 1

                That had no affect ... However, your first thought (previousTextFrame) worked like a charm.

                 

                 

                for (i= my_doc.textFrames.length-1; i >= 0; i--) {
                if (my_doc.textFrames[i].contents !== ""){   
                    var myResult = my_doc.textFrames[i].findGrep(true);
                if (myResult.length >> 0){
                         my_doc.textFrames[i].move(undefined, [0,-18]);
                         my_doc.textFrames[i].previousTextFrame.move(undefined, [0,-18]);
                         }}}

                 

                That did exactly what i needed.

                 

                thanks very much for all your assistance.

                • 5. Re: Moving threaded text frames CS3 (JS)
                  [Jongware] Most Valuable Participant

                  O-o-oh. Please reconsider!

                   

                  First off, the use of >> is indeed a typo with side effects -- that's why it was a candidate for making the script fail. (After looking again, not really, but it's still 'wrong'.) If you use >>, the left-hand value gets shifted to the right by the amount in the right-hand value, effectively dividing it by two each time it shifts. Fortunately, shifting by 0 doesn't have any side-effects -- the value gets divided by two, zero times.

                  You really meant this:

                   

                  if (myResult.length > 0)

                   

                  (Compare to this:

                  if (myResult.length >> 1)

                   

                  now that would be wrong.)

                   

                  The other thing is, previousTextFrame is only valid for the one immediately before the text occurrence it found! So only 'this' and the previous frame are moved, none other.

                  • 6. Re: Moving threaded text frames CS3 (JS)
                    Haakenlid Level 3
                    var myFrames = myStory[i].textFrames;

                     

                    story.textFrames is a collection of any nested text frames contained in the story.

                    To get the text frames that contain the story, use story.textContainers

                    which will return an array of both text frames and text paths.

                     

                    This code will do what you want:

                    I usually prefer javascript's regular expressions to InDesign's GREP, unless I need to search for styling as well as text content, because I have to write fewer lines.

                     

                    var findWhat = /some text/  // this is a regular expression
                    var moveBy = [0,-22] // amount to move text containers
                    
                    var myStories = app.activeDocument.stories;
                    for (i=myStories.length-1; i >= 0; i--) {
                         if (myStories[i].contents.match(findWhat)){
                              myTextFrames=myStories[i].textContainers;
                              for (n=myTextFrames.length-1; n >= 0; n--){
                                   myTextFrames[n].move(undefined, moveBy);
                              }
                         }
                    }
                    
                    1 person found this helpful
                    • 7. Re: Moving threaded text frames CS3 (JS)
                      jmw107 Level 1

                      Thanks -- yep, all I want to do is move the text frame with the found text and the one immediately before.

                       

                      Good advice on the >>. I will clean up my script.

                       

                      On that topic is here any adobe or other documentation on what the options are in an 'if' statement? I know:

                       

                      == equals

                      !== does not equal (I assume)

                      > greater than

                      < lesser than

                      && (and)

                       

                      What would mean greater than or equal to, and lesser than or equal to?

                      Also, && means 'and." is there an equivalent for 'or'?

                       

                      thanks again.

                      • 8. Re: Moving threaded text frames CS3 (JS)
                        Haakenlid Level 3

                        They are called comparison and logical operators, and are part of javascript. Here's some info:

                        http://www.w3schools.com/JS/js_comparisons.asp

                         

                        >> and << are actually something called "bitwise operators", which I suppose proper programmers might find a use for. Don't use them if you don't know how they work. Compirason operators like > and === do not change the values in your variables. Bitwise operations like  myInteger>>3 will assign a new value to myInteger.

                        • 9. Re: Moving threaded text frames CS3 (JS)
                          jmw107 Level 1

                          Thanks -- I did not know you could use regex inside Adobe CS3 scripts.

                           

                          Would you happen to know of a good regex resource on the Web for me to learn proper syntax?

                           

                          thanks again.

                          • 10. Re: Moving threaded text frames CS3 (JS)
                            [Jongware] Most Valuable Participant

                            The W3 link is excellent -- in fact, that was the page I also checked for ">>".

                             

                            It answers all of your questions on the comparisons, but in short:

                             

                            != Does not equal

                            == Equals [*]

                            < Less than

                            <= Less than or equal

                            > Greater than

                            >= Greater than or equal

                            && And

                            || Or

                             

                            [*] I'm not familiar with when to use the '===' Haakenlid mentions, I imagine it's for 'deep' comparisons. Up to now I can manage with plain '==' ...

                             

                            A rather frequently made error -- until you learn to recognize it -- is this one:

                             

                            if (a = 1)

                            ...

                             

                            because it will always return 'true'! That's because it's an assignment, not a comparison. Variable 'a' gets set to the value '1', and assignments return their last result to the 'surrounding' code, which is not a problem if it's on a line of its own but in this case will always make the test pass.

                            • 11. Re: Moving threaded text frames CS3 (JS)
                              Haakenlid Level 3

                              jmw107 wrote:

                               

                              Thanks -- I did not know you could use regex inside Adobe CS3 scripts.

                               

                              Would you happen to know of a good regex resource on the Web for me to learn proper syntax?

                               

                              There are plenty. Just google "javascript regexp tutorial"

                               

                              Just keep in mind that there are a few different flavors of regexp around. InDesign's GREP is more versatile than javascripts regexp, and can handle some special characters like column break, right tab and so on.

                               

                              Also remember to test your expressions a lot.

                              • 12. Re: Moving threaded text frames CS3 (JS)
                                Haakenlid Level 3

                                [*] I'm not familiar with when to use the '===' Haakenlid mentions, I imagine it's for 'deep' comparisons. Up to now I can manage with plain '==' ...

                                 

                                 

                                == is not very strict and behaves quite strangely in javascript. Here are some examples:

                                 

                                "" == "0"           //false
                                0 == ""             //true
                                0 == "0"            //true
                                
                                false == undefined  //false
                                false == null       //false
                                null == undefined   //true
                                

                                 

                                With === these comparisons would all be false. So === is a strict comparison.

                                Javascript "guru" Douglas Crockford recommends that you should always use === instead of == and !== instead of !=