Skip to main content
Inspiring
December 14, 2012
질문

Activating object layers basing on document layers

  • December 14, 2012
  • 2 답변들
  • 6809 조회

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;
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;

  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

이 주제는 답변이 닫혔습니다.

2 답변

Marc Autret
Legend
December 15, 2012

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).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.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.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;

            // 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 should work, as we re-access the element per index

            // (from the Graphics coll.)

            // ---

            t = gx.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

Community Expert
December 18, 2012

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

Community Expert
December 18, 2012

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

Uwe

Inspiring
December 14, 2012

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;

  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;

    // 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;

        }

      }

    }

  }

}

Jongware
Community Expert
Community Expert
December 14, 2012

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-layer-options-scripting where I encountered the very same problem.

Marco_Lugli작성자
Inspiring
December 14, 2012

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..