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

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

New Here ,
May 18, 2020 May 18, 2020

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.

TOPICS
Scripting
2.4K
Translate
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 1 Correct answer

Community Expert , May 18, 2020 May 18, 2020

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(
...
Translate
Adobe
Community Expert ,
May 18, 2020 May 18, 2020

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.

Translate
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
New Here ,
May 18, 2020 May 18, 2020

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.

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

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

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

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);
    }
}

 

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

Nice! 🙂

Translate
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
New Here ,
May 19, 2020 May 19, 2020

That's great - thank you!

Translate
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
New Here ,
May 19, 2020 May 19, 2020

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.

Translate
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 ,
May 20, 2020 May 20, 2020
LATEST

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);
    }
}

 

Translate
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