Saturday, June 02, 2007
More Edit Original
Let's replace that alert in the main function with some code that does something useful. First, let's just mimic what the Edit Original command does by simply opening the original document. To find that document, we use the itemLink property. So:
But of course, this was the easy part—so easy that one wonders why it isn't built into the application, but had it been, we wouldn't be having all this fun! Now the challenge is to try to integrate (a version of) our script into the Edit Original event handler. We don't want to take over the whole event because we only handle imported pages. We want to somehow pass control back to the application to handle all the other kinds of graphic.
At the moment, I'm going on blind faith that this must be possible. It might be a few days before I can get back to this because I'm in New York at the InDesign Conference this coming week and I have to finalize my preparations. Meanwhile, I've added a link to the current state of this script in the downloads list. [Life intervened and I've not yet added that link.]
function editOriginalIDPage(sel) {Well, that was easy. But what we really want to do is turn to the page that contains the imported page. Well, that information is available in the object's pageNumber property (which counts from 1 -- grrr):
var myImpPage = getImpPage(sel);
if (myImpPage == null) return;
var myLink = myImpPage.itemLink;
app.open(File(myLink.filePath))
...
function editOriginalIDPage(sel) {And that does the job.
var myImpPage = getImpPage(sel);
if (myImpPage == null) return;
var myPgNum = myImpPage.pageNumber;
var myLink = myImpPage.itemLink;
var newDoc = app.open(File(myLink.filePath))
app.activeWindow.activePage = newDoc.pages[myPgNum - 1];
app.activeWindow.zoom(ZoomOptions.fitPage);
...
But of course, this was the easy part—so easy that one wonders why it isn't built into the application, but had it been, we wouldn't be having all this fun! Now the challenge is to try to integrate (a version of) our script into the Edit Original event handler. We don't want to take over the whole event because we only handle imported pages. We want to somehow pass control back to the application to handle all the other kinds of graphic.
At the moment, I'm going on blind faith that this must be possible. It might be a few days before I can get back to this because I'm in New York at the InDesign Conference this coming week and I have to finalize my preparations. Meanwhile, I've added a link to the current state of this script in the downloads list. [Life intervened and I've not yet added that link.]
Edit Original Continued
It turns out that there is a naming bug in the object model. There is a collection object for importedPages but it has the unfortunate name IndesignPageItems. I had noticed that in the object model viewer (in ESTK 2, choose Adobe InDesign CS3 Object Model from the Help menu) but didn't recognize what it was.
So this raises the question, how to write code that uses this that doesn't get broken when they fix the name? How's this:
Dave
So this raises the question, how to write code that uses this that doesn't get broken when they fix the name? How's this:
function getImpPage(obj) {Yes! That works.
if (obj.constructor.name == "ImportedPage") return obj;
try {
return (obj.hasOwnProperty("importedPages") ? obj.importedPages[0] : obj.indesignPageItems[0]);
} catch(e) {
return null;
}
} // end of getImpPage
Dave
Friday, June 01, 2007
Edit Original for Placed Pages
Once again, I have used the making of a booklet as a proof of concept for a script of a new version of InDesign. Two releases ago, my BuildBooklet.js (as it was then) filled a gap in the InDesign CS feature set by making it possible to create booklets from documents; the only proviso was that the documents had to have a page count that was exactly a multiple of four. I based the script on a concept I'd heard about from Shane Stanley and used it to learn about managing sections in InDesign documents. I had no expectations that others would find this script useful.
But it took off. And even after InBooklet was added to InDesign (first to CS via the terribly-named PageMaker Plug-ins and then as part of CS2), some people advocated using my script because it was so simple to use. Well, here we are with CS3 and I've done it again. This time, I've called the script MakeBooklet.jsxbin. I've published it as a binary to emphasize that it works only with CS3. Unlike its predecessor, this script creates a new double-sized, single-sided document, placing the contents of the pages of the original document side-by-side in printer spread order.
The ability to place pages from one document to another is new in InDesign CS3 and that opens up all kinds of possibilities for scripts to perform these kinds of imposition tasks. If you'd like to try the script, I've put a link to it in the downloads area (or will have shortly, if it's not there yet).
What does all this have to do with Edit Original?
Well, the first time I created a booklet with my MakeBooklet script, I immediately tested the Edit Original feature and was very disappointed to discover that the original document didn't open at the page I had asked to edit. Yuck!
So, let's write a script to do the job. I think it's possible; it'll be very disappointing if I fail. Obviously, the script must start in the usual way checking for a selection:
Here's my untested first attempt to do this:
This is getting a bit long so I'll follow up in the next message.
But it took off. And even after InBooklet was added to InDesign (first to CS via the terribly-named PageMaker Plug-ins and then as part of CS2), some people advocated using my script because it was so simple to use. Well, here we are with CS3 and I've done it again. This time, I've called the script MakeBooklet.jsxbin. I've published it as a binary to emphasize that it works only with CS3. Unlike its predecessor, this script creates a new double-sized, single-sided document, placing the contents of the pages of the original document side-by-side in printer spread order.
The ability to place pages from one document to another is new in InDesign CS3 and that opens up all kinds of possibilities for scripts to perform these kinds of imposition tasks. If you'd like to try the script, I've put a link to it in the downloads area (or will have shortly, if it's not there yet).
What does all this have to do with Edit Original?
Well, the first time I created a booklet with my MakeBooklet script, I immediately tested the Edit Original feature and was very disappointed to discover that the original document didn't open at the page I had asked to edit. Yuck!
So, let's write a script to do the job. I think it's possible; it'll be very disappointing if I fail. Obviously, the script must start in the usual way checking for a selection:
//DESCRIPTION: Edit Original for Placed InDesign PagesAlso, obviously, the user ought to be able to do this with either the page selected or its frame. So, the first thing that my editOriginalIDPage function must do is get a reference to the graphic from the selection.
if (app.documents.length == 0 || app.selection.length == 0) { exit() }
editOriginalIDPage(app.selection[0]);
function editOriginalIDPage(sel) {
} // end editOriginalIDPage
Here's my untested first attempt to do this:
//DESCRIPTION: Edit Original for Placed InDesign PagesWell, golly, it didn't work. What am I doing wrong. Clearly, I need to single step through the script and see what happens. Hello! importPages doesn't exist as a collection. That's weird. That forces a different approach. I rewrote the getImpPage function like this:
if (app.documents.length == 0 || app.selection.length == 0) { exit() }
editOriginalIDPage(app.selection[0]);
function editOriginalIDPage(sel) {
var myImpPage = getImpPage(sel);
if (myImpPage == null) return;
alert("Got Here");
function getImpPage(obj) {
if (obj.constructor.name == "ImportedPage") return obj;
try {
return obj.importedPages[0];
} catch(e) {
return null;
}
} // end of getImpPage
} // end editOriginalIDPage
function getImpPage(obj) {And that gets the job done. Notice the neat use of recursion to avoid having to essentially rewrite out the first two lines of the function again at the end.
if (obj.constructor.name == "ImportedPage") return obj;
if (!obj.hasOwnProperty("graphics")) return null;
if (obj.graphics.length == 0) return null;
var myImpPage = obj.graphics[0].getElements()[0];
return getImpPage(myImpPage);
} // enf of getImpPage
This is getting a bit long so I'll follow up in the next message.