Installing and using the ScriptingListener plug-in

Not all operations are scriptable using Photoshop’s built-in methods. There are a couple of ways to get around this. One is calling a Photoshop Action from your script:

// Which Action(s) to run
doAction("My Great Action","Default Actions");

If you plan to share scripts with other users, this method requires that other users install the script and any Actions the script calls in order to run the desired operations.

The second is using the ScriptingListener plug-in to capture Javascript created by Photoshop to build Actions and incorporate this code directly into your script.

listernerIcon.jpg

Installing the ScriptingListener plug-in:

Quit Photoshop

Locate the ScriptingListener plug-in inside Photoshop’s application folder:

  • Adobe Photoshop CS2>Scripting Guide>Utilities>ScriptingListener

Drag the ScriptingListener plug-in into the folder ‘Automate’ in Photoshop’s Plug-Ins folder:

  • Adobe Photoshop CS2>Plug-Ins>Adobe Photoshop Only>Automate

Launch Photoshop

Using the ScriptingListener plug-in:

As you work in Photoshop, the ScriptingListener plug-in records Javascript for any operation which is Actionable to a log file named ScriptingListenerJS.log, which by default is saved to the desktop on Macintosh, or to the root of your C:\ drive on Windows.

listenerLog.jpg

To determine if an operation is Actionable, double-click the ScriptingListenerJS.log file to launch the Console application. Keep the Console window view of the ScriptingListenerJS.log visible as you are working. You will see the log update if the operation you just performed is Actionable. Painting, for example, is not an Actionable operation. You can click ‘Clear” at any point to clear the entries in the log.

script-Log.gif

As you will notice, the Javascript which is recorded by the ScriptingListener plug-in isn’t always easily read or clearly labeled.

For Example, here is some ScriptingListener Javascript for generating a guide:

// =======================================================
var id8 = charIDToTypeID( "Mk  " );
var desc4 = new ActionDescriptor();
var id9 = charIDToTypeID( "Nw  " );
var desc5 = new ActionDescriptor();
var id10 = charIDToTypeID( "Pstn" );
var id11 = charIDToTypeID( "#Rlt" );
desc5.putUnitDouble( id10, id11, 72.000000 );
var id12 = charIDToTypeID( "Ornt" );
var id13 = charIDToTypeID( "Ornt" );
var id14 = charIDToTypeID( "Vrtc" );
desc5.putEnumerated( id12, id13, id14 );
var id15 = charIDToTypeID( "Gd  " );
desc4.putObject( id9, id15, desc5 );
executeAction( id8, desc4, DialogModes.NO );

Try to get in the habit of recording one step at a time and commenting each operation so you know what it does. I generally record the operation a few times with different settings so I can see where the settings change in the code. In this case, I’ve determined that 72.000000 refers to the pixel position of the guide, and that "Vrtc" is used for vertical guides and "Hrzn" is used for horizontal guides.

Here is the code with some comments:

// Create Vertical Guide
/*This javacript creates a vertical guide 72 pixels in from the left edge.*/
var id8 = charIDToTypeID( "Mk  " );
var desc4 = new ActionDescriptor();
var id9 = charIDToTypeID( "Nw  " );
var desc5 = new ActionDescriptor();
var id10 = charIDToTypeID( "Pstn" );
var id11 = charIDToTypeID( "#Rlt" );
desc5.putUnitDouble( id10, id11, 72.000000 );
var id12 = charIDToTypeID( "Ornt" );
var id13 = charIDToTypeID( "Ornt" );
var id14 = charIDToTypeID( "Vrtc" );
desc5.putEnumerated( id12, id13, id14 );
var id15 = charIDToTypeID( "Gd  " );
desc4.putObject( id9, id15, desc5 );
executeAction( id8, desc4, DialogModes.NO );

You can also turn the Javascript that the ScriptingListener plug-in generates into your own functions. You can even pass in your own variables. In this case, we pass in an integer for pixelOffSet and the string "Vrtc", "Hrzn" for orientation:

