How to get DOM layer by ID?

Is it even possible to get DOM layer object by layer ID without recursively iterating through whole layers tree? BP returns a different object and I specifically need Layer.layers of that group I have ID for, and it can be located any amount of levels deep. More specifically, I need an index of the first layer/group in that group. I’m afraid parsing a larger full tree might slow down plugin significantly :confused:

I’d just do this with batchPlay by starting at the index of “that group” and iterating until you find a layerSectionStart. I don’t think DOM has any specific getters for layers.

You gave me an idea

  • Get index of the group I already have ID for
  • Get previous index (indexes ascend from bottom to top) layer data and see if it’s inside “that group” by checking layerSectionStart and/or other properties (after all I need only the first one)

Will try again after work. And again thank you :slight_smile:

Yep exactly :+1: Sometimes I forget whether indices start top or bottom, but I guess I just have to remember that the background layer has index 1 :smile:

:man_facepalming: :man_facepalming: :man_facepalming:

const result = require("photoshop").action.batchPlay(
[
   {
        _obj: "get",
        _target: [
            {_ref: "layer", _index: 0},
            {_ref: "document", _enum: 'ordinal', _value: 'targetEnum'},
        ],
    }
], {})

Returns background layer, which has itemIndex: 1
Requesting _index: 3 returns itemIndex: 4 and so on
Trying to solve further…

Indices are fun in ActionManager/PS, aren’t they :smiley: That’s why all code dealing with layer indices should factor in whether there’s a background layer or not, as this directly influences the itemIndex property:

(await require("photoshop").action.batchPlay(
[
   {
        _obj: "get",
        _target: [
            {_property: "itemIndex"},
            {_ref: "layer", _index: 1},
        ],
    }
], {}))[0].itemIndex

With background ➞ 1
Without background ➞ 2

_index: 0 is reserved for the background layer, so if you try to get any descriptor referenced by _index: 0 in a document without background layer, it will result in undefined.

So basically I ended up with almost what you suggested

  • Get group layer index
  • Subtract from that index
  • Get layer by that index
    • If it has parentLayerID, it’s the layer I need and get that layer index
    • If it doesn’t, then break operation

I’d also compare the parentLayerID against the group’s ID because if you just check if parentLayerID exists, it can give wrong results:

  • Some other group (layerSectionStart)
    • The group you check against (layerSectionStart)
    • The group you check against (layerSectionEnd)
    • Some layer (layerSectionContent) → has parentLayerID of “Some other group”
  • Some other group (layerSectionEnd)

In this case you’d find “Some layer”, which is not inside of “The group you check against” (which is empty).

So either compare the parentLayerID or alternatively, iterate down until the next layerSectionEnd - The first hit you find in between will definitely be inside the group.

Sure. In early days of UXP I suggested to expose classes. Therefore we can do something like:

const Layer = require('photoshop').app.Layer;
const lyr = new Layer(layerID, docID); //I don't remember now whether docID is first arg or layerID
3 Likes

@simonhenke, yes - I do check if parent ID match, but once again you made me realise I didn’t test with empty groups around the layer I want to interact with. Some more work for the evening :slight_smile:


@Jarda, are you saying, that creating a new Layer() while providing an ID of the existing layer will return that existing layer? :exploding_head: Will definitely check that also later

Yes… there is no need to touch document DOM structure at all. You can simply create DOM Layer instance out of thin air :smiley: :slight_smile: Example here: alchemist/GetDOM.ts at f20edd070e05a98295f69d14f7afe2fd991278d6 · jardicc/alchemist · GitHub

2 Likes

Nice! I didn’t know about that.

This is a good thing to keep in mind, but sadly could not really make it useful in this case. I thought DOM layers have index property, but apparently they don’t

And tested with empty groups and it seems my accepted solution works well in that case too