• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

[JS] How to add a group in a group ?

Guide ,
Sep 17, 2009 Sep 17, 2009

Copy link to clipboard

Copied

I need to group 2 page-items --say obj1 and obj2-- and to add the result in an existing group --say hostGroup.

Does anybody know why this code doesn't work :

hostGroup.groups.add([obj1,obj2]);

Thanks,

Marc

TOPICS
Scripting

Views

5.0K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 18, 2009 Sep 18, 2009

Copy link to clipboard

Copied

Group doesn't have a method add(), instead it has addPath(). But it doesn't seem to work very well. Suppose you have a page with two groups on it, then this

g = app.documents[0].groups[0];
array = [app.documents[0].groups[1]];
g.addPath (array);

gives you an error message: "Invalid value etc., expected array of page items but received Group". This doesn't look right. When you have one group and two ungrouped items, select those two items, and do this:

g = app.documents[0].groups[0];
array = [app.selection[0], app.selection[1]];
g.addPath (array);

you end up with a compound path (the two items you selected) and your original group, but there's no relation between the group and the compound path.

Peter

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 18, 2009 Sep 18, 2009

Copy link to clipboard

Copied

I now see that I misread your message -- sorry.But it's problematic anyway. The problem appears to be that groups.add() is finicky (and mistaken) about what is and what is not an array. So you'd think that something like this would work:

myDoc.groups.add ([myGroup1, myGroup2])

but it doesn't. Indesign thinks that the parameter in add () is a group while in fact it is an array. The only way I can make it work is to ungroup hostGroup, then create a new group with the groups to be grouped created on the fly as parameters of the group to be created. Apologies for the Pythonesque sentence.This convoluted code works for me:

// get array of page items in hostGroup, then ungroup hostGroup

x = hostGroup.pageItems.everyItem().getElements();

hostGroup.ungroup();

// create array two groups: one is the original hostGroup, the seceonf group consists of obj
array = [app.documents[0].groups.add (x), app.documents[0].groups.add ([obj1, obj2])];
app.documents[0].groups.add (array);

Not a thing of great beauty but it works.

Peter

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Sep 18, 2009 Sep 18, 2009

Copy link to clipboard

Copied

Hi Peter,

Thanks for your comments and suggestions.

So we always need to use ungroup() to extend an existing group? In truth, that's the method my script invokes for the moment, but I don't regard this workaround as a robust solution, because there are recursion issues: if you want to add an object in the group G, then you have to ungroup G and to rebuild the result from the parent. But the parent is not necessary a top-level object (Page/Spread/Document). The group G could be embedded in another group (or page item!), which could be embedded in another one... Thus, we need to ungroup recursively the whole hierarchy until we reach a Page/Spread parent, and to rebuild the same structure so to add finally the new object in the last group. For each step, the procedure needs to store the corresponding page items datas for callback, including the groups we are temporarily destroying!

What I see is that we cannot use the Groups.add() method from any page item, despite that the page item owns a groups property, which is the case of the Group object. The DOM and the documentation are pretty misleading about this. Basically, the Groups.add() method is prototyped to accept for the first argument an array of PageItem, and that's the way I use it in the instruction: hostGroup.groups.add( [obj1, obj2] )

IMHO, the code above should work, unless the DOM restricts explicitly the usage of Groups.add() for top-level parents.

Assuming we have a few page items selected on the active page, there is no problem with the code below:

var objs = app.selection;  // or any page items array
var host = app.activeWindow.activePage;

// create a group on the page:
var newGroup = host.groups.add(objs);

But, if the host is a Group object, the last line fails... The conclusion is that --apparently-- every group that a script needs to create must be created from a top container (Page/Spread/Document). If you want to build a subgroup G2 inside an existing group G1, you must first destroy G1 (ungroup), then create G2 (on the page), then rebuild G1 (on the page) with G2 and the other elements. All of this supposes that G2 is a top-level object, else, welcome to recursion!

Tricky, isn't it?

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Sep 18, 2009 Sep 18, 2009

Copy link to clipboard

Copied

