Copy link to clipboard
Copied
I'm working on cleaning up a training manual. The InDesign file has four layers but all copy and photographs were lumped into one layer.
Is there a script that can target images and put them into a layer named Images?
I need a similar task done for the copy. The script would target a paragraph style name and then move it to a particular layer.
Example: all copy linked to a paragraph style named "Captions" gets put those into a layer named Captions.
Hi @Chris Panny, I've written a script that basically does what you ask. It can be quite flexible, but I've included two usages to match the description of your needs. See the lines starting "moveItemsToLayers"? They are the two calls to execute the function. You can turn one or the other off by prepending two forward slashes (//) to the line you don't want to execute. Save the script as plain text—it won't work if saved as rich text (which many editors do by default, so you must ask for plain t
...Copy link to clipboard
Copied
It's both very easy and yet raise questions. What if you have a group made of a text and an image?
Images inside a table? You probably want to define your constraints and what you accept and what you don't.
Or in other words, if done manually, which challenges would you face and which logic should a script follow on those cases?
Once you cleared this out, helping with a script will be easier.
Copy link to clipboard
Copied
Hi @Chris Panny, I've written a script that basically does what you ask. It can be quite flexible, but I've included two usages to match the description of your needs. See the lines starting "moveItemsToLayers"? They are the two calls to execute the function. You can turn one or the other off by prepending two forward slashes (//) to the line you don't want to execute. Save the script as plain text—it won't work if saved as rich text (which many editors do by default, so you must ask for plain text).
Let me know if it helps. Was written quickly and only tested on my simple test document, so it will no doubt need some tweaking if something doesn't work the way you expect in your real document.
- Mark
/**
* Move items to layer.
* Examples of usage:
* 1. move text frames containing text with caption paragraph style
* 2. move all graphics of document
* @author m1b
* @discussion https://community.adobe.com/t5/indesign-discussions/looking-for-script-to-put-content-on-a-specified-layer/m-p/13970732
*/
function main() {
var doc = app.activeDocument,
captionStyle = doc.paragraphStyles.itemByName('Caption');
moveItemsToLayer(doc, captionStyle, 'captions');
moveItemsToLayer(doc, doc.allGraphics, 'Images');
};
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, 'Move Items To Layer');
/**
* Move items to layer.
* @author m1b
* @version 2023-07-29
* @param {Document} doc - an Indesign Document.
* @param {Array|Collection|Function|ParagraphStyle} getItems - items to move, or a method for getting them.
* @param {Layer} layer - the target layer.
* @returns {Number} - the count of moved items.
*/
function moveItemsToLayer(doc, getItems, layer) {
if (layer.constructor.name == 'String')
layer = doc.layers.itemByName(layer);
if (!layer.isValid) {
alert('Layer "' + layer.name + '" is invalid.');
return;
}
var items,
counter = 0,
already = {};
if (typeof getItems === 'function')
items = getItems(doc);
else if (getItems.constructor.name == 'ParagraphStyle')
items = findParagraphs(doc, getItems);
else if (getItems.hasOwnProperty('0'))
items = getItems;
for (var i = items.length - 1; i >= 0; i--) {
var moveMe = getMoveableItem(items[i]);
if (
moveMe == undefined
|| !moveMe.isValid
|| already[moveMe.toSpecifier()] == true
)
continue;
try {
moveMe.move(layer);
already[moveMe.toSpecifier()] = true;
counter++;
} catch (error) { }
}
return counter;
};
/**
* Get array of paragraphs with applied style.
* @author m1b
* @version 2023-07-29
* @param {Document} doc - an Indesign Document
* @param {ParagraphStyle} paragraphStyle - the target style.
* @return {Array<Paragraph>}
*/
function findParagraphs(doc, paragraphStyle) {
if (
paragraphStyle == undefined
|| !paragraphStyle.isValid
)
return [];
app.findTextPreferences = NothingEnum.NOTHING;
app.changeTextPreferences = NothingEnum.NOTHING;
app.findTextPreferences.appliedParagraphStyle = paragraphStyle;
return doc.findText();
}
/**
* Returns object (hopefully!) suitable
* for moving across layers, eg. given text,
* will return the parent text frame.
* @author m1b
* @version 2023-07-29
* @param {any} item - an Indesign DOM object.
* @return {any} - a 'moveable' Indesign DOM object.
*/
function getMoveableItem(item) {
var target = item;
while (
!target.hasOwnProperty('geometricBounds')
&& target.hasOwnProperty('parent')
) {
if (
target.hasOwnProperty('parentTextFrames')
&& target.parentTextFrames.length == 1
)
target = target.parentTextFrames[0];
else if (target.hasOwnProperty('parent'))
target = target.parent;
}
if (target.hasOwnProperty('itemLink'))
target = target.parent;
if (!target.hasOwnProperty('geometricBounds'))
// don't think we can move this item
return;
return target;
};
Edit 2023-08-02: improved error message and layer targetting.
Copy link to clipboard
Copied
Thank you both for your input! I'm very grateful for the script.
I took the script and copied it to a text editor and saved it with a .js extension. Then I moved it to the InDesign scripts folder. When I ran it, I got some error messages:
Copy link to clipboard
Copied
Hi @Chris Panny, thanks for trying it. That error most likely means that the target layer in your document doesn't exist. I've updated the script to give a more user-friendly alert when that happens. Can you try it again? And you must edit the layer names if they don't match the layers in your document.
- Mark
Edit 2023-08-02: updated when I noticed that you have posted the actual layer names in your screenshot.
Copy link to clipboard
Copied
I made the edits to your script and it worked! Thank you!!
Copy link to clipboard
Copied
Why is it an issue?
Copy link to clipboard
Copied
The manuals I work on are 100-250 pages. I end up having to move the assets into their correct layers manually. It's a lot of redundant work so I'm looking to automate this.
Copy link to clipboard
Copied
But why do it at all?
Just for aesthetics?
Copy link to clipboard
Copied
Sometimes I have to isolate the assets such as images. If they're all in one layer with text frames and vector objects, it means I'd have to sort through this to find multiple images in order to turn them off / on. There could be 40+ assets in one layer. It makes the layer cluttered.
It's also easier to apply object styles to the images if they're in their own layer. It makes my work flow more effecient.