问题
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?
回答1:
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()).
回答2:
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
来源:https://stackoverflow.com/questions/29908569/how-to-use-app-selection0-for-scripts-in-adobe-indesign