Copy link to clipboard
Copied
Hello everyone, I am searching for a script that could allow me to take all the text frames from a document (a manga, or comic book style), and create a new identical one (size and position) on a new layer, but with a different style based on my default frame type.
Does that exists or is it a hopeless quest ? 🙂
Using transform() would be easier. Try this:
//the amount to scale the frame
var s = 1.3
var d = app.activeDocument;
//change as object style name to to yours
var os = d.objectStyles.itemByName("YourStyle")
var tf = d.textFrames.everyItem().getElements();
var dl = makeLayer(d, "TextCopy");
var tm = app.transformationMatrices.add({horizontalScaleFactor:s, verticalScaleFactor:s})
var df;
for (var i = 0; i < tf.length; i++){
df = tf[i].duplicate();
df.transform(CoordinateSpaces.innerCoor
Copy link to clipboard
Copied
Do you really need a script? You can achieve what you need without any script:
Copy link to clipboard
Copied
the original frames are from a japanese file, and I cannot transform them into latin frames (because of the orientation of the characters). That's why I need to create new ones based on my default frames but with the position of the original ones. If I could make the frame bigger, that would be a great bonus !
Copy link to clipboard
Copied
and I cannot transform them into latin frames (because of the orientation of the characters). That's why I need to create new ones
Do you work with a japanese version? What happens if you apply a new paragraph style and apply any latin language to this style?
If I could make the frame bigger, that would be a great bonus !
In the object style, just enable “Auto-size” and the frame size will change according to the new text size.
Copy link to clipboard
Copied
Hi @Olivier5E38 , Try this:
var d = app.activeDocument;
//change as object style name to to yours
var os = d.objectStyles.itemByName("YourObjectStyle")
var dl = makeLayer(d, "TextCopy");
var tf = d.textFrames.everyItem().getElements();
var df;
for (var i = 0; i < tf.length; i++){
df = tf[i].duplicate();
df.itemLayer = dl
df.appliedObjectStyle = os
};
/**
* Makes a new named Layer
* @ param the document to add the layer
* @ param layer name
* @ return the new layer
*/
function makeLayer(d, n){
if (d.layers.itemByName(n).isValid) {
return d.layers.itemByName(n);
} else {
return d.layers.add({name:n});
}
}
Copy link to clipboard
Copied
Rob, your script does exactly what Olivier is asking for in the OP, but in Olivier's second post, I see that the new frames on the new layer are meant to be horizontal text frames for Latin script, not vertical text frames for Japanese. That can't be done with an object style in a non-CJK install of InDesign. In fact, it can't even be done with a script, in a non-CJK install of InDesign.
So my solution was to revise your for loop, grabbing only the source text frame .geometricBounds and .contents:
var d = app.activeDocument;
//change as object style name to to yours
var os = d.objectStyles.itemByName("vertical text frame")
var dl = makeLayer(d, "TextCopy");
var tf = d.textFrames.everyItem().getElements();
for (var i = 0; i < tf.length; i++){
pf = tf[i].geometricBounds;
cf = tf[i].contents;
var df = d.textFrames.add();
df.properties = {
geometricBounds : pf,
contents : cf
}
df.itemLayer = dl
df.appliedObjectStyle = os
};
/**
* Makes a new named Layer
* @ param the document to add the layer
* @ param layer name
* @ return the new layer
*/
function makeLayer(d, n){
if (d.layers.itemByName(n).isValid) {
return d.layers.itemByName(n);
} else {
return d.layers.add({name:n});
}
}
Given some time, I'm sure that I could eventually whip up a little bit of arithmetic to reach @Olivier5E38 's stretch goal of slightly increased geometric bounds to account for text expansion in translation from Japanese to English... but my brain is reaching for contemporary JS stuff that won't work in ExtendScript, like arrow functions, or map().
Copy link to clipboard
Copied
Not sure I’m following, think I need to see an example. In the altered script you are adding new text frames without indicating what page they should be on. So I get this with text frames on the 2-3 spread—all the new frames get added to page 1:
duplicate() clones the textFrame on top of the original using the same bounds, so the bounds of the cloned frames could be changed—this swaps their width and height:
var d = app.activeDocument;
//change as object style name to to yours
var os = d.objectStyles.itemByName("YourStyle")
var tf = d.textFrames.everyItem().getElements();
var dl = makeLayer(d, "TextCopy");
var df, b;
for (var i = 0; i < tf.length; i++){
df = tf[i].duplicate();
b = df.geometricBounds;
//swaps the width and height
df.geometricBounds = [b[0], b[1], b[0]+(b[3]-b[1]), b[1]+(b[2]-b[0])]
df.itemLayer = dl
df.appliedObjectStyle = os
};
/**
* Makes a new named Layer
* @ param the document to add the layer
* @ param layer name
* @ return the new layer
*/
function makeLayer(d, n){
if (d.layers.itemByName(n).isValid) {
return d.layers.itemByName(n);
} else {
return d.layers.add({name:n});
}
}
Copy link to clipboard
Copied
Yeah, that absolutely makes sense now. I was only testing it on a single-page document. The reason that Olivier can't use .duplicate() here is that Olivier wants to change a property of a frame that our installs of InDesign don't have. The one-pager I'm using is a Trad Chinese template that DIane Burns first distributed many years ago; currently she has it up at http://www.transpacificdigital.com/downloads/.
Here's what it looks like in action:
So, we can't use .duplicate, that will just dupe the frame with the vertical property unchanged. In my attempt I tried using .contents() but now I see that it only captures the raw text of the frame. I suppose that looping through app.activeDocument.textFrames.texts would work better, I'll give that a shot.
(If Olivier is using a CJK install of InDesign, then we could write a script that would address only storyOrientation. That's the only reason that I'm chasing this idea of creating new text frames with the contents of the old frames.)
Copy link to clipboard
Copied
I don't use a CJK inDesign. But I noticed something interesting : if I take the japanese frames layer, clone it into my regular latin file, then empty the text frames, change the content from texte to image and back to text, the japanese specs disappear. So I have a latin frame with the desired position.
So the procedure would be : select a layer / empty every frame on it / switch content from txt to image /switch back from img to txt/ (and bonus points for enlarge frames by 30% 😉
One newbie question, how do use the coding you shared ? I usually download script from the internet and save them in the indesign script folder, I don't know how to take the code and save it as a .js or .jsx.
Thank you !
Copy link to clipboard
Copied
So the procedure would be : select a layer / empty every frame on it / switch content from txt to image /switch back from img to txt/ (and bonus points for enlarge frames by 30%
So you want the duplicate text frame to be empty? The script could convert the duplicate to a graphic frame and back to a text frame, which would remove its contents. To test the script copy the code into a plain text editor (e.g. Notepad), save with a .jsx extension and save into your scripts folder:
var d = app.activeDocument;
//change as object style name to to yours
var os = d.objectStyles.itemByName("YourStyle")
var tf = d.textFrames.everyItem().getElements();
var dl = makeLayer(d, "TextCopy");
var df, b;
for (var i = 0; i < tf.length; i++){
df = tf[i].duplicate();
b = df.geometricBounds;
//swaps the width and height
//df.geometricBounds = [b[0], b[1], b[0]+(b[3]-b[1]), b[1]+(b[2]-b[0])]
//increases the frame width by 30%
df.geometricBounds = [b[0], b[1], b[2], b[1]+((b[3]-b[1])*1.3)];
df.itemLayer = dl;
df.appliedObjectStyle = os;
df.contents = ""
df.contentType = ContentType.GRAPHIC_TYPE;
df.contentType = ContentType.TEXT_TYPE;
};
/**
* Makes a new named Layer
* @ param the document to add the layer
* @ param layer name
* @ return the new layer
*/
function makeLayer(d, n){
if (d.layers.itemByName(n).isValid) {
return d.layers.itemByName(n);
} else {
return d.layers.add({name:n});
}
}
Copy link to clipboard
Copied
empty every frame on it
Also, do you really want to make copies of the text frames or do you just need to clear the existing text frame’s content and make the frame wider? If that’s the case the script could be this:
var d = app.activeDocument;
//change as object style name to to yours
var os = d.objectStyles.itemByName("YourStyle")
var tf = d.textFrames.everyItem().getElements();
var b;
for (var i = 0; i < tf.length; i++){
b = tf[i].geometricBounds;
tf[i].geometricBounds = [b[0], b[1], b[2], b[1]+((b[3]-b[1])*1.3)];
tf[i].appliedObjectStyle = os;
tf[i].parentStory.contents = ""
tf[i].contentType = ContentType.GRAPHIC_TYPE;
tf[i].contentType = ContentType.TEXT_TYPE;
};
Copy link to clipboard
Copied
You can duplicate WHOLE layer with one click:
Then - it would be just a case of iterating through the collection of TextFrames, checking if they are on the new layer - increasing size and performing change of contentType...
Copy link to clipboard
Copied
Hi @Robert at ID-Tasker that is exactly what I wrote at the beginning of this thread.
@rob day In this case, I wonder if a script is necessary since a few clicks can easily do the job
Copy link to clipboard
Copied
Maybe if the text frames are really on their own layer independent of the art? And then @Olivier5E38 wants to change the frames’ bounds.
Copy link to clipboard
Copied
So, we can't use .duplicate
I don‘t have anything to test, but @Olivier5E38 ’s switch from text to graphic back to text can be scripted
Copy link to clipboard
Copied
Seems to work perfectly:
Copy link to clipboard
Copied
I can't make it work, I am on mac and don't have notepad. So I tried to use text edit, but I have this error message when I try to use it. I really have no knowledge of programming, sorry.
Copy link to clipboard
Copied
TextEdit saves in RTF format by default, not raw text. The last time I needed to save raw text on a Mac, I opened the script in TextEdit and found "Make Plain Text" in the Format menu. You might be able to do the same thing by using Save As, and choosing a plain-text or raw-text format. You might have something like BBEdit installed, be which will also allow saving as plain text IIRC.
Copy link to clipboard
Copied
As Joel suggests you need to format the text as Plain Text—you can also make Plain text the default in Text Edit’s preferences:
Also, edit the object style name to yours on line 2, and make sure the extension is .jsx when you save (not .jsx.txt)
Copy link to clipboard
Copied
thank you very much for your time, it works ! I have one small problem, even though my reference point is the middle one, the script enlarges the frames to the right.
I managed to understand the enlargment ratio *1.3, if I want higher I could got to *2 or more, but didn't get how to adjust the reference point in the code.
ratio
Copy link to clipboard
Copied
For GeometricBounds, InDesign expects (top, left, bottom, right) arguments.
Or you can move() TF left - after resizing.
Copy link to clipboard
Copied
going from this, to this.
Copy link to clipboard
Copied
Using transform() would be easier. Try this:
//the amount to scale the frame
var s = 1.3
var d = app.activeDocument;
//change as object style name to to yours
var os = d.objectStyles.itemByName("YourStyle")
var tf = d.textFrames.everyItem().getElements();
var dl = makeLayer(d, "TextCopy");
var tm = app.transformationMatrices.add({horizontalScaleFactor:s, verticalScaleFactor:s})
var df;
for (var i = 0; i < tf.length; i++){
df = tf[i].duplicate();
df.transform(CoordinateSpaces.innerCoordinates, AnchorPoint.CENTER_ANCHOR, tm);
df.itemLayer = dl;
df.appliedObjectStyle = os;
df.contents = ""
df.contentType = ContentType.GRAPHIC_TYPE;
df.contentType = ContentType.TEXT_TYPE;
};
/**
* Makes a new named Layer
* @ param the document to add the layer
* @ param layer name
* @ return the new layer
*/
function makeLayer(d, n){
if (d.layers.itemByName(n).isValid) {
return d.layers.itemByName(n);
} else {
return d.layers.add({name:n});
}
}
Copy link to clipboard
Copied
Using transform() would be easier. Try this:
By @rob day
Why?
It's just a case of a different params for:
tf[i].geometricBounds = [b[0], b[1], b[2], b[1]+((b[3]-b[1])*1.3)];
Copy link to clipboard
Copied
Hi everyone, I had lots of project to finalise before getting into this action again, and it works like a charm! A huge thank you to everyone who helped. This is a great community !