How to use app.selection[0] for scripts in Adobe InDesign
Asked Answered
S

2

7

I would like to run code by testing only the current selection (not the whole document) and I'm having difficulty understanding exactly how the array "app.selection" and its methods work. To start, I use a "for" loop to cycle through each item selected by using:

for(loop = 0; loop < app.selection.length; loop++){
    var sel = loop;
}

This works okay, but when I want to get into determining what each item IS, it gets a little weird. For example,

for(txt = 0; txt < app.selection[sel].textFrames.length; txt++){
    // do something to each text frame in the selection here.
}

does not work as expected, but

for(img = 0; img < app.selection[sel].allGraphics.length; img++){
    // do something to each graphic in the selection here
}

seems to work fine, regardless if the selection includes more than just graphics alone, or whether it is inside or outside a group.

At times, it seems like app.selection[0] is the only way to access the item by itself. In other words, if a text frame is selected, app.selection[0] might be the same as app.document.textFrames[0], in which case it would be redundant (and incorrect) to say

app.document.textFrames[0].textFrames[0]

And yet the same concept on different page items works like a charm. It is quite puzzling to follow. Furthermore, it seems impossible to determine what kind of object the item is. I want to say something along the lines of:

if (app.selection[0] == [object TextFrame])

but that does not seem to work for me. Is there a way to clearly test if the current item is a group, a graphic or a text frame and do different things depending on the result?

Stately answered 28/4, 2015 at 1:8 Comment(0)
H
6

app.selection returns an array of Objects, so each item in the array can be of a different type, and the properties and methods available to it will differ. When using the Extendscript Javascript Console you can see what a particular item in the array is on the fly by just typing

app.selection[0]

(or whatever number). The result will be something like [object TextFrame].

While looping through the selection array, you could use app.selection[0].constructor.name to determine the type of each. Or, if you're only interested in certain types,

if (app.selection[i] instanceof TextFrame){}

At that point you'll know more about which properties you can access, depending on the type.

To answer the second part of the question, there isn't an allTextFrames property, but there is an allPageItems property. This returns an array of pageItems (textFrames, groups, etc.), and you can work with it similarly to app.selection. So, if I have three text frames grouped on the first page of my document (and nothing else), I can see that the following are all true:

app.activeDocument.pages[0].textFrames.length == 0;
app.activeDocument.pages[0].allPageItems.length == 4;
app.activeDocument.pages[0].allPageItems[0] instanceof Group;
app.activeDocument.pages[0].allPageItems[1].constructor.name == "TextFrame";

So you could probably cycle through that array if it's more useful to you than the textFrames collection. Just keep in mind that you don't have access to the special collection properties of TextFrames (like everyItem()).

Hydrotherapeutics answered 28/4, 2015 at 16:20 Comment(3)
Excellent response! I have another question regarding all text frames. To update the situation in my question where app.selection.allGraphics[0] acted okay and app.selection.textFrames[0] misbehaved, it seems that it was not a matter of misunderstanding the selection array, (although your answer cleared up the questions I had about it.) allGraphics finds every last graphic available, while textFrames fetches the outermost text frames in a group. Is there an equivalent to allTextFrames?Stately
There isn't an allTextFrames property, at least not in any of the versions of ID that I've worked with (5.5 through CC). There is an allPageItems property. I'll add a note about it.Hydrotherapeutics
Great! Thanks! I've now got a working version thanks to allPageItems.Stately
C
0

App.selection is indeed an array which every item can be accessed by its index:

var sel = app.selection //May be null on no open documents ! An empty array on no selection with an open document. One to n length array in case of selection.

then given that you selected one or several items, you can reach those objects by its index

sel[0] //This returns the first item of the array. Javascript starts counting at zero.

Once that said if you access, say sel[4] and selection count less than 5 items or column 5 is empty, then you get an undefined value. So you need to carefully check for selection item validity before using it and never presume it will return something.

HTH,

Loic http://www.ozalto.com

Charis answered 28/4, 2015 at 8:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.