• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Script to arrange one pathItem per layer

Community Beginner ,
Dec 18, 2024 Dec 18, 2024

Copy link to clipboard

Copied

I am looking for a script that moves all individual items to their own layer using the same layer name.

 

Screenshot 2024-12-18 at 8.21.29 PM.png

 

Screenshot 2024-12-18 at 8.24.56 PM.png

 

TOPICS
How-to , Scripting

Views

215

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 2 Correct answers

Community Expert , Dec 18, 2024 Dec 18, 2024

Hi @nutradial, this is a quick one. - Mark

/**
 * @file One Item Per Layer.js
 * 
 * Moves all document's page items to a new top-level layer,
 * matching properties of the item's original layer.
 * 
 * @author m1b
 * @version 2024-12-19
 */
(function () {

    var doc = app.activeDocument,
        items = doc.pageItems;

    // loop over the page items, backwards,
    // moving each to a new layer, which is
    // a copy of the original layer
    for (var i = items.length - 1, item, layer, newL
...

Votes

Translate

Translate
Community Expert , Dec 20, 2024 Dec 20, 2024

@nutradial this is one way...

/**
 * @file One Item Per Layer 2.js
 *
 * Moves a layer's page items to a new top-level layer,
 * matching properties of the item's original layer.
 *
 * @author m1b
 * @version 2024-12-19
 */
(function () {

    // will only target this layer
    const TARGET_LAYER = 'Layer 2';

    var doc = app.activeDocument,
        items = doc.pageItems;

    // loop over the page items, backwards,
    // moving each to a new layer, which is
    // a copy of the original laye
...

Votes

Translate

Translate
Adobe
Community Expert ,
Dec 18, 2024 Dec 18, 2024

Copy link to clipboard

Copied

Hi @nutradial, this is a quick one. - Mark

/**
 * @file One Item Per Layer.js
 * 
 * Moves all document's page items to a new top-level layer,
 * matching properties of the item's original layer.
 * 
 * @author m1b
 * @version 2024-12-19
 */
(function () {

    var doc = app.activeDocument,
        items = doc.pageItems;

    // loop over the page items, backwards,
    // moving each to a new layer, which is
    // a copy of the original layer
    for (var i = items.length - 1, item, layer, newLayer; i >= 0; i--) {

        item = items[i];
        layer = getLayer(item);

        if (!layer)
            continue;

        layer.locked = false;
        layer.visible = true;

        // create the new layer
        newLayer = doc.layers.add();
        newLayer.color = layer.color
        newLayer.locked = layer.locked
        newLayer.name = layer.name
        newLayer.preview = layer.preview
        newLayer.printable = layer.printable
        newLayer.visible = layer.visible

        // move into place
        newLayer.move(layer, ElementPlacement.PLACEAFTER);
        item.move(newLayer, ElementPlacement.PLACEATBEGINNING);

    }

    // remove empty layers
    for (var i = doc.layers.length - 1; i >= 0; i--)
        if (0 === doc.layers[i].pageItems.length)
            doc.layers[i].remove();

    /**
     * Returns an item's layer.
     * @param {PageItem} item - an Illustrator PageItem.
     * @returns {Layer?}
     */
    function getLayer(item) {

        var layer = item.parent;

        while (
            undefined !== layer
            && layer.hasOwnProperty('parent')
            && 'Document' !== layer.parent.constructor.name
        )
            layer = layer.parent;

        if ('Layer' === layer.constructor.name)
            return layer;

    };

})();

 demo.gif

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 20, 2024 Dec 20, 2024

Copy link to clipboard

Copied

What needs to change to have the "One Item Per Layer.js"  script only affect a specific layer (i.e. Layer 2)? 

 

 

Screenshot 2024-12-20 at 8.03.41 AM.png

 

 

Screenshot 2024-12-20 at 7.48.04 AM.png

 

 

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 20, 2024 Dec 20, 2024

Copy link to clipboard

Copied

@nutradial this is one way...

/**
 * @file One Item Per Layer 2.js
 *
 * Moves a layer's page items to a new top-level layer,
 * matching properties of the item's original layer.
 *
 * @author m1b
 * @version 2024-12-19
 */
(function () {

    // will only target this layer
    const TARGET_LAYER = 'Layer 2';

    var doc = app.activeDocument,
        items = doc.pageItems;

    // loop over the page items, backwards,
    // moving each to a new layer, which is
    // a copy of the original layer
    for (var i = items.length - 1, item, layer, newLayer; i >= 0; i--) {

        item = items[i];
        layer = getLayer(item);

        if (
            !layer
            || TARGET_LAYER !== layer.name
        )
            continue;

        layer.locked = false;
        layer.visible = true;

        // create the new layer
        newLayer = doc.layers.add();
        newLayer.color = layer.color
        newLayer.locked = layer.locked
        newLayer.name = layer.name
        newLayer.preview = layer.preview
        newLayer.printable = layer.printable
        newLayer.visible = layer.visible

        // move into place
        newLayer.move(layer, ElementPlacement.PLACEAFTER);
        item.move(newLayer, ElementPlacement.PLACEATBEGINNING);

    }

    // remove empty layers
    for (var i = doc.layers.length - 1; i >= 0; i--) {
        if (
            TARGET_LAYER === doc.layers[i].name
            && 0 === doc.layers[i].pageItems.length
        )
            doc.layers[i].remove();
    }

    /**
     * Returns an item's layer.
     * @param {PageItem} item - an Illustrator PageItem.
     * @returns {Layer?}
     */
    function getLayer(item) {

        var layer = item.parent;

        while (
            undefined !== layer
            && layer.hasOwnProperty('parent')
            && 'Document' !== layer.parent.constructor.name
        )
            layer = layer.parent;

        if ('Layer' === layer.constructor.name)
            return layer;

    };

})();

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 20, 2024 Dec 20, 2024

Copy link to clipboard

Copied

To bring it all home and finish the lesson ... how about within a sublayer.

 

Screenshot 2024-12-20 at 10.28.12 AM.png

 

Screenshot 2024-12-20 at 10.30.51 AM.png

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Dec 20, 2024 Dec 20, 2024

Copy link to clipboard

Copied

Again, there are so many ways, but here is one approach. I wanted to do it differently to the first script to make it more flexible. This time you can specify a targetLayerName (or names if you use an array, or none to apply to all layers). Like this:

0000_demo-A.jpg0001_demo-B.jpg0002_demo-C.jpg0003_demo-D.jpg

/**
 * @File One Item Per Layer 3.js
 *
 * Moves each of a layer's page items to a new top-level layer,
 * matching properties of the item's original layer.
 *
 * @author m1b
 * @version 2024-12-21
 * @discussion https://community.adobe.com/t5/illustrator-discussions/script-to-arrange-one-pathitem-per-layer/m-p/15047388
 */
(function () {

    var settings = {

        /**
         * The layer(s) to target
         *   - if String, target that single layer
         *   - if Array, target multiple layers
         *   - if undefined, target all layers
         */
        targetLayerName: ['Sublayer 2.1', 'Sublayer 2.1.1'],

    };

    if (0 === app.documents)
        return alert('Please open a document and try again.');

    if (
        undefined != settings.targetName
        && 'Array' !== settings.targetName.constructor.name
    )
        settings.targetName = [settings.targetName];

    var doc = app.activeDocument,
        items = doc.pageItems,
        moves = [],
        removeMe = new Unique();

    itemLoop:
    for (var i = 0; i < items.length; i++) {

        var item = items[i];

        if (!item.hasOwnProperty('parent'))
            continue;

        var obj = item,
            topLayer = undefined,
            parentLayer = undefined;

        while (!topLayer) {

            obj = obj.parent;

            if (!obj.hasOwnProperty('parent'))
                continue itemLoop;

            if (
                'Layer' === obj.constructor.name
                && !parentLayer
            )
                parentLayer = obj;

            if ('Document' === obj.parent.constructor.name)
                topLayer = obj;

        }

        if ('Layer' !== topLayer.constructor.name)
            continue itemLoop;

        if (settings.targetLayerName) {

            if (indexOf(parentLayer.name, settings.targetLayerName) !== -1)
                // match this layer by name
                removeMe.push(parentLayer);
            else
                continue itemLoop;
        }
        else
            removeMe.push(topLayer);

        // remove the layer once empty
        removeMe.push(topLayer);

        moves.push({
            item: items[i],
            layer: topLayer,
            layerName: parentLayer.name,
        });

    }

    // perform the moves
    for (var i = moves.length - 1; i >= 0; i--) {

        var move = moves[i],
            newLayer;

        move.layer.locked = false;
        move.layer.visible = true;

        // create the new layer
        newLayer = doc.layers.add();
        newLayer.color = move.layer.color;
        newLayer.locked = move.layer.locked;
        newLayer.name = move.layerName;
        newLayer.preview = move.layer.preview;
        newLayer.printable = move.layer.printable;
        newLayer.visible = move.layer.visible;

        // move into place
        newLayer.move(move.layer, ElementPlacement.PLACEAFTER);
        move.item.move(newLayer, ElementPlacement.PLACEATBEGINNING);

    }

    // remove empty layers
    for (var i = removeMe.length - 1; i >= 0; i--)
        if (isEmpty(removeMe[i]))
            removeMe[i].remove();

})();

/**
 * An array-like object that won't contain duplicates.
 * @author m1b
 * @version 2024-12-21
 */
function Unique() {

    this.array = [];
    this.length = 0;

    this.push = function pushUnique(obj) {

        for (var i = 0; i < this.array.length; i++)
            if (this.array[i] === obj)
                return;

        this.array.push(obj);
        this.length++;
        this[this.length - 1] = obj;

    };

    this.toString = function uniqueToString() {
        return String(this.array);
    };

};

/**
 * Returns index of obj in arr.
 * Returns -1 if not found.
 * @Param {any} obj
 * @Param {Array} arr
 * @Returns {Number}
 */
function indexOf(obj, arr) {
    for (var i = 0; i < arr.length; i++)
        if (arr[i] === obj)
            return i;
    return -1;
};

/**
 * Returns true when the layer and its sublayers are all empty.
 * @Param {Layer} layer - an Illsutrator Layer.
 * @Returns {Boolean}
 */
function isEmpty(layer) {

    if (!layer)
        return false;

    if (layer.layers.length > 0) {
        for (var i = 0; i < layer.layers.length; i++) {
            if (!isEmpty(layer.layers[i]))
                return false;
        }
    }

    if (layer.pageItems.length > 0)
        return false;

    return true;

};

 

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Dec 23, 2024 Dec 23, 2024

Copy link to clipboard

Copied

LATEST

@m1b  Nice update. I like how it splits up compoundPathItems and groupItems into new individual top-level layers. It does create an empty top-level layer when it does this which is not a big deal. Thanks again, I'm learinng a lot from your posts.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines