14 Replies Latest reply on Jun 23, 2010 5:04 AM by Muthuraj Durairaj

    Applescript to Javascript

    cloondaff53

      I have an Applescript that I need to convert to a Javascript.

      I have read some of the documentation for Javascript but I am finding it tough.

      Can anyone show me the equivalent Javascript for this Applescript

       

      set the thefolder to alias "macHD:Users:Smith:Desktop:PDFs:"
      tell application "Adobe InDesign CS3"
          tell document 1
              set the ADSTACK to every text frame whose label starts with "Product"
              if (count of ADSTACK) = 1 then
                  set the AdLabel to label of item 1 of ADSTACK
                  set AdNumber to word 3 of AdLabel & ".pdf"
                  tell item 1 of ADSTACK
                      try
                          set thisAd to thefolder & AdNumber as text as alias
                          place thisAd
                      on error
                          display dialog "Ad not found" buttons {"Cancel"} with icon 1
                      end try
                  end tell
              else
                  repeat with i from 1 to count of ADSTACK
                      set the AdLabel to label of item i of ADSTACK
                      set AdNumber to word 3 of AdLabel & ".pdf"
                      tell item i of ADSTACK
                          try
                              set thisAd to thefolder & AdNumber as text as alias
                               place thisAd
                          on error
                              display dialog AdNumber & " not found" buttons {"Cancel", "OK"} default button 2 with icon 1
                          end try
                      end tell
                  end repeat
              end if
          end tell
      end tell

        • 1. Re: Applescript to Javascript
          John Hawkinson Level 5

          Well, I don't have time to do the whole thing, but I can get you started:

           

          // set the thefolder to alias "macHD:Users:Smith:Desktop:PDFs:"
          var thefolder;
          thefolder = new Folder("macHD:Users:Smith:Desktop:PDFs");
          
          // But you would be better off not specifying the user,
          // almost certainly:
          
          thefolder = new Folder("~/Desktop/PDFs");
          
          // tell application "Adobe InDesign CS3"
          //   tell document 1
          
          //     set the ADSTACK to every text frame
          //     whose label starts with "Product"
          
          var ADSTACK = new Array();
          var tfs = app.activeDocument.textFrames; // tfs == textFrames
          var i;
          for (i=0; i<tfs.length; i++) {
               if tfs[i].label.match(/^Product/) ADSTACK.push(tfs[i]);
          }
          //        if (count of ADSTACK) = 1 then
          if (ADSTACK.length == 1) {
          //            set the AdLabel to label of item 1 of ADSTACK
            var AdLabel = ADSTACK[0].label;
          //            set AdNumber to word 3 of AdLabel & ".pdf"
            var AdNumber = AdLabel.split(" ")[2]+"/pdf";
          

          Of course, there are a bunch of style things:

           

          • Variable names in JavaScript should be written in "camelCase". That is, lowercase first letter, and then internal caps. So you would use "theFolder" and "adLabel" and "adStack" but not "thefolder", "AdLabel", or "ADSTACK." I've kept the variable names the same.

          • Not style, but javascript is zero-indexed. So "item 1 of ADSTACK" is ADSTACK[0] not ADSTACK[1]. Also "AdLabel.split(" ")[2]" but "word 3 of AdLabel".

          • I use a regular expression to check if the label starts with Product. This is not the most efficient, but is the most flexible and easy to type. I'm not sure what the trivial JavaScript comparison would be to match exactly what you've done in applescript in the most efficeient way.
          • JavaScript doesn't have filters, so you have to use an ugly for loop. I declare a temporary variable "tfs" (short for TextFrames) to add syntactic sugar and make the lines short enough to type. But you could ignore it and just write out app.activeDocument.textFrames[i]
          • You have needless code duplication conditionalized on whether there's more than 1 item in your stack. I didn't eliminate it, but you probably should.
          • As I note in the code, if you don't have to hardcode the name of the user running the script, you probably should not.

           

          This should be enough to get you started. Ask if you need more specific help.

          • 2. Re: Applescript to Javascript
            [Jongware] Most Valuable Participant
            I use a regular expression to check if the label starts with Product. This is not the most efficient, but is the most flexible and easy to type. I'm not sure what the trivial JavaScript comparison would be to match exactly what you've done in applescript in the most efficeient way.

             

            I'm fairly convinced this is the most efficient way (a direct string comparison), although I doubt efficiency is a prime objective for such a script.

             

            if ( tfs[i].label.substr(0,7) == "Product") ...

            • 3. Re: Applescript to Javascript
              Muppet Mark-QAl63s Level 4

              Jong I went the way of substring() as you. Like John now that I look at it I don't think case 1 is required wouldn't it be covered by default?

               

              #target indesign

               

              function adStack() {

              if (app.documents.length == 0) {

              alert('Please have an "InDesign" document open before running this script.');

              return;

              }

              var inputFolder = new Folder('~/Desktop/PDFs');

              var docRef = app.activeDocument;

              with (docRef) {

              var adStackList = new Array();

              for (var j = 0; j < textFrames.length; j++) {

              if (textFrames[j].label.substring(0,7) == 'Product') {

              adStackList.push(textFrames[j]);

              }

              }

              switch (adStackList.length) {

              case 0 :

              alert('No Items');

              break;

              case 1 :

              var adNumber = adStackList[0].label.split(' ')[2];

              var pdfPath = new File(inputFolder.fsName + '/' + adNumber  + '.pdf');

              if (pdfPath.exists) {

              adStackList[0].place(pdfPath);

              } else {

              alert('File "' + adNumber + '" does NOT exist?');

              }

              break;

              default :

              for (var k = adStackList.length-1; k >= 0; k--) {

              var adNumber = adStackList[k].label.split(' ')[2];

              var pdfPath = new File(inputFolder.fsName + '/' + adNumber  + '.pdf');

              if (pdfPath.exists) {

              adStackList[k].place(pdfPath);

              } else {

              alert('File "' + adNumber + '" does NOT exist?');

              continue;

              }

              }

              break;

              }

              }

              }

               

              adStack();

              • 4. Re: Applescript to Javascript
                John Hawkinson Level 5

                Muppet Mark, could you please use Java syntax highlighting? It makes reading posted scripts so much easier!

                 

                Jongware, of course that works, but from my ivory tower, it is Unacceptable because you stopped to count the number of letters in Product, and you hardcoded them in the script. So if somebody casually changes the word "Product" to "Producto," then the script will stop working! Etc. I think posting stuff like this does a disservice to the OP, who may not have a good way to evaluate which solution really matters (sorry, OP!).

                 

                I don't know if there's a way to make the JavaScript tokenizer do the count for you.

                 

                But maybe within acceptability is:

                if (tfs[i].label.substr(0,"Product".length) == "Product")
                

                 

                I guess there's always:

                function startsWith(a, b) {return a.substr(0,b.length) == b}
                if (startsWith(tfs[i].label,"Product"))
                

                 

                and then someone will argue we should use:

                if (function(a,b){return(a.substr(0,b.length)==b)
                  (tfs[i].label,"Product"))
                

                 

                and someone else will go for:

                String.prototype.startsWith =
                  function(s) { return this.substr(0,s.length)==s }
                if (tfs[i].label.startsWith("Product"))
                

                 

                and I don't know which of them I dislike more! Maybe someone will tell us that the function call overhead is significant, and someone else will tell us that the JIT compiler will take it out (is there a JIT compiler here? I have no idea!).

                 

                I should just delete this post instead of clicking "Post Message." Sorry, cloondaff53 --- I hope you don't hate JavaScript now; at least, not any more than it deserves.

                 

                P.S.: I broke up two medium-long lines in the last two snippets so you don't have to scroll to read them on the forum. But of course each would be 1 line shorter, making the last 2 lines and the penultimate 1 line. If you're one of those line-counters...

                • 5. Re: Applescript to Javascript
                  Muppet Mark-QAl63s Level 4

                  Sorry John, where do I find this styling option?

                   

                  BTW 'Producto'.substring(0,7) == 'Product'

                  • 6. Re: Applescript to Javascript
                    John Hawkinson Level 5

                    Just follow the >> arrows at the top of the reply textarea:

                    Screen shot 2010-03-31 at 9.24.11 AM.png

                    With respect to:

                    BTW 'Producto'.substring(0,7) == 'Product'

                    Nooooooo! That's exactly the problem! It'd be like I asked for for words starting with "Product" and it also happened to give me all words starting with "Produc". Sure, it would correctly give me "Product" and "Productize," but it would also incorrectly give me "Produce," and "Producible" and...any other words you might happen to make up, like "ProducMuppetMarkOutOfAHatOopsIforgotTheLetterE!".

                    • 7. Re: Applescript to Javascript
                      Muppet Mark-QAl63s Level 4

                      Thanks John, thats why Im a muppet…

                      • 8. Re: Applescript to Javascript
                        cloondaff53 Level 1

                        Hi John,

                         

                        Thanks for all your help.

                         

                        When I run the script it stops at this line.

                         

                             if tfs[i].label.match(/^Product/) ADSTACK.push(tfs[i]);
                        • 9. Re: Applescript to Javascript
                          [Jongware] Most Valuable Participant

                          You should have used my version

                          John forgot to start with an open parenthesis after the first "if", and a close one after the "match(/product/)" stuff.

                           

                          if (xx) ... should always have its argument surrounded by parentheses.

                           

                          By the way, this was an easy case, but you should always try to copy the exact line and error number that Javascript reports! Rather than just saying "it does not work".

                          • 10. Re: Applescript to Javascript
                            cloondaff53 Level 1

                            Thanks to everyone who responded to my question.

                            I just started to read the Javascript InDesign pdf yesterday.

                            Sorry about not listing the information about the error and line number.

                             

                            Buy using the samples you have provided I have come up with this.

                             

                             

                             

                            //path to ContigencyPDFs on desktop
                            var inputFolder = new Folder("~/Desktop/ContigencyPDFs");
                            //Create a new array
                            var adStack = new Array();
                            //Array "tfs" holds a reference to all page items in the open document
                            var tfs = app.activeDocument.pageItems;
                            var i;
                            //Loop to get a reference to all page items that have the label "Product" as part of the name and add it to the adStack Array
                            for (var i=0; i<tfs.length; i++) {
                                 //Check to see if  the word "Product" appears in label
                                 if (tfs[i].label.match(/^Product/)) adStack.push(tfs[i]);
                            }
                            //Array "adStack" contains only one item
                            if (adStack.length == 1) {
                            // Get the label name
                            var adLabel = adStack[0].label;
                            // Get the 3rd word of the label name
                              var adNumber = adLabel.split(" ")[2]+".pdf";
                               //Set up a complete path to the file
                               var pdfPath = new File(inputFolder.fsName + '/' + adNumber);
                                //Place the ad in the frame
                                adStack[0].place(pdfPath);
                               }
                            //More than 1 item in adStack
                            else if (adStack.length > 1) {
                            for (var k = adStack.length-1; k >= 0; k--) {
                            var adNumber = adStack[k].label.split(' ')[2];
                            var pdfPath = new File(inputFolder.fsName + '/' + adNumber  + '.pdf');
                            if (pdfPath.exists) {
                            adStack[k].place(pdfPath);

                             

                            } else {
                            alert('File "' + adNumber + '" does NOT exist?');
                            }
                            }
                            }

                            • 11. Re: Applescript to Javascript
                              John Hawkinson Level 5

                              Sorry about the missing paren. Consider it a lesson.

                               

                              cloon, you, just like Muppet Mark, should use Java syntax highlighting.

                               

                              Anyhow, I still don't understand why you're testing the size of the adStack. Also a bit weird, stylistically, for you to count up your i but count down your k. But anyhow, I would combine your 2nd half like this, also get rid of k, and you don't need to var your loop counter seperately. Also, best practice is for your error message to give the name of the file it is looking for, not just the number. Otherwise someone unfamiliar w/ the script might have to look at the script to debug it. And that's no fun if they don't know how:

                               

                              //path to ContigencyPDFs on desktop
                              var inputFolder = new Folder("~/Desktop/ContigencyPDFs");
                              var adStack = new Array();
                              var tfs = app.activeDocument.pageItems;
                              //Loop to get a reference to all page items that have the
                              // label "Product" as part of the name and add it to
                              // the adStack Array
                              for (var i=0; i<tfs.length; i++) {
                                   //Check to see if  the word "Product" appears in label
                                   if (tfs[i].label.match(/^Product/)) adStack.push(tfs[i]);
                              }
                              for (var i = 0; i < adStack.length; i++) {
                                var adNumber = adStack[i].label.split(' ')[2];
                                var pdfPath = new File(inputFolder.fsName + '/' +
                                  adNumber  + '.pdf');
                                if (pdfPath.exists)
                                  adStack[i].place(pdfPath);
                                else
                                  alert('File "' + pdfPath +
                                  '" ('+ adNumber + ') does NOT exist?');
                              }
                              
                              • 12. Re: Applescript to Javascript
                                Muppet Mark-QAl63s Level 4

                                John, in the OP's AppleScript they were looking for 'textFrames' whose labels started with 'Product'. Your script has changed this to 'pageItems' and changed the scope a little there. I did not ask as to why this was just took it at face value. When placing a PDF graphic in a text frame it is NO longer a text frame but a rectangle therefore your loop will break around the mid point with invalid object. Reversing the second loop avoided this. Also a continue to proceed this the rest of the available PDFs.

                                 

                                #target indesign
                                
                                var inputFolder = new Folder("~/Desktop/ContigencyPDFs");
                                var adStack = new Array();
                                var tfs = app.activeDocument.textFrames;
                                
                                for (var i=0; i<tfs.length; i++) {
                                     if (tfs[i].label.match(/^Product/)) adStack.push(tfs[i]);
                                }
                                
                                for (var i = adStack.length-1; i >= 0; i--) {
                                     var adNumber = adStack[i].label.split(' ')[2];
                                     var pdfPath = new File(inputFolder.fsName + '/' +
                                          adNumber  + '.pdf');
                                     if (pdfPath.exists)
                                          adStack[i].place(pdfPath);
                                     else
                                          alert('File "' + pdfPath +
                                          '" ('+ adNumber + ') does NOT exist?');
                                          continue;
                                }
                                

                                 

                                Liking the highlighting thing…

                                • 13. Re: Applescript to Javascript
                                  John Hawkinson Level 5

                                  I was just editing the last version of the script cloondaff53 posted...-- the 12:45pm version used pageItems. Good observation!

                                   

                                  I'm confused about your "continue". You wrote:

                                      if (pdfPath.exists)
                                            adStack[i].place(pdfPath);
                                       else
                                            alert('File "' + pdfPath +
                                            '" ('+ adNumber + ') does NOT exist?');
                                            continue;
                                  

                                   

                                  but since the if is the last thing in the for loop, what does it matter? In either case, though, you need curly braces around the multiple lines:

                                      if (pdfPath.exists)
                                            adStack[i].place(pdfPath);
                                       else {
                                            alert('File "' + pdfPath +
                                            '" ('+ adNumber + ') does NOT exist?');
                                            continue;
                                       }
                                  
                                  • 14. Re: Applescript to Javascript
                                    Muthuraj Durairaj Level 1

                                    Hi Muppet Mark,

                                     

                                    I saw your great help on converting applescript to Javascript and I am also in a need to convert a applescript into Javascript.

                                     

                                     

                                    tell application "Adobe InDesign CS3" 
                                    activate 
                                    set theDoc to active document 
                                    tell theDoc 
                                    repeat 3 times 
                                    set theUnusedSwatches to unused swatches 
                                    repeat with UnusedSwatch from 1 to count of theUnusedSwatches 
                                    if name of (item UnusedSwatch of theUnusedSwatches) is not "" then 
                                    try 
                                    delete (item UnusedSwatch of theUnusedSwatches) 
                                    end try 
                                    end if 
                                    set myParagraphStyles to every paragraph style of theDoc 
                                    set basedOnStyles to based on of paragraph styles 2 thru -1 
                                    set theCount to count of myParagraphStyles 
                                    repeat with n from (count myParagraphStyles) to 2 by -1 
                                    set myCurrentStyle to item n of myParagraphStyles 
                                    if myCurrentStyle is not in basedOnStyles then 
                                    my RemoveUnusedStyle(myCurrentStyle) 
                                    end if 
                                    end repeat 
                                    end repeat 
                                    end repeat 
                                    end tell 
                                    end tell 
                                    on RemoveUnusedStyle(myStyle) 
                                    tell application "Adobe InDesign CS2" 
                                    set find preferences to nothing 
                                    set change preferences to nothing 
                                    set theDoc to active document 
                                    search theDoc with find attributes {applied paragraph style:myStyle} 
                                    tell active document 
                                    set myFoundStyles to search theDoc with find attributes {find text:""} 
                                    if (count myFoundStyles) = 0 then 
                                    try 
                                    delete myStyle 
                                    end try 
                                    end if 
                                    end tell 
                                    end tell 
                                    end RemoveUnusedStyle 
                                    
                                    


                                    I hope the above applescript is being used to remove unused paragraph and character styles and unused swatches in a document. I am in a great need for this script and I am looking forward your great help on this. Please.

                                     

                                    Regards,

                                    Muthuraj. D