Thread View: adobe.scripting.indesign
20 messages
20 total messages
Started by Ben_J.D
Fri, 02 Jan 2009 02:05
[JS] :: [CSX] - PageItem Stacking Order
Author: Ben_J.D
Date: Fri, 02 Jan 2009 02:05
Date: Fri, 02 Jan 2009 02:05
27 lines
1960 bytes
1960 bytes
Hi folks,
Does any one here have any knowledge and or experience on how indesign handles the stacking order of page items.
I have a simple script which looks like this:
//----------------------------------------------------
//-----Loop through each page then each page item
//----------------------------------------------------
var currentDocument = app.open(File("/c/sample.indd"), false);
var docPages = currentDocument.pages;
var docPageItems;
//Every Page
for(var pagesKey=0;pagesKey<docPages.length;pagesKey++) { docPageItems = docPages[pagesKey].pageItems;
//Every Item of Every page
for(var itemKey=0;itemKey<docPageItems.length;itemKey++) { alert( "index = "+docPageItems[itemKey].index+", color = "+docPageItems[itemKey].fillColor.name+", id = "+docPageItems[itemKey].id ); } } //----------------------------------------------------
The indesign file I am opening can be downloaded here:
<http://home.exetel.com.au/thunder/img/sample> Folder.zip
I am trying to use the index property of pageItem to determine the proper stacking order--I am trying to sort the page Items from top down.
In This example inDesign reports that the object 'little circle' is underneath 'big Circle' and the index numbers in general do not seem to match how I have placed the objects on top of each other in the document.
Is this the correct way to determine stacking order?
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Peter Kahrel
Date: Fri, 02 Jan 2009 08:30
Date: Fri, 02 Jan 2009 08:30
3 lines
1099 bytes
1099 bytes
Indexes indicate the stacking order of objects, but only of objects of the same type. You have two types of object on your page, three Ovals and two Rectangles. The Ovals have indexes 0, 1, and 2, the Rectangles, 0 and 1. On pages with objects of mixed types it is therefore not possible (or not straightforward anyway) to determine those objects' stacking order. (An object's id doesn't change when you send it to the front or back, so that doesn't tell you anything about stacking order.) Peter
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Ben_J.D
Date: Sun, 04 Jan 2009 07:02
Date: Sun, 04 Jan 2009 07:02
6 lines
1179 bytes
1179 bytes
Thank you for your reply Peter, Your message helped me understand how indesign assigns indicies to PageItems and why I cant use them to determine a stacking order. (Unless they are all the same type of object). Can you think of any other ways this might be done or any scripts out there that are already doing this? I thought if I could add all of my page items to groups and therefore bring them all into the same type this would produce an accurate stacking order. But the groups I make do not stay in the same order and find myself back to square one. Thanks again for your reply. Ben
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Ben_J.D
Date: Sun, 04 Jan 2009 12:16
Date: Sun, 04 Jan 2009 12:16
6 lines
1310 bytes
1310 bytes
I had another go with my grouping strategy and came up with a solution that works. I have uploaded a new modified version of my script here: <http://home.exetel.com.au/thunder/img/simpleScript2.js> Basically I create a bunch of empty text frames and group them to all of the individual page items, this creates a new set of page items who are all of the same type 'Group' and therefore share unique indicies which represent their stacking order. This script could surely by improved and optimized. This method seems entirely over the top for something that should be very simple. I am open to better suggestions.
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Peter Kahrel
Date: Sun, 04 Jan 2009 14:43
Date: Sun, 04 Jan 2009 14:43
23 lines
1419 bytes
1419 bytes
Ben,
What a great idea: duplicate pageItems and group the original and the duplicate so that all page items are of the same type. But you're making things very complicated. Your brilliant idea can be scripted simply as follows: on each page, duplicate each page item and group it with its original. Label the duplicates so that you can delete them easily later on:
doc = app.activeDocument;
for (i = 0; i < doc.pages.length; i++)
{
p_items = doc.pages[i].allPageItems;
for (j = 0; j < p_items.length; j++)
{
dupl = p_items[j].duplicate();
doc.pages[i].groups.add ([dupl, p_items[j]]);
}
}
Afterwards these two lines ungroup everything and delete the duplicates:
doc.groups.everyItem().ungroup();
doc.pageItems.item ('duplicate').remove()
Peter
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Robert Tkaczyk
Date: Sun, 04 Jan 2009 15:02
Date: Sun, 04 Jan 2009 15:02
9 lines
1093 bytes
1093 bytes
Peter, unless you don't have other groups you don't want to ungroup ;) I think all new temp groups should be labeled and only these groups should be ungrouped robin -- www.adobescripts.com
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Peter Kahrel
Date: Sun, 04 Jan 2009 15:29
Date: Sun, 04 Jan 2009 15:29
23 lines
999 bytes
999 bytes
I think all new temp groups should be labeled and only these groups should
be ungrouped
Good point. The line that creates the groups should then be
doc.pages[i].groups.add ([dupl, p_items[j]], {label: 'dupl_group'});
and the line that ungroups should then be
doc.groups.item('dupl_group').ungroup();
Peter
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Robert Tkaczyk
Date: Sun, 04 Jan 2009 15:31
Date: Sun, 04 Jan 2009 15:31
9 lines
1129 bytes
1129 bytes
in VBS - after grouping selected items - order is from top to bottom so - I think there is no need to play with duplicates ... just group, read order of elements in group and ungroup of course - this is OK ONLY for items from same layer in case of few layers - this need to be done for each layer robin -- www.adobescripts.com
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Peter Kahrel
Date: Mon, 05 Jan 2009 10:41
Date: Mon, 05 Jan 2009 10:41
12 lines
1040 bytes
1040 bytes
Robin,
in VBS - after grouping selected items - order is from top to bottom
That's the case in JS, too. But the moment you ungroup, each object type gets its own range of indexes again. Maybe Ben can do what he wants to do while the objects are grouped.
You're right that layers are another consideration. Anyway, all I wanted to point out to Ben was that what he tried to achieve needn't be that complicated.
Peter
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Robert Tkaczyk
Date: Mon, 05 Jan 2009 19:13
Date: Mon, 05 Jan 2009 19:13
9 lines
1051 bytes
1051 bytes
Peter, I know that your solution is faster and simpler ;) and I know that all objects back to ID-order after ungrouping - but when objects are temp group - order of IDs could be stored in array for later use robin -- www.adobescripts.com
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Ben_J.D
Date: Tue, 06 Jan 2009 06:44
Date: Tue, 06 Jan 2009 06:44
4 lines
1085 bytes
1085 bytes
Wow thanks Peter for your optimized/improved script that makes things a lot more elegant and efficient. Thank you Robin for your insight also. In my project I can work with the page Items while they are grouped and ungroup them all at the end. Different layer constructs do not concern me for this project only different pages. Cheers Ben
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Harbs
Date: Tue, 06 Jan 2009 08:45
Date: Tue, 06 Jan 2009 08:45
19 lines
1219 bytes
1219 bytes
Hi guys,
Unless I'm missing something obvious, this technique should work for getting the stacking order of objects (without duplicating, etc.):
1) var items = page.pageItems.everyItem().getElements().slice(0) (to get an array of all top level page items.)
2) for each item you'd find the index in the items array. Here's a function I use:
function GetItemIndex(array,item){
for(var i=0;i<array.length;i++){
if(array[i] == item){return i}
}
return null;
}
3) then you just compare the indexes.
Harbs
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Peter Kahrel
Date: Tue, 06 Jan 2009 10:30
Date: Tue, 06 Jan 2009 10:30
6 lines
792 bytes
792 bytes
Hi Harbs, The rest of us were missing something obvious! You make it look so easy :) But as a matter of interest, what's the ".slice(0)" doing there at the end of the first line? Peter
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Ben_J.D
Date: Tue, 06 Jan 2009 10:50
Date: Tue, 06 Jan 2009 10:50
3 lines
754 bytes
754 bytes
Oh I get it--the pageItems Array is already in the right order and we should use the array's index not the index property ... Nice one Harbs!
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Harbs
Date: Tue, 06 Jan 2009 19:23
Date: Tue, 06 Jan 2009 19:23
22 lines
1581 bytes
1581 bytes
Peter Kahrel wrote:
> But as a matter of interest, what's the ".slice(0)" doing there at the end of the first line?
>
I'm not sure if it really makes a difference in this case (I've never
bothered to check), but here's an article written by Kris Coppieters
which explains the idea behind it...
http://www.niemannross.com/developer/wiki/index.php?title=Avoiding_slowness_with_object_arrays
FWIW, I use this function to get an array when I deal with a large
number of objects and I don't specifically need a dynamic collection
over an array. I don't need to worry about whether I'm starting out with
an array or a collection and the difference in performance is tremendous:
function AsArray(collection){
if(collection instanceof Array){return collection.slice(0)}
return collection.everyItem().getElements().slice(0);
}
--
Harbs
http://www.in-tools.com
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Robert Tkaczyk
Date: Tue, 06 Jan 2009 21:16
Date: Tue, 06 Jan 2009 21:16
8 lines
1034 bytes
1034 bytes
Harbs, the same way we can check order of selected objects in older versions of ID - but this was removed in CS3 and this misleaded me ;) robin -- www.adobescripts.com
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Harbs
Date: Tue, 06 Jan 2009 23:13
Date: Tue, 06 Jan 2009 23:13
15 lines
1292 bytes
1292 bytes
Peter, Your question finally prompted me to do some timing tests: I created 400 text frames for testing purposes. Accessing pageItems to check if they were text frames took about 20 times as long when they were collections than with everyItem().getElements(). adding the "slice(0)" cut the time by about a third. So slice(0) doesn't make a very big difference in this case, but it does make a difference... -- Harbs http://www.in-tools.com
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Peter Kahrel
Date: Wed, 07 Jan 2009 09:49
Date: Wed, 07 Jan 2009 09:49
56 lines
3441 bytes
3441 bytes
Harbs.
I knew that arrays process much quicker than collections, but didn't know that .slice(0) sped up things even more -- thanks very much for the pointer. But I can't reproduce that. I did a test similar to yours (a document with 400 pages, a text frame on each page, then tested if each object was a text frame), and it turned out that adding .everyItem().getElements() reduced the script's running time by a factor 20, which is what you found, too, but then adding .slice(0) didn't matter at all (see timings below). Maybe any fractional advantage in processing the array is cancelled by the overhead created by .slice(). So it looks as if Kris is not entirely correct when he says
The '.slice(0)' is there to force a duplication of the array. If it were omitted, InDesign would merely copy a reference to theRealm.allPageItems, and we'd be no better off.
Maybe the differences are due to the type of test (.slice(0) may have a distinct advantage on longer/shorter arrays) or type of computer (you can measure the difference, I can't). Interestingly, Kris adds another optimalisation by assigning the array's length to a variable:
var realmItems = theRealm.allPageItems.slice(0);
var realmLength = realmItems.length;
for (var idx = 0; idx < realmLength; idx++)
This has long been known to speed up array-processing, but again its effect turns out to depend on the type of test and computer. The speed tests show that collections benefit, but arrays don't always. On my PC, assigning array length to a variable and using that in the loop doesn't make any difference, but on an older computer that I used previously, which was much slower (0.8 vs 3.2 GHz), it did make a big difference: it halved an 'array-intensive' script's running time.
Anyway, here are some timings. 400-page document, text frame on each page, document has no undo-stack. Timings are highest and lowest of ten runs. Time differences such as 0.14 vs. 0.12 can be considered meaningless.
Peter
3.6-3.7 (seconds)
t = app.activeDocument.textFrames;
for (i = 0; i < t.length; i++)
if (t[i] instanceof TextFrame) {}
0.06-0.11
t = app.activeDocument.textFrames.everyItem().getElements();
0.06-0.14
t = app.activeDocument.textFrames.everyItem().getElements().slice(0);
2.5-2.6
t = app.activeDocument.textFrames;
t_length = t.length;
for (i = 0; i < t_length; i++)
if (t[i] instanceof TextFrame) {}
0.06-0.14
t = app.activeDocument.textFrames.everyItem().getElements();
0.06-0.12
t = app.activeDocument.textFrames.everyItem().getElements().slice(0);
PS: there have been claims that there might be a speed difference between 'x instance of y' and 'x.constructor.name == "y"', but that's not borne out by repeating the above tests using constructor.name.
P.
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Harbs
Date: Wed, 07 Jan 2009 11:45
Date: Wed, 07 Jan 2009 11:45
11 lines
1090 bytes
1090 bytes
Hi Peter, Yes, you are correct. I was looking at the timing data in the ESTK, and I forgot to take the overhead of slice(0) into account. Without doing further testing, it looks like slice(0) doesn't hurt but it doesn't help either (for arrays created by getElements() ). -- Harbs http://www.in-tools.com
Re: [JS] :: [CSX] - PageItem Stacking Order
Author: Harbs
Date: Wed, 07 Jan 2009 13:42
Date: Wed, 07 Jan 2009 13:42
6 lines
933 bytes
933 bytes
I just realized that I did the tests on CS4. I wonder if CS/CS2/CS3 will give different results... -- Harbs http://www.in-tools.com
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads