How to check if there is a selection in the active document with UXP?

I am porting a cep extension to UXP. It used app.activeDocument.selection.bounds in a try-catch block to check whether there was actually a selection present.

The documentation mentions a selection class (https://www.adobe.io/photoshop/uxp/ps_reference/classes/selection/), but I have not found any way to access it. (require("photoshop").app.activedocument.selection evaluates to undefined)

What would be the proper way to perform this kind of check in Photoshop UXP?

1 Like

This is how I am doing it in my plugin. If you don’t need the selection coordinates var then you can replace the try line with try{await getSelectionBounds();}

var selectionExists=true;    
try{var selectionBounds=await getSelectionBounds();}
catch(e){selectionExists=false;}

async function getSelectionBounds(){

const idDoc=await app.activeDocument._id;

const result = await require("photoshop").action.batchPlay(
[
   {
  "_obj": "get",
  "_target": [
     {
        "_property": "selection"
     },
     {
        "_ref": "document",
        "_id": idDoc
     }
  ],
  "_options": {
     "dialogOptions": "dontDisplay"
  }
   }
],{
   "synchronousExecution": false,
   "modalBehavior": "fail"
});


const left = result[0].selection.left._value;
const top = result[0].selection.top._value; 
const right = result[0].selection.right._value; 
const bottom = result[0].selection.bottom._value;  

return [left,top,right,bottom];    

}
1 Like

const idDoc=await app.activeDocument._id;

Note that you possibly won’t need to await the ID, just use:

const idDoc = app.activeDocument._id

Oh, one more thing regarding "_target" section of your code above:
idDoc is used for targeting the current opened document using its ID, that’s OK.

 {
    "_ref": "document",
    "_id": idDoc
 }

That’s (by default) how Alchemist generates a code from the opened document, using "_id"

However, sometimes you just need to target the current opened document, and you can avoid getting its ID by just targeting the current opened document like so:

{
    "_ref": "document",
    "_enum": "ordinal",
    "_value": "targetEnum"
}

Cheers!

1 Like

Thanks a bunch! I had no idea you could use “_obj”: “get” to simply get various properties in Photoshop.

Additionally, Thank you for this extra info as well!

I have seen some things I thought didn’t need await cause timing issues on some computers but not on other computers. Because of that, I have been adding await when in doubt just in case it needs it. It doesn’t seem to hurt it.

I didn’t know about the method you suggested or the current doc ID. I’ll try that.

Generally you only need await on asynchronous code, for example promises or async functions (that essentially return promises). When it comes to batchplay, there are two possible return values:
Descriptor and Promise<Descriptor>. Normally, it will return a promise, but if you add { synchronousExecution: true } as the batchPlay options, it will already wait for that internally and return a Descriptor.

In regards to the Photoshop API it’s always clearly stated in the docs when a function is async, for example:

Hello everybody, I tried executing the same code after doing a lazo (or any other type) selection but it always ends on the catch(e) case. Any suggestion ?

async function getSelectionBounds(){

     const idDoc=await app.activeDocument._id;

     var selectionExists=true;    

     try {

        const result = await require("photoshop").action.batchPlay(

           [{

              "_target": [{

                 "_property": "selection"

              },

              {

                 "_ref": "document",

                 "_id": idDoc

              }

              ]

           }],

           {

           "synchronousExecution": false,

           "modalBehavior": "fail"

           }

        );

        

        console.log(result[0])

        

        const left = result[0].selection.left._value;

        const top = result[0].selection.top._value;

        const right = result[0].selection.right._value;

        const bottom = result[0].selection.bottom._value;

        selBounds = [left, top, right, bottom];

        selectionExists = true;

    

     } catch (e) {

        selectionExists = false;

     }

     console.log(selectionExists)

  }
1 Like

Is it though? :slight_smile: Where’s the "_obj": "get", for eg.? Your descriptor is way too different in structure, than what is given in the solution.

Also you could always try logging the error

catch (e) {
  console.log(e)
}

I apologize for this confused post, the result of having worked late into the night … when I realized my mistake I wanted to delete the post to avoid unnecessary disturb but I didn’t make it in time. In any case, the correct code obviously works and I thank you for the answer