8 Replies Latest reply on Dec 21, 2012 2:21 AM by Loic.Aigon

    Activating object layers basing on document layers

    Marco Lugli Level 1

      Hello,

      I have a series of Illustrator files placed on different layers in an Indesign document.

      I would like to set the visibility of the layers contained in the Illustrator files basing on the name of the Indesign layers to which they belong (Eg.: I want to activate only the "ES", "quote", and "disegno" layers in my Illustrator file if this one is on the "ES" layer of my Indesign file).

       

      Here is my first attempt (which gives me an error):

       

      var myDoc = app.activeDocument;
      var totRectangles = myDoc.rectangles;


      for(i=0; i<totRectangles.length; i++){
      var myRectangle = totRectangles[i];
      var myRectangleLevel = myRectangle.itemLayer.name; // the name of the Indesign's layer to which the rectangle belongs

       

      var totGraphics = myRectangle.allGraphics;

       

      for(k=0; k<totGraphics.length; k++){
        var myGraphic = totGraphics[k];

       

        if(myGraphic.imageTypeName == "Adobe PDF"){
         var myGraphicLayers = myGraphic.graphicLayerOptions.graphicLayers; // the layers of the Illustrator file

       

         for(j=0; j<myGraphicLayers.length; j++){
          var myGraphicLayer = myGraphicLayers.item(j).name; // the name of the current Illustrator's layer

       

          if(myRectangleLevel = "ES"){
           switch(myGraphicLayer){
            case "PT":
             myGraphicLayers.item(j).currentVisibility = false;
             break;
            case "ES":
             myGraphicLayers.item(j).currentVisibility = true;
             break;
            case "DE":
             myGraphicLayers.item(j).currentVisibility = false;
             break;
            case "FR":
             myGraphicLayers.item(j).currentVisibility = false;
             break;
            case "EN":
             myGraphicLayers.item(j).currentVisibility = false;
             break;
            case "IT":
             myGraphicLayers.item(j).currentVisibility = false;
             break;
            case "quote":
             myGraphicLayers.item(j).currentVisibility = true;
             break;
            case "Disegno":
             myGraphicLayers.item(j).currentVisibility = true;
             break;
           }
          }
         }
        }
      }
      }

       

      I think the script is someway conceptually correct, but there has to be something wrong, as it doesn't work..

       

      Any help would be much appreciated

       

      Thanks in advance

        • 1. Re: Activating object layers basing on document layers
          Stephen Horne

          I'm not able to test this properly I'm afraid, but this may be of some help to you.

           

           

          var myDoc = app.activeDocument;
          var totRectangles = myDoc.rectangles;
          
          
          var visibleLayers = "Disegno__quote";
          var hiddenLayers  = "PT__DE__FR__EN__IT";
          
          
          for(i=0; i<totRectangles.length; i++){
            var myRectangle = totRectangles[i];
            var myRectangleLevel = myRectangle.itemLayer.name; // the name of the Indesign's layer to which the rectangle belongs
          
          
            var totGraphics = myRectangle.allGraphics;
          
            for(k=0; k<totGraphics.length; k++){
              var myGraphic = totGraphics[k];
          
              // I was getting this error:
              // execution error: Adobe InDesign CS5 got an error: The property is not applicable in the current state.
              // So I put this line in to catch those cases and skip to the next loop iteration.
              // I don't have a document set up to see if this is going to actually work, however.
              try{myGraphic.imageTypeName}catch(e){continue;}
          
              if(myGraphic.imageTypeName == "Adobe PDF"){ // You had a single equals sign here
                var myGraphicLayers = myGraphic.graphicLayerOptions.graphicLayers; // the layers of the Illustrator file
          
          
                for(j=0; j<myGraphicLayers.length; j++){
                  var myGraphicLayer = myGraphicLayers.item(j).name; // the name of the current Illustrator's layer
          
          
                  if(hiddenLayers.match(myGraphicLayer)){
                    myGraphicLayers.item(j).currentVisibility = false;
                  }else if(visibleLayers.match(myGraphicLayer)){
                    myGraphicLayers.item(j).currentVisibility = true;
                  }
                }
              }
            }
          }
          
          
          • 2. Re: Activating object layers basing on document layers
            [Jongware] Most Valuable Participant

            Stephen,

             

            // I was getting this error:

                // execution error: Adobe InDesign CS5 got an error: The property is not applicable in the current state.

             

            This is because it seems InDesign invalidates the reference to the current image and the list of all other images, as soon as you change a layer's visiblity state. You can work around it by not using intermediate variables ...

             

            See my script at http://indesignsecrets.com/forum/indesign-add-ons-scripts-scripting-and-plug-ins/object-la yer-options-scripting where I encountered the very same problem.

            • 3. Re: Activating object layers basing on document layers
              Marco Lugli Level 1

              Hi Jongware, thanks for your support. I tried your script, but it seems that it turns on and off the same image layers on all Indesign layers: what I would like to do instead, is to turn on / off specific image layers depending on the Indesign layer to which they belong (Eg: turn on image layer "ES" on Indesign layer "A"; turn on image layer "EN" on Indesign layer "B"; and so on). I don't know if I was able to let you understand my aim..

              • 4. Re: Activating object layers basing on document layers
                Stephen Horne Level 1

                Hi Jongware, I'm not quite sure that I follow. Do you mean to do this:

                 

                 

                      for(j=0; j<myGraphic.graphicLayerOptions.graphicLayers.length; j++){
                        var myGraphicLayer = myGraphic.graphicLayerOptions.graphicLayers.item(j).name; // the name of the current Illustrator's layer
                
                

                 

                rather than this:

                 

                      for(j=0; j<myGraphicLayers.length; j++){
                        var myGraphicLayer = myGraphicLayers.item(j).name; // the name of the current Illustrator's layer
                
                

                 

                ?

                • 5. Re: Activating object layers basing on document layers
                  Marc Autret Level 4

                  Hi all,

                   

                  I had a similar issue and it totally puzzled me. What I found is that when you change the currentVisibility of a graphicLayer, its specifier becomes instantly invalid! As a matter of fact, it seems that the Graphic container (e.g. myPDF) gets a new id so the whole chain is disabled: myPDF, myPDF.graphicLayerOptions, etc.

                   

                  I have not AI installed at home, so I can't test my theory with actual files. Anyway, I believe this is a very special case where we need to use unresolved specifiers in order to recreate a valid access to the graphic object each time the state of a graphic layer is changed within. In other words, I recommend you do not use resolved arrays (myRectangle.allGraphics). Instead, try to re-access the element by its index from the collection myRectangle.graphics. Using indices rather than ids should work [remainder: a resolved specifier is based on ids.]

                   

                  Of course my code should be refined if you have nested graphics (?) and/or nested graphic layers (?), but in basic situations this may be a good starting point. So, try something like this:

                   

                  // =====================================
                  // YOUR SETTINGS
                  // =====================================
                  var ID_TO_AI_LAYERS = {
                          "ES": ["ES", "quote", "disegno"],
                          "EN": ["EN", "quote", "design"],
                          "FR": ["FR"],
                          /* etc.*/
                          },
                      TARGET_COLLECTION = 'rectangles';
                  
                  // =====================================
                  // SYNCHRONIZE ID<->AI LAYERS
                  // =====================================
                  const EXTRA_CHAR = '\uE080';
                  
                  var items = app.activeDocument[TARGET_COLLECTION],
                      i = items.length,
                      r, gx, j,
                      s, okNames, a,
                      t, j, k, v;
                  
                  while( i-- )
                      {
                      // Name of the ID layer the current rectangle (r) belongs to
                      // ---
                      s = (r=items[i]).itemLayer.name;
                  
                      // Make sure that this layer is supported
                      // ---
                      if(! ID_TO_AI_LAYERS.hasOwnProperty(s) ) continue;
                  
                      // Store the allowed AI layer names in a String (okNames)
                      // ---
                      okNames = EXTRA_CHAR + ID_TO_AI_LAYERS[s].join(EXTRA_CHAR) + EXTRA_CHAR;
                  
                      // Consider only the direct graphic children of the current rectangle
                      // (We need unresolved specifiers here => gx remains a collection.)
                      // ---
                      gx = r.graphics;
                      j = gx.length;
                      while( j-- )
                          {
                          // Temporarily resolve the underlying graphic object (--> PDF)...
                          // ---
                          t = gx[j].getElements()[0];
                  
                          // ...in order to check whether t has graphic layers
                          // ---
                          if( !('graphicLayerOptions' in t) ) continue;
                  
                          // Consider the names of the contained graphic layers
                          // ---
                          a = t.graphicLayerOptions.graphicLayers.everyItem().name;
                          k = a.length;
                          while( k-- )
                              {
                              s = a[k];
                  
                              // Depending on a graphic layer name, do we want to show or hide it?
                              // ---
                              v = 0 <= okNames.indexOf(EXTRA_CHAR + s + EXTRA_CHAR);
                  
                              // Now, the problem is to point out to the graphic layer although
                              // the parent graphic specifier may not be valid anymore!
                              // But gx[j] should work, as we re-access the element per index
                              // (from the Graphics coll.)
                              // ---
                              t = gx[j].graphicLayerOptions.graphicLayers.itemByName(s);
                  
                              // Hit the DOM *only* if a change is possible AND required
                              // ---
                              ( ! t.isValid ) ||
                              ( t.currentVisibility === v ) ||
                              ( t.currentVisibility = v );
                              }
                          }
                      }
                  

                   

                  Note: turning enabledRedraw off is highly recommended during the process!

                   

                  Hope that helps.

                   

                  @+

                  Marc

                  • 6. Re: Activating object layers basing on document layers
                    Laubender Adobe Community Professional & MVP

                    Marc Autret wrote:

                    I have not AI installed at home, so I can't test my theory with actual files.

                     

                    @Marc – I just checked with a sample Illustrator file placed in InDesign.
                    And I must say: you are absolutely right!

                     

                    After changing the visibility of some of the graphic layers, the id of the placed graphic changed.

                     

                    Good to know!!

                     

                    Uwe

                    • 7. Re: Activating object layers basing on document layers
                      Laubender Adobe Community Professional & MVP

                      Fortunately the links id of the placed AI file does NOT change in the process…

                       

                      Uwe

                      • 8. Re: Activating object layers basing on document layers
                        Loic.Aigon Adobe Community Professional

                        Hi all,

                         

                        I wanted to make a blog post a few months ago as I was facing that exact same issue for a AI/ID script workflow. Once I changed layer visibility, the reference vanished. I had to redefine my variable every time in the loop to get it working.

                         

                        Loic