Copy link to clipboard
Copied
Hi,
this is probably so easy that I can't see it. Simple document:
Simple script that loops through layers and deletes the one that's hidden:
var doc = app.activeDocument;
for (var i = 0; i < doc.artLayers.length; i++) {
if (!doc.artLayers.visible) {
doc.artLayers.remove();
}
}
There are better ways I know, but it works.
Now try this as a starting point (no layers actually selected):
The above script fails with error "The Command Delete is not currently available".
I've added an extra line to make it active, but it doesn't (at least Photoshop CC2015.5, OSX)
var doc = app.activeDocument;
for (var i = 0; i < doc.artLayers.length; i++) {
if (!doc.artLayers.visible) {
app.activeDocument.activeLayer = doc.artLayers;
doc.artLayers.remove();
}
}
Am I missing something here?
Thank you!
Davide
Copy link to clipboard
Copied
I do not think so. I have had to catch that error in some scripts when the user used the script and had nothing targeted. Even when the script was processing all layers. I had to catch that error I thought should not have happen because I was processing all layers in a recursive loop. I had to target the top layer the use the scipt's main function to get the recursive loop to work. I think your loop will also miss layers in layer groups that have their visibility off.
Copy link to clipboard
Copied
Hi JJMack,
the script is for demo purposes only. The question remains – how to you select / make active *any* layer if even:
app.activeDocument.activeLayer = app.activeDocument.artLayers[0];
fails? I'd like to avoid actionmanager in this case.
Thank you!
Davide
Copy link to clipboard
Copied
I tired second case (no layer selected) with hidden layer[1] or background and it worked, but only then. The same was when I made a loop from end to beggining, so it failed when first (not bottom / background) layer was hidden.
When I checked which layer is active when none of them was selected it always said the first one, even if before I unselected any other that was below top layer. It must be bug.
It doesn't work also with simple:
activeDocument.activeLayer = activeDocument.layers[0]
no matter top layer is (in)visible, when all are unselected
it works only for any other layer beside first one in case of all (manually) unselected layers
Copy link to clipboard
Copied
Let's step back and forget for a moment about the delete layer, which doesn't work if a layer (any) isn't selected.
I rephrase the issue: if no layer is selected, how do you select / make active a layer (possibly w/o ActionManager)?
Thank you,
Davide
Copy link to clipboard
Copied
I can not help w/o ActionManager code. What I used was the Action Manager code for the shortcut Alt+. Select front visible layer.
function selectFront() {
// Alt+. shortcut select ftont visible layer
var idslct = charIDToTypeID( "slct" );
var desc250 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref207 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idFrnt = charIDToTypeID( "Frnt" );
ref207.putEnumerated( idLyr, idOrdn, idFrnt );
desc250.putReference( idnull, ref207 );
var idMkVs = charIDToTypeID( "MkVs" );
desc250.putBoolean( idMkVs, false );
executeAction( idslct, desc250, DialogModes.NO );
}
Copy link to clipboard
Copied
JJMack,
Thank you very much for the code snipped. It will help for my case.
Do you know is there any way (preferably fast to run) to find out if layer is unselected or selected any.
app.activeDocument.activeLayer seems same when it is selected and when none of layer selected.
Thank you,
Naoki
Copy link to clipboard
Copied
Only a trick works:
1) when there are more than one layer or background, and all layers (incl. bg) are unselected then:
select by script any other layer and then you can select layer[0]
2) when there is only one (unselected) layer in a document and it's not a background you can:
if that is set to invisible, make it visible - it won't make a layer active. Then (or if that was already visible) change this layer to background, so it automaticly will be selected. Finally you can change it to layer again. (In case of only background and no other layers there is no problem as background can't be unselected).
Copy link to clipboard
Copied
I JUST THOUGHT UP ANOTHER TRICK!
It's not always method to change only one layer to background, as then you may loose masks or some adjustmensts, so the best and most practical is:
- change only one layer to background
- call the history state before that change, so even if that was unselected, now it will be selected and all adjustments and masks won't be lost
if (activeDocument.layers[0].visible == 1) activeDocument.activeLayer.isBackgroundLayer = true
activeDocument.activeHistoryState = activeDocument.historyStates[activeDocument.historyStates.length - 2]
I tried with duplication but that didn't work. maybe setting to Inteligent Object could help, anyway that above solution seems to be convinient.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
I am experiencing same issues as well when duplicating layers.
Found yet another workaround - create new layer and then remove it. This will force to auto highlight first layer in the stack.
var newLayer = app.activeDocument.artLayers.add();
newLayer.remove();
Copy link to clipboard
Copied
I was having the same issue with the following script.
Before adding in the two noted lines the script would not function correctly unless I started with the first layer selected.
Explicitly making it the active layer by calling it by name didn't seem to matter. This seems like a real hack, but it works.
Will see what happens when I test it further in production.
Thanks for the tip,
Scott
#target photoshop
// Make Photoshop the frontmost application
app.bringToFront();
var myDoc = app.activeDocument;
//Adding these two lines fixed it
//var newLayer = myDoc.artLayers.add();
//newLayer.remove();
var numberOfLayerGroups = myDoc.layerSets.length;
alert("Number of Layer Groups:" + numberOfLayerGroups);
for (i = 0 ; i < numberOfLayerGroups ; i++){
var myLayerGroup = myDoc.layerSets;
var numberOfSubGroups = myLayerGroup.layerSets.length;
alert("Number of SubGroups:" + numberOfSubGroups);
for (j = 0 ; j < numberOfSubGroups ; j++){
var theSubGroup = myLayerGroup.layerSets
; myDoc.activeLayer = myDoc.artLayers.getByName("Signature"); //Get the signature layer
var sigLay = myDoc.activeLayer;
var sigCopy = sigLay.duplicate(theSubGroup, ElementPlacement.INSIDE);
myDoc.activeLayer = sigCopy;
}
}
Copy link to clipboard
Copied
I owe you a beer!
Copy link to clipboard
Copied
Hey guys.
I have an issue that might be related or not to this topic.
Having a document with 2 layers:
Layer 0 – invisibile
Layer 1 – visibile
I need to merge this all to a new layer. Because merging doesn't work when you have only one visible layer in the document, what I try to do is create a new empty layer on top and then call merging to new layer method. It results in merging going to that new layer.
Now the problem is that when Layer 0 is invisible, calling app.activeDocument.activeLayer = app.activeDocument.layers[0], for whatever reason, makes it visible. This breaks logic of my script a little.
Any tips? I didn't find anything in the docs about activeLayer being visible all the time
Copy link to clipboard
Copied
So far I have worked this around by doing
app.activeDocument.activeLayer = app.activeDocument.layers[0]
app.activeDocument.activeLayer.visible = topLayerVisibility
But that's a little funny
Copy link to clipboard
Copied
activeDocument.activeLayer = (lyr = activeDocument.layers)[1], lyr[0].remove()
Copy link to clipboard
Copied
When you make a loop that deletes an element like a layer, you need to change what "i" is less than. The layers length is going to change as you delete layers. Put that into a variable then us that variable in the loop statement.
var Len = app.activeDocument.layers.length;
for (var i =0;i<Len;i++)
Copy link to clipboard
Copied
function reselect_active_layer()
{
var r = new ActionReference();
r.putProperty(stringIDToTypeID("property"), stringIDToTypeID("layerID"));
r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var id = executeActionGet(r).getInteger(stringIDToTypeID("layerID"));
var r = new ActionReference();
r.putEnumerated(stringIDToTypeID("layer"), stringIDToTypeID("ordinal"), stringIDToTypeID("targetEnum"));
var d = new ActionDescriptor();
d.putReference(stringIDToTypeID("null"), r);
try { executeAction(stringIDToTypeID("selectNoLayers"), d, DialogModes.NO); } catch(e) {}
var r = new ActionReference();
r.putIdentifier(stringIDToTypeID("layer"), id);
var d = new ActionDescriptor();
d.putReference(stringIDToTypeID("null"), r);
d.putBoolean(stringIDToTypeID( "makeVisible"), activeDocument.activeLayer.visible);
try { executeAction(stringIDToTypeID("select"), d, DialogModes.NO); } catch(e) {}
}
Copy link to clipboard
Copied
Hi Davide,
I have the same error as you on the last version of Photoshop (19.1.4).
I know you said you don't want AM code, but somehow this will delete all the hidden layers with no error on the "delete".
deleteAllHiddenLayers();
function deleteAllHiddenLayers() {
var c2t = function (s) { return app.charIDToTypeID(s); };
var s2t = function (s) { return app.stringIDToTypeID(s); };
var descriptor = new ActionDescriptor();
var reference = new ActionReference();
reference.putEnumerated( s2t( "layer" ), s2t( "ordinal" ), s2t( "hidden" ));
descriptor.putReference( c2t( "null" ), reference );
executeAction( s2t( "delete" ), descriptor, DialogModes.NO );
}
Copy link to clipboard
Copied
Found the same problem after all these years... Has this bug been reported?
It happens both when no layer is selected and when all layers are selected.
So far, the solutions below work (a big thank you!), but it leaves kind of unnecessary code in the script...