6 Replies Latest reply on Jan 6, 2017 10:01 AM by williamadowling

    Repeating Function dependent on number of items selected

    Babymac08 Level 1

      I'm building a script that will allow me to Open a .pdf and copy it's contents and layers into another existing document (template) I have set up... I want to be able to center these on the document (template) I have but depending on the .pdf file there could be 1 layer up to 3 or more... so I want the function to repeat until all layers have been centered. The script I've posted below will handle two layers, but in the even a second layer is not present or more than 2 are... I need the function to behave correctly... I know I'm missing a simple step somewhere, but not sure what... Thanks in advance for any assistance.

       

      //Center Placed Image on Artboard
      var aDoc = app.activeDocument;  
      app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;  
      var abIdx = aDoc.artboards.getActiveArtboardIndex();  
      var actAbBds = aDoc.artboards[abIdx].artboardRect;  
      var obj2move = aDoc.selection[0];
      obj2move.position = new Array ((actAbBds[2]-actAbBds[0])/2 - obj2move.width/2, (actAbBds[3]-actAbBds[1])/2  + obj2move.height/2);
      var obj2move = aDoc.selection[1];
      obj2move.position = new Array ((actAbBds[2]-actAbBds[0])/2 - obj2move.width/2, (actAbBds[3]-actAbBds[1])/2  + obj2move.height/2);
      
        • 1. Re: Repeating Function dependent on number of items selected
          Silly-V Adobe Community Professional

          You have to make use of javascript loops.
          I'm sure you've used them before, now it's time to write one for the purpose of iterating through your selection.

           

          for(var i=0; i<aDoc.selection.length; i++){

               alert(aDoc.selection[i]);

          };

           

          also you do not have to do the 'var' keyword again after you've done it the 1st time with var obj2move.

          You can do this:

           

          var obj2move;

          for(var i=0; i<aDoc.selection.length; i++){

               obj2move = aDoc.selection[i];

          };

           

          also it's good to put long things, duplicated code lines into a variable. Let's try to do the whole thing now

           

          var obj2move;

          var newPos = new Array ((actAbBds[2]-actAbBds[0])/2 - obj2move.width/2, (actAbBds[3]-actAbBds[1])/2  + obj2move.height/2);

          for(var i=0; i<aDoc.selection.length; i++){

               obj2move = aDoc.selection[i];

               obj2move.position = newPos;

          };

          • 2. Re: Repeating Function dependent on number of items selected
            williamadowling Level 4

            Someone may disagree with me, but in my opinion, you're making it more complicated than it needs to be.

             

            First, let's look at fixing up the code you have currently.

             

            Instead of hardcoding the indexes of aDoc.selection, you can run a loop to execute some code to each existing selected item. When you hard code things as you've done in the snippet you posted, you run the risk of a runtime error if something doesn't exist. You've identified this issue yourself when you pointed out that the code you have currently won't work properly if there's only one item in your selection. So, let's take a look at that necessary loop.

             

            function container()
            {
                var aDoc = app.activeDocument;
                var artboards = aDoc.artboards;
                app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
                var abIdx = artboards.getActiveArtboardIndex();
                var actAbBds = artboards[abIdx].artboardRect;
            
                var sel = aDoc.selection;
            
                //begin loop
                for(var a=0 ; a<sel.length ; a++)
                {
                    //here we're declaring the variable obj2move and setting it equal to
                    //the index "a" of the current selection.
                    //This way, the code will repeat until you've processed all of the selected items
                    //whether the number of selected items is 1, or 100, or more.
                    var obj2move = sel[a];
                    obj2move.position = new Array ((actAbBds[2]-actAbBds[0])/2 - obj2move.width/2, (actAbBds[3]-actAbBds[1])/2  + obj2move.height/2);
                }
            
            }
            container();
            

             

            When you can, you should try to avoid embedding calculations in an argument like you do in your "new Array" constructor. It's easier to read, fix and debug if you save those calculations into variables, like so:

             

            function container()
            {
                var aDoc = app.activeDocument;
                var artboards = aDoc.artboards;
                app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
                var abIdx = artboards.getActiveArtboardIndex();
                var actAbBds = artboards[abIdx].artboardRect;
            
                var hCenter = (actAbBds[2] - actAbBds[0]) / 2;
                var vCenter = (actAbBds[3] - actAbBds[1]) / 2;
            
                var sel = aDoc.selection;
            
                //begin loop
                for(var a=0 ; a<sel.length ; a++)
                {
                    var obj2move = sel[a];
                    var halfW = obj2move.width/2;
                    var halfH = obj2move.height/2;
            
                    var x = hCenter - halfW;
                    var y = vCenter + halfH;
            
                    //you'll also notice that i dropped the Array constructor syntax in favor
                    //of the 'array literal' syntax. I've been taught in school recently that this
                    //method is preferred and agreed to be the 'standard', though both approaches
                    //will work equally as well. 
                    obj2move.position = [x,y];
                }
            
            }
            container();
            

             

            This way, if you see a problem with the vertical centering for instance, it's easier to look specifically at the parts of the code that relate specifically to the vertical centering and ignore the horizontal or vice versa. Not to mention, if you decide you need to access those same values later, you'll have variables accessible to use so you don't have to re-type the equation again.

            • 3. Re: Repeating Function dependent on number of items selected
              Babymac08 Level 1

              Silly-V & williamadowling

              First off thanks so much for the quick response and the ability to see two different option... I like how William suggested to break down the equations, and the foresight of thinking through trouble shooting is a great suggestion...

               

              Thanks again for your help

              • 4. Re: Repeating Function dependent on number of items selected
                williamadowling Level 4

                i've learned the hard way far too many times that  if you wait until later to think about how you might troubleshoot an issue, you're going to be in a lot of trouble. especially when you start writing veritable programs rather than errant functions here and there.

                 

                For my company i've written something like 50 different "scripts" (some of them are essentially full fledged programs with 10's of thousands of lines of code meant to handle hundreds of different tasks each with it's own rules for art placement and blah blah blah) to do a wide variety of different things and as time goes on, they get more and more complicated in an attempt to account for the seemingly endless variations that the files i'm scripting might include. It's a difficult thing to tell a computer all the different ways it might need to process a file that was generated by one of 100 different people who all have their own way of creating files. I'm not attempting to brag here, in fact, i still run into problems dealing with this issue on a daily basis. I'm just trying to point out that things get very complex very quickly and it ALWAYS behooves you to take a breath before you begin (and periodically throughout writing your script) to consider what could possibly go wrong and how you can minimize the risk while maximizing your ability to find and fix the issue quickly and easily.

                 

                Good luck! And keep up the great work. You're coming along much faster than I did when I started doing this stuff. =)

                • 5. Re: Repeating Function dependent on number of items selected
                  Babymac08 Level 1

                  ok williamadowling Your script ran perfectly when I ran it by itself... but Now I'm trying to add it to my script and I'm getting an error on line 18 (var aDoc = app.activeDocument;). The front part of my script is still being tweaked. The reason I wrote this is because I was having trouble when placing .pdf's with layers that it was placing them as a single layer object. So I'm having it open the .pdf file directly in Illustrator rather than importing and my layers are in tact... so I'm Selecting All and copy to my template with the "Paste Remember Layers" option checked in my layer pallet... Works perfectly... but is stopping at the active document... Eventually I'll script the line 8 (var mFile = File('~/Desktop/126370-3 - Bun Warmer Patch.pdf') to look in my hot folder for files.

                   

                  THanks for looking my script over and offering suggestion on how to get past the error...

                   

                  //Open template File

                  var theFile = File('~/Desktop/Illustrator Hot Folder/11 x 8.5 Proof Sticker/ai_file/Proof Sticker 11 x 8.5.ait');

                  app.open(theFile);

                   

                   

                  //Fit artboard To window

                  app.executeMenuCommand ('fitall');

                   

                   

                  var mFile = File('~/Desktop/126370-3 - Bun Warmer Patch.pdf');

                  app.open(mFile);

                  app.executeMenuCommand('selectall');

                  app.executeMenuCommand('copy');

                  app.executeMenuCommand('close');

                  app.executeMenuCommand('paste');

                   

                   

                  // Center Selections on Artboard

                  function container()

                  {

                      var aDoc = app.activeDocument;

                      var artboards = aDoc.artboards;

                      app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;

                      var abIdx = artboards.getActiveArtboardIndex();

                      var actAbBds = artboards[abIdx].artboardRect;

                   

                   

                      var hCenter = (actAbBds[2] - actAbBds[0]) / 2;

                      var vCenter = (actAbBds[3] - actAbBds[1]) / 2;

                   

                   

                      var sel = aDoc.selection;

                   

                   

                      //begin loop

                      for(var a=0 ; a<sel.length ; a++)

                      {

                          var obj2move = sel[a];

                          var halfW = obj2move.width/2;

                          var halfH = obj2move.height/2;

                   

                   

                          var x = hCenter - halfW;

                          var y = vCenter + halfH;

                   

                   

                          obj2move.position = [x,y];

                      }

                   

                   

                  }

                  container();

                  • 6. Re: Repeating Function dependent on number of items selected
                    williamadowling Level 4

                    Herein lies the danger with piecing together scripts from different places. Variables can often be conflicting and redundant etc. At first glance I can't quite see what would be going wrong. By the time the "container" function executes, there should be 1 document open ("Proof Sticker 11x 8.5.ait"). So that document should be the activeDocument and you shouldn't have any trouble..

                     

                    Try moving this line:

                    var aDoc = app.activeDocument;

                     

                    just below this line:

                    app.open(theFile)

                     

                    That will preemptively set Proof Sticker 11x 8.5.ait as the activeDocument. The only thing i can think of is that the script is moving faster than the application and it's trying to set "aDoc" while mFile is closing or something like that... idk.