batchPlay change text of text layer issue

I just started learning UXP Photoshop development and I’ve run into a snag that I haven’t found anyone else having. I’ve put together a test plugin that simply replaces the text contents of any text layer named “My Text”. When I run the code by clicking on a UI button the batchPlay code doesn’t work unless the alert code line that I was using to troubleshoot is uncommented. This seems like strange behavior. Has anyone experienced this?

Code from main.js:

const app = require("photoshop").app;
const batchPlay = require("photoshop").action.batchPlay;

function change_text () {
    require("photoshop").core.executeAsModal(process_layers(app.activeDocument));
}

async function change_text_alchemist_code (layer_id, text) {

    // alert(text);

    await batchPlay(
        [
            {
                _obj: "set",
                _target: [
                    {
                        _ref: "layer",
                        _id: layer_id
                    }
                ],
                to: {
                    _obj: "textLayer",
                    textKey: text
                }
            }
        ],
        {}
    );
}

function process_layers (layers) {
    let i,
        layer;

    for (i = 0; i < layers.layers.length; i += 1) {
        layer = layers.layers[i];
        if (layer.kind === "group") {
            process_layers(layer);
        } else {
            if (layer.name === "My Text" && layer.kind === "text") {
                change_text_alchemist_code(layer.id, "Hello World!");
            }
        }
    }
}

document.getElementById("change_text").addEventListener("click", change_text);

We all experience many strange behaviors in this new async world when we forget to add an await in front of an async function call. The alert causes enough of a pause that the call goes through. At a glance, I would start by making all the functions async and adding await before each call to them.

As a side note, I would recommend avoiding batchPlay for text. The descriptors are the largest by default. We added support for text in DOM; please take a look.

Sam

1 Like

Hi Sam,

I really appreciate the response!

I had a feeling it was something like that. Unfortunately, that did not fix the issue. I still get the same behavior. It does not update the text without the alert line being uncommented. I will look into the DOM text support but I will need this to work for other batchPlay code that I’m planning on adding.

The revised code still does not work:

const app = require("photoshop").app;
const batchPlay = require("photoshop").action.batchPlay;

async function change_text () {
    await require("photoshop").core.executeAsModal(process_layers(app.activeDocument));
}

async function change_text_alchemist_code (layer_id, text) {

    // alert(text);

    await batchPlay(
        [
            {
                _obj: "set",
                _target: [
                    {
                        _ref: "layer",
                        _id: layer_id
                    }
                ],
                to: {
                    _obj: "textLayer",
                    textKey: text
                }
            }
        ],
        {}
    );
}

async function process_layers (layers) {
    let i,
        layer;

    for (i = 0; i < layers.layers.length; i += 1) {
        layer = layers.layers[i];
        if (layer.kind === "group") {
            await process_layers(layer);
        } else {
            if (layer.name === "My Text" && layer.kind === "text") {
                await change_text_alchemist_code(layer.id, "Hello World!");
            }
        }
    }
}

document.getElementById("change_text").addEventListener("click", change_text);

Hi Sam,

The DOM method is not working either.

const app = require("photoshop").app;

async function execute_as_modal () {
    await require("photoshop").core.executeAsModal(change_text());
}

async function change_text () {
    app.activeDocument.layers[0].textItem.contents = "Hello World!";
}

document.getElementById("change_text").addEventListener("click", execute_as_modal);

Hi Sam,

I found the solution here.

Thanks again for your help.

Ah, yes. executeAsModal does expect a function as an argument. That is one of hurdles to this new modal paradigm.
This is perhaps an example of where type definitions can help identify issues.