Complete coincidence that I was working on something similar this morning. I posted a new thread on the issue of adding text frames to an inline group. With that under my belt, I thought I'd give this a shot, but I come to the same conclusion that it doesn't work. I made a group on the only page of a new document and then added a couple of text frames to the page and tried this:

var myPage = app.documents[0].pages[0];
var myGroup = myPage.groups[0];
var myTFs = myPage.textFrames.everyItem().getElements();
var myNewTFs = new Array();
for (var j = 0; myTFs.length > j; j++) {
     var myNewTF = myGroup.textFrames.add();
     myNewTF.properties = myTFs.properties;
     myNewTFs.push(myNewTF);
}
myPage.textFrames.everyItem().remove();
myGroup.groups.add(myNewTFs);

The idea being to group the two new items after they were in the group, but it didn't work. The last line gives a bad parameters error.

Dave

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Guide ,
Sep 18, 2009 Sep 18, 2009

Copy link to clipboard

Copied

Hi Dave,

Yep, the groups.add() method sounds like a mirage when you call it from a group.

You can only extend a group by creating a page item at the group level, targeting the appropriate sub-collection:

myGroup.textFrames.add();

But how to add in myGroup an existing TextFrame, or to inject in it a subgroup of various page items?

In some respects, the Group object behaves as a fake container. For instance, you may have notice that if myGroup contains two objects of different types (a Rectangle R and a TextFrame T), then you will have both R.index == 0 and T.index == 0 ! Because, in fact, the index of an object in a group is not the index in the group container, but the index in the corresponding collection in the group container. So R.index is the R-index in myGroup.rectangles (0), and T.index is the T-index in myGroup.textFrames (0).

Anyway, since Group.groups.add doesn't work, let's create this tool.

Here's my first try (the method includes the possibility to add a single PageItem rather than a subgroup):

Group.prototype.addItems = function(/*PageItem[] | PageItem*/ newItems)
//----------------------------
// Emulates Group.groups.add(items) or Group.add(existing_item)
// <newItems> == Array of 2+ PageItem -> create a <newItems> subgroup in <this>
// <newItems> == single PageItem -> add the PageItem in <this>
// Returns the added subgroup or item (the whole group hierarchy is preserved)
// [this method fails if <this> is anchored/embedded in a story]
{
var     nodes=[], gs=[], g=this, node;

var makeNode = function(id,g)
     {
     var elems = g.pageItems.everyItem().getElements();
     if (id === null) // placeholder for newItems
          return {index: elems.length, items:elems.concat(0)};
     for(var i=elems.length-1 ; i>=0 ; i--)

               // need to find the actual index in the group
          if (elems.id == id) break;
     return {index: i, items:elems};
     }

for( var id=null ; g.constructor == Group ; id=g.id, g=g.parent )
     {
     gs.push(g.getElements()[0]);
     nodes.push(makeNode(id,g));
     }

var add = (function()
     {
     var host = g;
     return function(items){return host.groups.add(items);};
     })();

var r = (typeof newItems == 'array' ) ?
     add(newItems) :
     newItems;

while( g=gs.pop() ) g.ungroup();

for( g=r ; node=nodes.shift() ; )
     {
     node.items[node.index] = g;
     g = add(node.items);
     }
return r;
}

Sample usages:

var subGroup = myGroup.addItems(myNewTFs);

or

myGroup.addItems(mySingleTextFrame);

Hope it will help my fellow scripters...

@+

Marc

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 19, 2009 Sep 19, 2009

Copy link to clipboard

Copied

Nice one, Marc! Thanks.

Peter

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jan 31, 2018 Jan 31, 2018

Copy link to clipboard

Copied

https://forums.adobe.com/people/Peter+Kahrel  wrote

… So you'd think that something like this would work:

myDoc.groups.add ([myGroup1, myGroup2])

I know this is a very old thread.

Nevertheless:

myDoc.groups.add ([myGroup1, myGroup2]);

is working. At least with InDesign CS3 and above.

Just tested this. Provided myGroup1 and myGroup2 is on the same spread.

Regards,
Uwe

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Feb 01, 2018 Feb 01, 2018

Copy link to clipboard

Copied

LATEST

And so it does! Thanks, Uwe.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines