17 Replies Latest reply on May 25, 2018 7:35 AM by Pedro Cortez Marques

    Targeting a layer when none is selected.

    DBarranca Level 4

      Hi,

      this is probably so easy that I can't see it. Simple document:

       

      DB 2016-09-23 at 18.27.31.png

       

      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[i].visible) {
              doc.artLayers[i].remove();
          }
      }
      

       

      There are better ways I know, but it works.

      Now try this as a starting point (no layers actually selected):

       

      DB 2016-09-23 at 18.31.44.png

       

      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[i].visible) {
              app.activeDocument.activeLayer = doc.artLayers[i];
              doc.artLayers[i].remove();
          }
      }
      

       

      Am I missing something here?

      Thank you!

       

      Davide

        • 1. Re: Targeting a layer when none is selected.
          JJMack Most Valuable Participant

          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.

          • 2. Re: Targeting a layer when none is selected.
            DBarranca Level 4

            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

            • 3. Re: Targeting a layer when none is selected.
              Kukurykus Adobe Community Professional

              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

              • 4. Re: Targeting a layer when none is selected.
                DBarranca Level 4

                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

                • 5. Re: Targeting a layer when none is selected.
                  JJMack Most Valuable Participant

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

                  }

                  2 people found this helpful
                  • 6. Re: Targeting a layer when none is selected.
                    Kukurykus Adobe Community Professional

                    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).

                    1 person found this helpful
                    • 7. Re: Targeting a layer when none is selected.
                      Kukurykus Adobe Community Professional

                      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.

                      1 person found this helpful
                      • 8. Re: Targeting a layer when none is selected.
                        DBarranca Level 4

                        Interesting information: the issue happens only when trying to make active the layer[0], and not layer[1] – thanks to Kukurykus for finding this out – thanks to JJMack for the AM code.

                         

                        I've submitted this as a bug, because this is what it looks like.

                         

                        Davide

                        • 9. Re: Targeting a layer when none is selected.
                          Tomas Sinkunas Adobe Community Professional

                          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();
                          
                          3 people found this helpful
                          • 10. Re: Targeting a layer when none is selected.
                            Naoki-Hada Level 1

                            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

                            • 11. Re: Targeting a layer when none is selected.
                              Chuck Uebele Adobe Community Professional & MVP

                              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++)

                              • 12. Re: Targeting a layer when none is selected.
                                AverinAAA Level 1

                                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

                                • 13. Re: Targeting a layer when none is selected.
                                  AverinAAA Level 1

                                  So far I have worked this around by doing

                                   

                                  var topLayerVisibility = app.activeDocument.layers[0].visible

                                   

                                     app.activeDocument.activeLayer = app.activeDocument.layers[0]

                                     app.activeDocument.activeLayer.visible = topLayerVisibility

                                   

                                  But that's a little funny

                                  • 14. Re: Targeting a layer when none is selected.
                                    Kukurykus Adobe Community Professional
                                    activeDocument.activeLayer = (lyr = activeDocument.layers)[1], lyr[0].remove()
                                    
                                    • 15. Re: Targeting a layer when none is selected.
                                      Wild Apple

                                      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[i];           
                                              var numberOfSubGroups = myLayerGroup.layerSets.length;
                                              alert("Number of SubGroups:" + numberOfSubGroups);
                                              
                                      
                                              for (j = 0 ; j < numberOfSubGroups ; j++){
                                                  
                                                  var theSubGroup = myLayerGroup.layerSets[j];
                                                  myDoc.activeLayer = myDoc.artLayers.getByName("Signature"); //Get the signature layer
                                                  
                                                  var sigLay = myDoc.activeLayer;
                                      
                                      
                                                  var sigCopy = sigLay.duplicate(theSubGroup, ElementPlacement.INSIDE);
                                               
                                                  myDoc.activeLayer = sigCopy;
                                                             
                                              }          
                                          }
                                      
                                      • 16. Re: Targeting a layer when none is selected.
                                        r-bin Level 4
                                        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) {}
                                            }
                                        
                                        • 17. Re: Targeting a layer when none is selected.
                                          Pedro Cortez Marques Level 3

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