Highlighted

Script (JavaScript) to search, store, and select nested layers.

New Here ,
May 18, 2020

Copy link to clipboard

Copied

I'm trying to sort out a way to search through nested layers for any layer starting with *, store them all to an array, and then use an array index to select the corresponding nested layer. I currently have a method that this works for but it feels inefficient and requires interations every time I try to access a nested layer and check for names. It seems like saving the entire path (app.activeDocument.layers[#].layers[#].getByName....) stored into the array would be the cleanest for working on the layer in the future however I can't seem to use the path once it goes into the array (app.activeDocument.activeLayer = path[0] for example does not work). Any help would be apprecaited.

Adobe Community Professional
Correct answer by CarlosCanto | Adobe Community Professional

to go through nested layers you need a "recursive" function, a function that calls itself, as pointed out in m1b's sample script above. So in short, your function will analyze the condition you're looking for then if it has sublayers, it calls itself with the layer as argument.

 

here's a sample

var idoc = app.activeDocument;

var layers = [];

collectLayers (idoc, layers);

alert(layers);

function collectLayers(container, layers) {
    if(container.name.indexOf ('*') == 0)
        layers.push(container);

    for (var b=0; b<container.layers.length; b++) {
        collectLayers (container.layers[b], layers);
    }
}

 

Topics

Scripting

Views

956

Likes

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

Script (JavaScript) to search, store, and select nested layers.

New Here ,
May 18, 2020

Copy link to clipboard

Copied

I'm trying to sort out a way to search through nested layers for any layer starting with *, store them all to an array, and then use an array index to select the corresponding nested layer. I currently have a method that this works for but it feels inefficient and requires interations every time I try to access a nested layer and check for names. It seems like saving the entire path (app.activeDocument.layers[#].layers[#].getByName....) stored into the array would be the cleanest for working on the layer in the future however I can't seem to use the path once it goes into the array (app.activeDocument.activeLayer = path[0] for example does not work). Any help would be apprecaited.

Adobe Community Professional
Correct answer by CarlosCanto | Adobe Community Professional

to go through nested layers you need a "recursive" function, a function that calls itself, as pointed out in m1b's sample script above. So in short, your function will analyze the condition you're looking for then if it has sublayers, it calls itself with the layer as argument.

 

here's a sample

var idoc = app.activeDocument;

var layers = [];

collectLayers (idoc, layers);

alert(layers);

function collectLayers(container, layers) {
    if(container.name.indexOf ('*') == 0)
        layers.push(container);

    for (var b=0; b<container.layers.length; b++) {
        collectLayers (container.layers[b], layers);
    }
}

 

Topics

Scripting

Views

957

Likes

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
Contributor ,
May 18, 2020

Copy link to clipboard

Copied

Hi,

 

Perhaps you an just give the nested layer a unique name? Then just access it with:

 

 

var name = 'nested-layer-1'
var myNestedLayer = app.activeDocument.layers.getByName(name);

 

 

If you need an array of these nested layers for another script, then use a function to collect them all by that method. You don't need a path (as far as I can tell from reading your post)—the array just stores references to the actual layers.

 

If you're happy to post your script I'll be able to understand your needs better.

Likes

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
Reply
Loading...
New Here ,
May 18, 2020

Copy link to clipboard

Copied

My understanding is that in order to refer to a nested layer I need to first refer to the parent layer. So to that end I don't think your example works as it would just work on the top most layers. I could be mistaken but I think I need to iterate over everything to go down in the heirarchy tree. So instead of:

 

...activeDocument.layers.getByName... 

 

it would have to be

 

...activeDocument.layers[#].layers[#].getByName...

 

But this means extensive iteration and then lengthier code to access layers vs nested layers vs nested nested layers and so on.

Likes

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
Reply
Loading...
Contributor ,
May 18, 2020

Copy link to clipboard

Copied

You're right! I didn't know that.

 

I've written a couple of functions to help out. You seem to be familiar with scripting so see what you make of them:

// gets a layer by name
function getLayerByName(name) {
    var layers = allLayers();
    var found;
    for (var i = 0; i < layers.length; i++) {
        if (layers[i].name == name) {
            found = layers[i];
            break;
        }
    }
    return found; // undefined if not found
}

// gets an array of every layer of active document
function allLayers(layers) {
    // returns an array containing layers, including layers found inside layers
    if (layers === undefined) layers = app.activeDocument.layers;
    var found = [];
    for (var i = 0; i < layers.length; i++) {
        var sublayers = layers[i].layers;
        if (sublayers.length > 0) {
            found = found.concat(allLayers(sublayers));
        }
    }
    found = found.concat(objectsIntoArray(layers));
    return found;
}

// this moves the layers out of their "Layers" object and into an ordinary Array
function objectsIntoArray(objects) {
    var array = [];
    for (var i = 0; i < objects.length; i++) {
        array.push(objects[i]);
    }
    return array;
}

 

Regards,

Mark

Likes

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
Reply
Loading...
Adobe Community Professional ,
May 18, 2020

Copy link to clipboard

Copied

to go through nested layers you need a "recursive" function, a function that calls itself, as pointed out in m1b's sample script above. So in short, your function will analyze the condition you're looking for then if it has sublayers, it calls itself with the layer as argument.

 

here's a sample

var idoc = app.activeDocument;

var layers = [];

collectLayers (idoc, layers);

alert(layers);

function collectLayers(container, layers) {
    if(container.name.indexOf ('*') == 0)
        layers.push(container);

    for (var b=0; b<container.layers.length; b++) {
        collectLayers (container.layers[b], layers);
    }
}

 

Likes

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
Reply
Loading...
Contributor ,
May 18, 2020

Copy link to clipboard

Copied

Nice! 🙂

Likes

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
Reply
Loading...
New Here ,
May 19, 2020

Copy link to clipboard

Copied

That's great - thank you!

Likes

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
Reply
Loading...
New Here ,
May 19, 2020

Copy link to clipboard

Copied

Developing a step further on this - how would you go about collecting the pathItems that exist within these flagged layers? I'm still learning about recursion so another pointer here would be great.

Likes

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
Reply
Loading...
Adobe Community Professional ,
May 20, 2020

Copy link to clipboard

Copied

just follow the same concept. Add another array to hold the pathItems. Then when you evaluate each layer, if the condition is true, after adding the layer to the layer array, loop through its path items and add them one by one to the paths array.

 

 

var idoc = app.activeDocument;

var layers = [];
var paths = [];

collectLayers (idoc, layers);

alert(layers);
alert(paths);

function collectLayers(container, layers) {
    if(container.name.indexOf ('*') == 0) {
        layers.push(container);
        
        for (var a=0; a<container.pathItems.length; a++) 
            paths.push(container.pathItems[a]);
    }
    for (var b=0; b<container.layers.length; b++) {
        collectLayers (container.layers[b], layers);
    }
}

 

Likes

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
Reply
Loading...