yaksey
yaksey

Reputation: 67

Select, adjust and distribute textframes in InDesign [ExtendScript]

I want to write a script that does the following:

My first problem is, that I only want to select textframes from a unlocked layer. I found several solutions where all textframes, even on locked layers, were selected. And the only solution I found so far that just selects the textframes from my unlocked layer (app.menuActions.item("$ID/Select &All").invoke();) doesn't provide an object I can work with (adjust, distribute) afterwards.

Is there a solution to my requirements?


Edit: My last attempt looked like this (for a single page, I didn't used a loop for several pages while testing):

// 'allPageItems' erfasst alle Rahmen, zusätzlich Gruppen und Bilder 
var allObjects = app.activeDocument.layoutWindows[0].activeSpread.allPageItems; 
// eine Schleife durch die Objekte 
for (var n=0; n<allObjects.length; n++) { 
    var curObject = allObjects[n]; 
    // prüfen, ob Textrahmen 
    if (curObject.constructor.name == "TextFrame") { 
        // verankerte Textrahmen ausschliessen 
        if (curObject.parent != "[object Character]") { 
            // zur Auswahl hinzufügen 
            curObject.select(SelectionOptions.ADD_TO); 
        }   
    } 
} 

Upvotes: 0

Views: 1659

Answers (1)

mdomino
mdomino

Reputation: 1235

Generally, selection is something that is intended for UI interaction, not for scripting. Therefore you should avoid handling all the selection stuff in your script and collect the textFrames as objects in an array that you then can use to do the other stuff.

This should work:

#target indesign

var doc = app.activeDocument;
var curSpread = doc.layoutWindows[0].activeSpread;
var spreadItems = curSpread.allPageItems;

var distObjects = [];

// collect all relevant objects in distObjects
for (var i = 0; i < spreadItems.length; i += 1) {
  var si = spreadItems[i];

  // skip if itemLayer is locked
  if (si.itemLayer.locked) continue;

  // skip if item is not a textFrame
  if (!(si instanceof TextFrame)) continue;

  // skip if item is anchored
  if (si.parent.constructor.name === "Character") continue;

  distObjects.push(si);
};

// group all collected objects to center them, then ungroup
var distGroup = curSpread.groups.add(distObjects);
doc.align([distGroup], AlignOptions.HORIZONTAL_CENTERS, AlignDistributeBounds.SPREAD_BOUNDS);
distGroup.ungroup();

// distribute all objects horizontally
doc.distribute(distObjects, DistributeOptions.HORIZONTAL_CENTERS, AlignDistributeBounds.ITEM_BOUNDS);

Note: If this is used with an older ID version (prior to CC2014 I believe), after ungrouping, all pageItems will stay on the same layer. The feature for them to move back to the original layer was only introduced recently. If you need a solution for an older InDesign version, you would need to calculate the bounds of the group of objects you found, then offset them all one by one, so the entire "selection" can get centered.

Upvotes: 2

Related Questions