Copy link to clipboard
Copied
Use getElements() to convert the collection into an array, then use this sort function, like so:
var myStories = app.activeDocument.stories.everyItem().getElements();
myStories.sort(function(a,b) {
return a.textContainers[0].parentPage.documentOffset < b.textContainers[0].parentPage.documentOffset;
});
Copy link to clipboard
Copied
Use getElements() to convert the collection into an array, then use this sort function, like so:
var myStories = app.activeDocument.stories.everyItem().getElements();
myStories.sort(function(a,b) {
return a.textContainers[0].parentPage.documentOffset < b.textContainers[0].parentPage.documentOffset;
});
Copy link to clipboard
Copied
Thank you~ haven't had a chance to do much testing yet but that appears to do it. In limited testing, I changed to > rather than a < in the sort. Using <, the story on the last page came up first.
Copy link to clipboard
Copied
Without wanting to criticize my colleagues, I strongly discourage the proposed solution (which anyway seems problematic in other respects), simply because commands such that
a.textContainers[0].parentPage.documentOffset
within a custom sort function will explode the Scripting DOM as soon as the document contains a huge number of stories. In ExtendScript, a custom sort involves on average 5×N×Log(N) internal calls of the function.
Note. - You should also take care of possible runtime errors (e.g. parentPage may be null, etc) and other issues (what about master pages?)
As usual, the solution I suggest is based on generating safe UTF16 sort keys through one linear loop, calling the native Array.prototype.sort() and building the desired array. Safer and probably much faster with long documents.
Here is a quick implementation [not tested in depth but you get the idea]
function sortedStories(/*Document*/doc, K,ev,r,a,i,t)
{
// Init.
const CHR = String.fromCharCode;
K=doc.stories, ev=K.everyItem(), r=ev.id, a=ev.textContainers;
// Make sort keys -> r[i] :: <key> + storyId
for
(
i=r.length ; i-- ;
// ---
(t=a[i]).length // Have we a container?
&& (t=t[0].parentPage) // Have we a parent page?
&& 'Spread'===t.parent.constructor.name // Skip master pages!
? ( r[i]=CHR(1+t.documentOffset)+r[i] ) // Make 1st char sortable, add the ID.
: r.splice(i,1)
);
// Instant sort.
r.sort();
// Build array of sorted stories and return.
for( i=r.length ; i-- ; r[i]=K.itemByID(parseInt(r[i].slice(1),10)) );
return r;
};
var myStories = sortedStories(app.activeDocument);
// etc
[EDIT] Still, this is certainly not the optimal way to reach the goal, but I wanted to illustrate my point while keeping the textContainers[0].parentPage.documentOffset approach proposed by @brian_p_dts
Best,
Marc
Copy link to clipboard
Copied
Hi @Marc Autret
Appreciate the refined approach and additional insight. I was aware of issue related to null parentPages and stories in parent spreads; it was definitely a quick and dirty solution that could throw errors that the user then could explore how to work through as part of their learning journey.
Really interesting approach with stringifying the sort values by offset / IDs and reconstructing the array. Thanks for your insights as always!
Copy link to clipboard
Copied
Alternatively you can iterate the pages collection and each page has a textframes collection so you can get the story from the textframes.
-Manan
Copy link to clipboard
Copied
Alternatively you can iterate the pages collection and each page has a textframes collection so you can get the story from the textframes.
-Manan
By @Manan Joshi
But OP wants order for the whole document - not for the current page?
Copy link to clipboard
Copied
Hi Robert, Manan was talking about iterating through the whole page collection. Probably is a faster approach than what I proposed in a longer doc too.
Copy link to clipboard
Copied
But that's not what OP wants?
OP wants order of the stories in the document by pages - not on a specific single page.
Copy link to clipboard
Copied
I did not get you @Robert at ID-Tasker we would iterate story of each page is what I suggested.
-Manan
Copy link to clipboard
Copied
I did not get you @Robert at ID-Tasker we would iterate story of each page is what I suggested.
-Manan
By @Manan Joshi
But Stories are per Document - not per Page - so you would be analysing the same Stories over and over again.
And OP wants order of the Stories in the Document - not on any particular Page.
Copy link to clipboard
Copied
They want to iterate stories in page order. So if I iterate the pages and check the stories on it and ignore the story already encountered before like linked frames spanning pages then what would I be missing?
-Manan
Copy link to clipboard
Copied
Something like the following should work
function getStoriesInPageOrder() {
var uniqueStories = {};
var orderedStories = [];
var doc = app.activeDocument;
for (var i = 0; i < doc.pages.length; i++) {
var page = doc.pages[i];
for (var j = 0; j < page.textFrames.length; j++) {
var textFrame = page.textFrames[j];
if (textFrame.isValid && textFrame.parentStory.isValid) {
var storyId = textFrame.parentStory.id;
if (!uniqueStories[storyId]) {
uniqueStories[storyId] = true;
orderedStories.push(textFrame.parentStory);
}
}
}
}
return orderedStories;
}
var stories = getStoriesInPageOrder();
for (var s = 0; s < stories.length; s++) {
$.writeln("Story " + (s + 1) + ": " + stories[s].contents);
}
-Manan
Copy link to clipboard
Copied
But in this code you are processing same Stories over and over again?
Let's say you have 100 pages and 2 Stories and 10 frames per page - 5 frames of each Story on each Page...
Copy link to clipboard
Copied
It is just looping over the frames and checking by id if the story is already accounted for or not. if it is accounted, we ignore it and if not then we add the story to our collection. How fast/slow the approach will be can be know after testing it. I thought you mentioned that the idea is not workable but it seems workable to me, how fast it will be is something that can be tested.
-Manan
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Then maybe I misunderstood. Anyhow we have an alternative approach in the open now it is for the users to try and choose the one that suits them
-Manan