Skip to main content
Chris Panny
Inspiring
July 28, 2023
Answered

Looking For Script To Put Content On A Specified Layer

  • July 28, 2023
  • 3 replies
  • 2088 views

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.

This topic has been closed for replies.
Correct answer m1b

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.

3 replies

Community Expert
August 2, 2023

Why is it an issue? 

Chris Panny
Inspiring
August 3, 2023

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.

It's only an island if you look at it from the water.
Community Expert
August 3, 2023

But why do it at all? 
Just for aesthetics? 

m1b
Community Expert
m1bCommunity ExpertCorrect answer
Community Expert
July 28, 2023

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.

Chris Panny
Inspiring
August 1, 2023

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:

 

 

It's only an island if you look at it from the water.
m1b
Community Expert
Community Expert
August 1, 2023

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.

Participating Frequently
July 28, 2023

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.