function makeGuide(pixelOffSet, orientation) {
var id8 = charIDToTypeID( "Mk  " );
var desc4 = new ActionDescriptor();
var id9 = charIDToTypeID( "Nw  " );
var desc5 = new ActionDescriptor();
var id10 = charIDToTypeID( "Pstn" );
var id11 = charIDToTypeID( "#Rlt" );
desc5.putUnitDouble( id10, id11, pixelOffSet ); // integer
var id12 = charIDToTypeID( "Ornt" );
var id13 = charIDToTypeID( "Ornt" );
var id14 = charIDToTypeID( orientation ); // "Vrtc", "Hrzn"
desc5.putEnumerated( id12, id13, id14 );
var id15 = charIDToTypeID( "Gd  " );
desc4.putObject( id9, id15, desc5 );
executeAction( id8, desc4, DialogModes.NO );
}

Then you can simply call the function every time you want to use it:

makeGuide(100, "Hrzn");

Using an ‘include’ to reference an external script

Another neat trick is to move all of your own functions created using the ScriptingListener into an external .jsx file. Then you can use an ‘include’ to reference the .jsx file with all your functions, keeping the script your working on neat and tidy.

Save your functions in a file ‘myFunctions_lib.jsx’ in the Photoshop’s ‘Scripts’ directory:

  • Adobe Photoshop CS2>Presets>Scripts

Next create a new script. Use an ‘Include’ to reference ‘myFunctions_lib.jsx’ file:

// Includes an external .jsx file

// @include 'myFunctions_lib.jsx'

Note: the ‘Include’ code will execute even though it looks like a comment.

Call the function ‘makeGuide’ from the ‘myFunctions_lib.jsx’ file:

makeGuide(100, "Hrzn");

Save the file as ‘my_script.jsx’ in the Photoshop’s ‘Scripts’ directory:

  • Adobe Photoshop CS2>Presets>Scripts

Run the script called ‘my_script.jsx’.

If you want to comment out an ‘Include’ you can comment it using /* */.

// Includes an external .jsx file

/*// @include 'myFunctions_lib.jsx'*/

4 Responses to Installing and using the ScriptingListener plug-in

  1. forest says:

    I have used the //@include and #include (CS2) for a while now, but recently one or more of the files that I include are not being loaded by photoshop.For example://@include “functions1.js”//@include “functions2.js”//@include “functions3.js”In the debugger I see://@include “functions1.js”//@include “functions2.js”//@include “functions3.js”// ++++++ include “functions3.js” +++++…code for functions3…// +++++++ end ++++++But there is nothing for the top two includes and my script fails because the code in the first two includes is not loaded.Any ideas?

  2. squish says:

    Is there a way to select the layers above and below the current layer?[Yes. You can either use the PS Scripting DOM or Listener code:// =======================================================var id77 = charIDToTypeID( “slct” );var desc20 = new ActionDescriptor();var id78 = charIDToTypeID( “null” );var ref8 = new ActionReference();var id79 = charIDToTypeID( “Lyr ” );var id80 = charIDToTypeID( “Ordn” );var id81 = charIDToTypeID( “Bckw” );ref8.putEnumerated( id79, id80, id81 );desc20.putReference( id78, ref8 );var id82 = stringIDToTypeID( “selectionModifier” );var id83 = stringIDToTypeID( “selectionModifierType” );var id84 = stringIDToTypeID( “addToSelection” );desc20.putEnumerated( id82, id83, id84 );var id85 = charIDToTypeID( “MkVs” );desc20.putBoolean( id85, false );executeAction( id77, desc20, DialogModes.NO );// =======================================================var id86 = charIDToTypeID( “slct” );var desc21 = new ActionDescriptor();var id87 = charIDToTypeID( “null” );var ref9 = new ActionReference();var id88 = charIDToTypeID( “Lyr ” );var id89 = charIDToTypeID( “Ordn” );var id90 = charIDToTypeID( “Frwr” );ref9.putEnumerated( id88, id89, id90 );desc21.putReference( id87, ref9 );var id91 = stringIDToTypeID( “selectionModifier” );var id92 = stringIDToTypeID( “selectionModifierType” );var id93 = stringIDToTypeID( “addToSelection” );desc21.putEnumerated( id91, id92, id93 );var id94 = charIDToTypeID( “MkVs” );desc21.putBoolean( id94, false );executeAction( id86, desc21, DialogModes.NO );- JT]

  3. Brandon Drake says:

    If you are having trouble using this utility with Windows Vista, try right clicking on the Photoshop icon that you use to run Photoshop and select “Run as administrator”.

  4. Grant Freeman says:

    I would like to know if you’ve ever had to translate actions from english to german/spanish?ThanksG[Not personally. We have people on our team that are responsible for translating content. – Jeff]