Skip to main content
Inspiring
April 18, 2023
Answered

How would I write a script to select the layer directly above the currently selected layer?

  • April 18, 2023
  • 4 replies
  • 2559 views

I am at a loss as to how this is done.

Help please.

This topic has been closed for replies.
Correct answer mangurian

Thanks to all.  What a great community.

4 replies

Stephen Marsh
Community Expert
Community Expert
April 18, 2023

And here is one from @ joonaspaakko:

 

https://gist.github.com/joonaspaakko/048c9b58ccbb6e6f44c894bf4ce30b68

 

// Select Next Layer (invisible or not).jsx
// https://gist.github.com/joonaspaakko/048c9b58ccbb6e6f44c894bf4ce30b68

nextLayer('up');

// direction (↑): "up" or "above"
// direction (↓): "down" or "below"
function nextLayer( direction ) {
  
  var doc = app.activeDocument;
   // Doc duplication is necessary because while the History panel can record visibility change, but for some reason it doesn't do that when the visibility command comes from a script... (AFAIK)
  var tempDoc = doc.duplicate();
  var layer1 = tempDoc.activeLayer;
  
  // Turn background layer into a normal layer
  var lastLayer = tempDoc.layers[ tempDoc.layers.length-1 ];
  function cTID(s) { return app.charIDToTypeID(s); };
  function sTID(s) { return app.stringIDToTypeID(s); };
  var layer1ID = activeLayerID();
  tempDoc.activeLayer = lastLayer;
  var bgLayerExists = lastLayer.isBackgroundLayer;
  if ( bgLayerExists ) { lastLayer.isBackgroundLayer = false; }
  try { selectLayerByID( layer1ID ); } catch(e) {}
  // Select all layers
  var desc23 = new ActionDescriptor();
  var ref5 = new ActionReference();
  ref5.putEnumerated( cTID('Lyr '), cTID('Ordn'), cTID('Trgt') );
  desc23.putReference( cTID('null'), ref5 );
  executeAction( sTID('selectAllLayers'), desc23, DialogModes.NO );
  // Make active layers visible
  var desc209 = new ActionDescriptor();
  var list93 = new ActionList();
  var ref129 = new ActionReference();
  ref129.putEnumerated( cTID('Lyr '), cTID('Ordn'), cTID('Trgt') );
  list93.putReference( ref129 );
  desc209.putList( cTID('null'), list93 );
  executeAction( cTID('Shw '), desc209, DialogModes.NO );
  // Reselect the starting layer
  if ( bgLayerExists ) { lastLayer.isBackgroundLayer = true; }
  selectLayerByID( layer1ID );
  // Select next layer
  try { snl( direction ); } catch(e) {}
  // Store the layer
  var nextLayer = activeLayerID();
  tempDoc.close( SaveOptions.DONOTSAVECHANGES );
  // Try to select the next layer using its ID
  try {
    selectLayerByID( nextLayer );
  }
  // If it fails, well assume it did so because it was a background layer... and use another method for selecting that.
  catch(e) {
    var desc299 = new ActionDescriptor();
        var ref187 = new ActionReference();
        ref187.putName( cTID('Lyr '), "Background" );
    desc299.putReference( cTID('null'), ref187 );
    desc299.putBoolean( cTID('MkVs'), false );
        var list138 = new ActionList();
        list138.putInteger( 1 );
    desc299.putList( cTID('LyrI'), list138 );
    executeAction( cTID('slct'), desc299, DialogModes.NO );
  }
  
  function snl( direction ) {
    
    var select;
    if ( direction == 'up' || direction == 'above' ) {
      select = cTID('Frwr');
    }
    else if ( direction == 'down' || direction == 'below' ) {
      select = cTID('Bckw');
    }
    
    var desc67 = new ActionDescriptor();
    var ref41 = new ActionReference();
    ref41.putEnumerated( cTID('Lyr '), cTID('Ordn'), select );
    desc67.putReference( cTID('null'), ref41 );
    desc67.putBoolean( cTID('MkVs'), false );
    var list17 = new ActionList();
    list17.putInteger( 5 );
    desc67.putList( cTID('LyrI'), list17 );
    executeAction( cTID('slct'), desc67, DialogModes.NO );
  }
  
  function activeLayerID() {
      var ref = new ActionReference();
      ref.putProperty( charIDToTypeID("Prpr") , charIDToTypeID( "LyrI" ));
      ref.putEnumerated( charIDToTypeID("Lyr "), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
  	return executeActionGet(ref).getInteger( stringIDToTypeID( "layerID" ) );
  }
  
  function selectLayerByID(id, add){
     add = (add == undefined) ? add = false : add;
     var ref = new ActionReference();
     ref.putIdentifier(cTID('Lyr '), id);
     var desc = new ActionDescriptor();
     desc.putReference(cTID('null'), ref);
     if(add){
        desc.putEnumerated(sTID('selectionModifier'), sTID('selectionModifierType'), sTID('addToSelection'));
     }
     desc.putBoolean(cTID('MkVs'), false);
     executeAction(cTID('slct'), desc, DialogModes.NO);
  }
  
}
Stephen Marsh
Community Expert
Community Expert
April 18, 2023

Another option, without the visibility limitation:

 

/*
Select Forward layer by Index.jsx
v1.0 - Stephen Marsh, 1st September 2021
Select the forward layer, relative to the current selected layer, regardless of visibility
Note:
Does not cycle through the top layer to the bottom layer
Does not work with layer sets/groups
*/

var forwardLayer = (getActiveLayerIndex() + 1);
selectLayerByIndex(forwardLayer);

function selectLayerByIndex(index) {
    /* https://github.com/ES-Collection/Photoshop-Scripts/blob/master/Remove%20Unused%20Layers.jsx */
    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.putIndex(s2t("layer"), index);
    descriptor.putReference(c2t("null"), reference);
    descriptor.putBoolean(s2t("makeVisible"), false);
    executeAction(s2t("select"), descriptor, DialogModes.NO);
}

function getActiveLayerIndex() {
    /* https://github.com/Paul-Riggott/PS-Scripts/blob/master/getLayersetLayerIDs.jsx */
    var ref = new ActionReference();
    ref.putEnumerated(charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt'));
    try {
        activeDocument.backgroundLayer;
        return executeActionGet(ref).getInteger(charIDToTypeID("ItmI")) - 1;
    } catch (e) {
        return executeActionGet(ref).getInteger(charIDToTypeID("ItmI"));
    }
}

 

Stephen Marsh
Community Expert
Community Expert
April 18, 2023

@mangurian 

 

Perhaps the simplest way is to use ScriptingListener to record the same keyboard shortcut that you would use if doing this via an action using a relative keyboard shortcut ALT/OPT + ] (with the same visibility limitations):

 

/* Select VISIBLE forward or backward layer, skips invisible layers */

selectForwardORBackwardLayer(false, "forwardEnum");

function selectForwardORBackwardLayer(makeVisible, forwardORbackward) {
    var s2t = function (s) {
        return app.stringIDToTypeID(s);
    };
    var descriptor = new ActionDescriptor();
    var list = new ActionList();
    var reference = new ActionReference();
    // "forwardEnum" or "backwardEnum"
    reference.putEnumerated(s2t("layer"), s2t("ordinal"), s2t(forwardORbackward));
    descriptor.putReference(s2t("null"), reference);
    // true or false
    descriptor.putBoolean(s2t("makeVisible"), makeVisible);
    list.putInteger(15);
    descriptor.putList(s2t("layerID"), list);
    executeAction(s2t("select"), descriptor, DialogModes.NO);
}

 

 

mangurianAuthor
Inspiring
April 18, 2023

wow.........I feel so ignorant.  Im did not even know there was a command to select the next layer !!

ALT - ]

mangurianAuthorCorrect answer
Inspiring
April 18, 2023

Thanks to all.  What a great community.