It looks like you are trying to group the items immediately inside top-level layers which are not groups. To quickly get to the issue, your approach here is needing an instrumental overhaul which will make your future work easier and possible.
In Illustrator, there's a document pageItems
collection, as well as the other 'item' collections such as groupItems
. The thing is, when you go document-level, it gives you all the items in all levels of nesting - so your groupItems would get you the groups you want, but also groups you don't want.
What you want to do is go after things in specific containers if you want to do some grouping. In your case you want to go through all the top layers and group immediately-nested items which aren't groups themselves already.
To reference a top-level layer you can use the Document.layers
collection - do not worry as unlike the art-items mentioned above, document.layers
does not return nested layers. Just as a note, Illustrator layers have the ability to have nested sub-layers, and are also accessed via the layer.layers
property.
Now, unlike the document-level art stuff when you do something like var neededGroups = doc.layers[0].groupItems
then you are targeting with your script just the top-level groups in the 1st layer.
Back in the day you used to have to create new groupItems and move
art into them to group art with code. In the later versions they allowed us to use app.executeMenuCommand()
to make grouping a little easier, but it has to rely on the document's current selection. Therefore, first we must ensure nothing is selected in the document.
var doc = app.activeDocument;
doc.selection = null;
You will need to go through your document's layers in an outer loop:
var thisLayer;
for(var i = 0; i < doc.layers.length; i++){
thisLayer = doc.layers[i];
}
During that, you will need to go through the current layer's art in an inner loop (notice the 'i' counter is changed to the 'j' counter to ensure nested loop does not break the parent loop):
var thisPageItem;
for(var j = 0; j < thisLayer.pageItems.length; j++){
thisPageItem = thisLayer.pageItems[j];
}
You will then have to check each item's typename
property to see what kind of item that is. (As far as I know, the .typename
is same result as .constructor.name
property.) The typename
for a group is going to be the string "GroupItem"
. If it's a group then we will avoid it, but for all other ones, we're going to select them.
if(thisPageItem.typename != "GroupItem"){
thisPageItem.selected = true;
}
Now that all non-group items are selected at the bottom of the main loop, use the menu command function. It may be good to ensure that there's a selection with a conditional statement too:
if(doc.selection.length){
app.executeMenuCommand("group");
}
And after it's been grouped - de-select the document for next go-around:
doc.selection = null;
Here is the whole thing put together:
var doc = app.activeDocument;
doc.selection = null;
var thisLayer;
for(var i = 0; i < doc.layers.length; i++){
thisLayer = doc.layers[i];
var thisPageItem;
for(var j = 0; j < thisLayer.pageItems.length; j++){
thisPageItem = thisLayer.pageItems[j];
if(thisPageItem.typename != "GroupItem"){
thisPageItem.selected = true;
}
}
if(doc.selection.length){
app.executeMenuCommand("group");
}
doc.selection = null;
}