6 Replies Latest reply on Oct 15, 2009 9:28 AM by chughes133

    This script is being read too fast?

    chughes133 Level 1

      Hello, I am currently working on a script that will enable me to take a document, make several global changes, then save that document as 6 different files in order to make the changes needed on those particular versions.

       

      Now the code I'm running works perfectly fine, except for the fact that it is applying the wrong specific formatting or perhaps no formating to the particular versions.  however when one applies the specific formatting script individually one at a time, it works fine.

       

      I also couldnt figure out the object class for finding out a document name and making that into a document object (I'm just beginning, so my names are probably incorrect.)

       

      So I figured the issue was trhat indesign was still opening the file while the script was still running and therefore by the time it opens D it is applying the formating of X.  This is a real problem, so is there any kind of onLoad feature in indesign scripting format, or perhaps a condition within the opening method that forces it to wait for the opening to finish?

       

      Thanks!

       

      as a forwarning, here in the post i changed some of the names from what they were to just either A,S,D,Z,X, or C. also in the second part of the script A and S are missing. these things arent in the final i just changed them for reading purposes here.

       

      heres the script:

       

       

      var myFileName = app.activeDocument.name;

      var myDoc = app.activeDocument;

      var strPrefix;

      var strSuffix;

                  strPrefix = myFileName.substr(0, myFileName.lastIndexOf("."));

                  strSuffix = myFileName.substr(myFileName.lastIndexOf("."));

      var inFolder = Folder.selectDialog("Please choose the destination of the 6 X files.");

       

       

      function saveDocuments(doc, fullPath){

                 

                  myDoc.save(new File(decodeURI(inFolder) +"/" +(strPrefix + "A" + strSuffix)));

                  myDoc.save(new File(decodeURI(inFolder) +"/" +(strPrefix + "S" + strSuffix)));

                  myDoc.save(new File(decodeURI(inFolder) +"/" +(strPrefix + "D" + strSuffix)));

                  myDoc.save(new File(decodeURI(inFolder) +"/" +(strPrefix + "Z" + strSuffix)));

                  myDoc.save(new File(decodeURI(inFolder) +"/" +(strPrefix + "X" + strSuffix)));

                  myDoc.save(new File(decodeURI(inFolder) +"/" +(strPrefix + "C" + strSuffix)));

      }

       

      function save(){

                 

                  myDoc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.picas;

                  myDoc.viewPreferences.verticalMeasurementUnits = MeasurementUnits.picas;

                  myDoc.textPreferences.smallCap = 75

                  myDoc.textPreferences.superscriptPosition = 33.2

                  myDoc.textPreferences.superscriptSize = 60

                  myDoc.textPreferences.subscriptPosition = 33.2

                  myDoc.textPreferences.subscriptSize = 60

       

       

                  saveDocuments(myDoc, inFolder.fullName + "/" + myFileName);

      }

       

      save();

      for(myCounter = app.documents.length; myCounter > 0; myCounter--)

                  {

                  app.documents.item(myCounter-1).close(SaveOptions.no);

                }

       

      var sFolder = inFolder +"";

       

       

      function D(){

                              app.open(File (sFolder + "/" + (strPrefix + "D" + strSuffix)));

       

       

                 

       

                  var myStyles = app.activeDocument.paragraphStyles;

                  var myChStyles = app.activeDocument.characterStyles;

                              for (oneStyle=1;oneStyle<myStyles.count();oneStyle++)

                                          {

                                          myStyles[oneStyle].appliedLanguage= "D";

                                          }

                              for (unStyle=1;unStyle<myChStyles.count();unStyle++)

                                          {

                                          myChStyles[unStyle].appliedLanguage= "D";

                                          }

                 

                  app.activeDocument.save(File(), true);

                  app.activeDocument.close(SaveOptions.no);

                  }

      D();

      /*

      function Z(){

                  app.open(File (sFolder + "/" + (strPrefix + "Z" + strSuffix)));

       

                  var myStyles=app.activeDocument.paragraphStyles;

                  var myChStyles=app.activeDocument.characterStyles;

                                for (oneStyle=1;oneStyle<myStyles.count();oneStyle++)

                                          {

                                          myStyles[oneStyle].appliedLanguage= "Z";

                                          }

                              for (unStyle=1;unStyle<myChStyles.length;unStyle++)

                                          {

                                          myChStyles[unStyle].appliedLanguage= "Z";

                                          }

                 

                  app.activeDocument.save(File(myFileName), true);

                  app.activeDocument.close(SaveOptions.no);

                  }

       

      Z();

      function X(){

                  app.open(File (sFolder + "/" + (strPrefix + "C" + strSuffix)));

       

                  var myStyles=app.activeDocument.paragraphStyles;

                  var myChStyles=app.activeDocument.characterStyles;;

       

                              for (oneStyle=1;oneStyle<myStyles.count();oneStyle++)

                                          {

                                          myStyles[oneStyle].appliedLanguage= "X";

                                          }

                              for (unStyle=1;unStyle<myChStyles.length;unStyle++)

                                          {

                                          myChStyles[unStyle].appliedLanguage= "X";

                                          }

                 

                  app.activeDocument.save(File(myFileName), true);

                  app.activeDocument.close(SaveOptions.no);

                  }

      X();

      function C(){

                  app.open(File (sFolder + "/" + (strPrefix + "C" + strSuffix)));

       

                  var myStyles=app.activeDocument.paragraphStyles;

                  var myChStyles=app.activeDocument.characterStyles;

                               

                              for (oneStyle=1;oneStyle<myStyles.count();oneStyle++)

                                          {

                                          myStyles[oneStyle].appliedLanguage= "C";

                                          }

                              for (unStyle=1;unStyle<myChStyles.length;unStyle++)

                                          {

                                          myChStyles[unStyle].appliedLanguage= "C";

                                          }

                 

                  app.activeDocument.save(File(myFileName), true);

                  app.activeDocument.close(SaveOptions.no);

                  }

      C();

      app.open(File (sFolder + "/" + (strPrefix + "D" + strSuffix)));

       

        • 1. Re: This script is being read too fast?
          Marc Autret Level 4

          Hi chugues133, you need to fight code redundance!

           

          I don't know what actually are 'A', 'S', 'Z', 'D', 'X', 'C'... (maybe Language names or something)

          Attempting to extract the idea behind your script, I just suggest you a more 'modular' approach:

           

          // Put your 'A','S','D','Z','X','C' in an array
          // -----------------
          // as an example:
          var languages = ['Spanish','Italian','French'/* etc.*/];
          
          (function()
          {
          // check if there's something to do
          // -----------------
          if (app.documents.length == 0) return;
          
          // get the dest folder (cancelable)
          // -----------------
          var inFolder = Folder.selectDialog("Please choose the destination of the 6 X files.");
          if (!inFolder) return;
          
          // now let's go
          // -----------------
          var doc = app.activeDocument;
               
          // preset picas units
          // -----------------
          (function()
               { //<this>: viewPreference
               this.horizontalMeasurementUnits =
               this.verticalMeasurementUnits =
               MeasurementUnits.picas;
               }).call(doc.viewPreferences);
          
          // preset textPreferences
          // -----------------
          (function()
               { // <this>: textPreference
               this.smallCap = 75;
               this.superscriptPosition = 33.2;
                this.superscriptSize = 60;
               this.subscriptPosition = 33.2;
               this.subscriptSize = 60;
               }).call(doc.textPreferences);
          
          // build (once) the helper path fct
          // -----------------
          var getLangFilePath = (function()
               { // <this>: string (doc name)
               var splitName = this.split('.');
               var sfx = '.' + splitName.pop();
               var pfx = decodeURI(inFolder) + "/" + splitName.join('.');
               return function(lg){return pfx+lg+sfx;};
               }).call(doc.name);
          
          // build the 're-style' fct
          // -----------------
          var restyleDocLang = function(doc,lg)
               {
               var restyle = function()
                    { // <this>: array of styles
                    var s;
                    while(s=this.pop())
                         {
                         try{s.appliedLanguage = lg;}
                         catch(e){}
                         }
                    };
               restyle.call(doc.paragraphStyles.everyItem().getElements());
               restyle.call(doc.characterStyles.everyItem().getElements());
               };
          
          // then, loop on your array
          // -----------------
          var lg;
          while(lg=languages.pop())
               {
               restyleDocLang(doc,lg);
               doc.save( new File(getLangFilePath(lg)) );
               doc = app.activeDocument;
               }
          
          doc.close(SaveOptions.no);
          })();
          

           


          Just a draft...

          1 person found this helpful
          • 2. Re: This script is being read too fast?
            chughes133 Level 1

            Wow, that script seems to simplify my code a lot however I don't understand a number of elements.  All in all quite brilliant. Let me start out by saying that the purpose of the script is to take a single document apply changes (these changes will effect the 6 documents that are to be created from this one) and then create 6 different correctly named language files (you were right about that) and then apply unique properties for each of those documents.  In the long run I was hoping to add more elements to the code besides changing the language but for now that is my starting point.

            Now from what I could understand from your code it is expecting these 6 files to already be prepared. If that's a mistake then please day so. Also the names have to be in caps, and since certain languages require a qualification (such as English: UK) one cannot correlate the two words without what I imagine might be a complex little function.

             

            I also had a few questions if you might inform me.  Like i said I'm just beginning so all of the objects and classes (even the basic ones) I don't fully comprehend.  Now the return (command?  its not a class. maybe an object?) object at the end of a line seems to stop the script as possibly the case is here:

            if (app.documents.length == 0) return;

            but in this case:

            returnfunction(lg){returnpfx+lg+sfx;};

            I dont really understand. 

             

            with this variable, were you saying to make it local, or that it should be a different name within all the functions?

             

            what is this?:

            }).call(doc.viewPreferences);

             

            This also lost me.  and how does one create an array out of the styles?  I used the paragraphStyles.length object but I didnt think that created an array.

            while(s=this.pop())
                           {
                           try{s.appliedLanguage = lg;}
                           catch(e){}

             

            Thank you so much for all your help! Your version really seems to make a lot of sense, but I just wanted to raise those few issues before I tried it out. especially with he name to language issue.

            • 3. Re: This script is being read too fast?
              Marc Autret Level 4

              Hi chugues133,

               

              Many of your questions relate to the basics of functionnal programming. If I was a good teacher I could try to explain the principles, but I'm not (!) and there are many excellent resources on the Web to learn JavaScript syntax... For example, try this one: http://eloquentjavascript.net/

               

              chughes133 wrote:

               

              Now from what I could understand from your code it is expecting these 6 files to already be prepared.

               

              Not exactly. The script takes the active document as a kind of model. It applies on it some "presets" (see the commented lines), then for each language it applies the language styles AND saves the prepared document with a specific file name depending on the current language. So, at the end, you have as many saved documents as languages defined at the beginning of the code.

               

              The targetted languages are given in an array:

              var languages = ['Spanish','Italian','French'/* etc.*/];

               

              chughes133 wrote:

               

              Also the names have to be in caps, and since certain languages require a qualification (such as English: UK) one cannot correlate the two words without what I imagine might be a complex little function.

               

               

              I didn't know exactly what you need to handle through the mysterious 'A', 'S', 'D', 'Z'..., so I made the assumption that these letters were placeholders for kind of language codes. But you're right, the script has to be improved so as to deal with issues in file naming. I suggest you to distinguish between the language code you want to inject in the filename AND the language name InDesign can apply to a style. You can easily manage this aspect through an associative array:

               

              var languages = {IT: 'Italian', UK: 'English: UK', FR: 'French'};

               

              The keys ('IT', 'UK', 'FR'...) could specify a formal code for filenaming and the values ('Italian', 'English: UK') could be the InDesign language names. In a recent thread (http://forums.adobe.com/thread/505796), Jongware gives a good tip to identify ID language names from your localized UI.

               

              To traverse the languages associative array, you can do this:

               

              for (var key in languages)
                   {
                   // use key as the language code ('IT', 'UK'...)
                   // use languages[key] as the language name ('Italian', 'English: UK'...)
                   }
              

               

              chughes133 wrote:

               

              return function(lg) {return pfx+lg+sfx;};

              I dont really understand. 

               

              with this variable, were you saying to make it local, or that it should be a different name within all the functions?

               

              This code returns a function. An interesting aspect of JS is that you can return (from a function) any type of object, including function. In this case, the function returned takes one argument, lg, and is designed to return the concatenated string pfx + lg + sfx. The idea behind this stuf is that lg (the language code) is the only information which varies at this point of the process. Suppose your main file is myDocument.indd and your destination folder is /my/Folder/. What do you want? You want to create the files: /my/Folder/myDocumentIT.indd, /my/Folder/myDocumentUK.indd, etc. There is no reason to recalculate each part of the complete path when you will loop in the language codes. The prefix is known (/my/Folder/myDocument) and the suffix too (.indd). The function above build the path by simply mixing what we know (pfx, sfx) with what varies (lg).

               

              The key point is to "pre-compute" as much information as you can before to perform a loop. If you study closely the needs of your script, you see that once the user has selected the destination folder and once the active document is "prepared", all the parameters are freezed. Then, the essential part of the process is here:

               

              // loop on the language codes
              while(lg=languages.pop())
                   {
                   // apply the language style
                   restyleDocLang(doc,lg);

                   // save the document with the language-specific name
                   doc.save( new File(getLangFilePath(lg)) );

                   // update the <doc> variable
                   doc = app.activeDocument;
                   }

               

              chughes133 wrote:

               

              what is this?:

              }).call(doc.viewPreferences);


               

              Maybe a little tricky to explain in depth... Say it's a way to encapsulate operations targetting the same object (doc.viewPreferences) and to avoid redundancy of arbitrary variable name(s).

               

              You can see:

               

              (function()
                   { //<this>: viewPreference
                   this.horizontalMeasurementUnits =
                   this.verticalMeasurementUnits =
                   MeasurementUnits.picas;
                   }).call(doc.viewPreferences);

               

              as:

               

              doc.viewPreferences.horitontalMeasurementUnits =
              doc.viewPreferences.verticalMeasurementUnits =
              MeasurementUnits.picas;
              

               

              chughes133 wrote:

               

              This also lost me.  and how does one create an array out of the styles?  I used the paragraphStyles.length object but I didnt think that created an array.

              while(s=this.pop())
                             {
                             try{s.appliedLanguage = lg;}
                             catch(e){}

               

              You need to take the whole function to understand:

               

              // build the 're-style' fct
              // -----------------
              var restyleDocLang = function(doc,lg)
                   {
                   var restyle = function()
                        { // <this>: array of styles
                        var s;
                        while(s=this.pop())
                             {
                             try{s.appliedLanguage = lg;}
                             catch(e){}
                             }
                        };
                   restyle.call(doc.paragraphStyles.everyItem().getElements());
                   restyle.call(doc.characterStyles.everyItem().getElements());
                   };

               

              Once again, I can't explain in depth. Just regard restyle() as a little tool which apply the language lg on each style of an array. We use this tool twice: one for doc.paragraphStyles, one for doc.characterStyles. But since doc.xxxStyles is not really an array --it's a collection--, we use the ...everyItem().getElements() syntax to get an actual array.

               

               

              About:

              while ( <myItem> = <myArray>.pop() )

               

              let's say it's a quick way to loop in a temporary array (from the end to the beginning) when we don't need to re-use the array after the loop.

               

               

              @+

              Marc

              1 person found this helpful
              • 4. Re: This script is being read too fast?
                chughes133 Level 1

                Hello Marc Autret

                 

                IThank you for taking the time to explain some of the functions in the script. You're as patient as anyone could ever hope to ask for when it comes to internet forum responses. And also for the reference. I will be using this in the future before pestering people. I'm really only just beginning to understand the extendscript object model viewer, which will also I'm sure be a key to picking up some of this stuff more.

                 

                efore I step forward and ask any more questions as to what you just said, let me predicate it by the fact that I wasn't able to get the script to work. This I believe is an effect of the changes from 5.0 to 6.0 InD javascript coding. the object(method?) of .everyItem().getElements() doesn't seem to work in the new code.  Neither does my original script however.  It worked on the paragraphStyles that were naked without a folder, but for files that were in groups, it remained ineffective. Unfortunately in my case this makes my efforts rather fruitless.  Therefore after spending a few frustrating hours on the script I managed to discover the solution.  But first I'd like to ask why this didn't work:*note this is from my memory and therefore informally written.  If there are any spelling mistakes or cap mistakes, please disregard.

                var gPstyles=app.activeDocument.paragraphStyleGroups

                for (i=0;i<gPstyles.length;i++){

                     for (p=0;p<gPstyles[i].length;p++){

                          app.activeDocument.paragraphStyleGroup[i].paragraphStyle[p].appliedLanguages= "Spanish";

                }

                 

                }

                 

                 

                Now naturally it responded with a complaint.  However I wanted to know if I was close, and that I simply had to redefine i as object rather than let its index number stand for an object, or was I wrong down to the last }? smaller question I suppose, and only for my own edification. this was eventually the solution that I arrived at and it worked much simpler than the above code:

                 

                app.activeDocument.allParagraphStyles.appliedLanguage= "Spanish";

                 

                the allParagraphStyles object would enable me to access all the styles regardless of grouping.

                 

                Now my question is that if I Make that small change to your code will it work as is? OR do I need to define further some of the elements.  Mainly I'm thinking about your language key. If my code is such:

                 

                var lg = [ENGLISH: "English: UK", FRENCH: "French", SPANISH: "Spanish"]

                     for {

                          ??????

                }

                I wouldnt be sure how to identify the key versus the name.  secondly, you placed the fileName portion following the language name.  However in the case of English: UK, i was guessing that the colon would be in conflict with the code.

                 

                Thanks for your time again. I'll delve into that link as soon as I can.

                • 5. Re: This script is being read too fast?
                  Marc Autret Level 4

                  chughes133 wrote:

                   

                  But first I'd like to ask why this didn't work:*note this is from my memory and therefore informally written.  If there are any spelling mistakes or cap mistakes, please disregard.

                  var gPstyles=app.activeDocument.paragraphStyleGroups

                  for (i=0;i<gPstyles.length;i++){

                       for (p=0;p<gPstyles[i].length;p++){

                            app.activeDocument.paragraphStyleGroup[i].paragraphStyle[p].appliedLanguages= "Spanish";

                  }

                   

                  }

                   

                   

                  gPstyles is a paragraphStylesGroups collection

                  gPstyles[i] is a paragraphStylesGroup

                   

                  then, you wanted to loop in the paragraphStyles owned by this group, so the sub-loop should be rather:

                  for (p=0;p<gPstyles[i].paragraphStyles.length;p++) {

                       gPstyles[i].paragraphStyles[p].appliedLanguages= "Spanish";

                       }

                   

                  chughes133 wrote:

                   

                  (...) this was eventually the solution that I arrived at and it worked much simpler than the above code:

                   

                  app.activeDocument.allParagraphStyles.appliedLanguage= "Spanish";

                   

                  the allParagraphStyles object would enable me to access all the styles regardless of grouping.

                  You are correct! allParagraphStyles will quite simplify the code.

                   

                  chughes133 wrote:

                   

                   

                  Now my question is that if I Make that small change to your code will it work as is? OR do I need to define further some of the elements.  Mainly I'm thinking about your language key. If my code is such:

                   

                  var lg = [ENGLISH: "English: UK", FRENCH: "French", SPANISH: "Spanish"]

                       for {

                            ??????

                  }

                  I wouldnt be sure how to identify the key versus the name.  secondly, you placed the fileName portion following the language name.  However in the case of English: UK, i was guessing that the colon would be in conflict with the code.

                   

                  Thanks for your time again. I'll delve into that link as soon as I can.

                   

                  Attention! languages (not lg) is now an "associative array" wich is in fact an Object (not an actual Array). Here the correct declaration needs braces { } (not square brackets):

                   

                  var languages = { ENGLISH: "English: UK", FRENCH: "French", SPANISH: "Spanish" };

                   

                   

                  Obviously, the code must be modified accordingly.

                   

                  Try this:

                  var languages = {
                       // CODE: "<InDesign Language Name>"
                       ENGLISH: "English: UK",
                       FRENCH: "French",
                       SPANISH: "Spanish"
                       };
                  
                  (function()
                  {
                  // check if there's something to do
                  // -----------------
                  if (app.documents.length == 0) return;
                   
                  // get the dest folder (cancelable)
                  // -----------------
                  var inFolder = Folder.selectDialog("Please choose the destination of the 6 X files.");
                  if (!inFolder) return;
                   
                  // now let's go
                  // -----------------
                  var doc = app.activeDocument;
                       
                  // preset picas units
                  // -----------------
                  (function()
                       { //<this>: viewPreference
                       this.horizontalMeasurementUnits =
                       this.verticalMeasurementUnits =
                       MeasurementUnits.picas;
                       }).call(doc.viewPreferences);
                   
                  // preset textPreferences
                  // -----------------
                  (function()
                       { // <this>: textPreference
                       this.smallCap = 75;
                       this.superscriptPosition = 33.2;
                        this.superscriptSize = 60;
                       this.subscriptPosition = 33.2;
                       this.subscriptSize = 60;
                       }).call(doc.textPreferences);
                   
                  // build (once) the helper path fct
                  // -----------------
                  var getLangFilePath = (function()
                       { // <this>: string (doc name)
                       var splitName = this.split('.');
                       var sfx = '.' + splitName.pop();
                       var pfx = decodeURI(inFolder) + "/" + splitName.join('.');
                       return function(lg){return pfx+lg+sfx;};
                       }).call(doc.name);
                   
                  // build the 're-style' fct
                  // -----------------
                  var restyleDocLang = function(doc,lgName)
                       {
                       var restyle = function()
                            { // <this>: array of styles
                            var s;
                            while(s=this.pop())
                                 {
                                 try{s.appliedLanguage = lgName;}
                                 catch(e){}
                                 }
                            };
                       restyle.call(doc.allParagraphStyles);
                       restyle.call(doc.allCharacterStyles);
                       };
                   
                  // then, loop in the associative array
                  // -----------------
                  for(var lg in languages)
                       {
                       // languages[lg] is the language name
                       restyleDocLang(doc,languages[lg]);
                       
                       // lg is the language code
                       doc.save( new File(getLangFilePath(lg)) );
                       doc = app.activeDocument;
                       }
                   
                  doc.close(SaveOptions.no);
                  })();
                  

                   

                  @+

                  Marc

                  • 6. Re: This script is being read too fast?
                    chughes133 Level 1

                    First off thanks for clarifying the gPstyles issue.  I KNEW i was pretty close. but now I know how to create the distinctions between the collection object and the (element?) object. I didn't think of crossing the i and p values like that.

                     

                    My god man, but that script works beautifully. It was incredibly faster than mine, and worked like a charm. I've been reading that site and slowly making it through (having more than once created some kind of endless loop and having to shut down the browser haha!) and have already learned quite a bit.

                     

                    From that I understood what you made clear in this post about the {} array and the [] array.  I also came upon the .toUpperCase function and thought that might work, but there would have to be another prefix suffix check in order to delete that : UK. So that was that end of it.  Now I am beginning to understand your code however if you dont mind I'd like to ask one or two more small questions before I try moving on to the next project/back to the site.

                     

                    it's my understand that the pop() function gets rid of all data behind it's reference point. I know in other or loops it might just drop down the integer by 1, but in this case it pops off everything before the '.'

                     

                    however here:

                     

                    // build the 're-style' fct
                    // -----------------
                    var restyleDocLang = function(doc,lgName)
                         {
                         var restyle = function()
                              { // <this>: array of styles
                              var s;
                              while(s=this.pop())
                                   {
                                   try{s.appliedLanguage = lgName;}
                                   catch(e){}
                                   }
                              };
                         restyle.call(doc.allParagraphStyles);
                         restyle.call(doc.allCharacterStyles);
                         };

                    this refers to the doc.allParagraphStyles.  however then you pop off.....OOOOH haha ok then so it is in fact simply popping off the previous paragraph style altered.  OK then. but then what is the catch(e){} object?

                     

                    I was going to ask another question about how you used the lg and lgName variables.  But then before pressing the send button i carefully read the explaination again and I got it.  Thanks!

                     

                    I also wanted to say that it was pretty neat how you properly scoped the variable doc through the whole thing, among all the other variables that were moving through the beginning but were only defined at the end.  Naturally since I'm a beginner alot of thing amaze me but this was especially nice.