Skip to main content

Module 6 β€’ Lesson 1πŸ’» JavaScript / UXP Scripting in Depth

Actions replay fixed steps; scripts think. With a little JavaScript you can loop over files, branch on logic, do math, and reach parts of Photoshop no Action can touch. You don't need to be an engineer β€” you need to read, adapt, and run code, and this lesson makes that concrete.

πŸ“š What You'll Learn

By the end of this lesson, you will be able to:

  • Explain the Photoshop DOM: app β†’ documents β†’ layers β†’ properties
  • Tell ExtendScript (.jsx) from modern UXP JavaScript, and when each applies
  • Write loops and conditionals β€” the logic Actions can't express
  • Read and adapt a complete script (and run it via File β–Έ Scripts)
  • Reach for batchPlay when the DOM doesn't expose something

⏱️ Estimated Time: 60 minutes

🎯 Project: One adapted, working script that does something an Action can't β€” a per-file decision or a computed output.

In This Lesson

πŸ‘€ The Goal: Steps That Think

An Action does the same thing every time; a script decides. On the right, an Action blindly replays fixed steps β€” it can't ask "is this one landscape?" or "how many layers are there?". On the left, a script loops, checks conditions, and produces different, correct output per file. Logic is the whole difference. Drag the handle:

Script (logic) Action (fixed)
A diagram of the principle. The moment a job needs a decision β€” per-file, per-value, per-condition β€” you've outgrown Actions and want a script. Logic is the line between the two.

🧠 Mental Model: The DOM

A script drives Photoshop through its Document Object Model β€” a tree of objects you read and change. At the top is app; it has documents; each document has layers, a width, a color mode; each layer has a name, opacity, blend mode, bounds. Scripting is just walking that tree and setting properties: "for each document, for each layer, if the name starts with 'BG', hide it." If you can describe the task as objects and properties, you can script it.

app .documents[] .layers[] .name .opacity.blendMode .bounds app.activeDocument.layers[0].opacity = 50; // walk the tree, set a property
Figure 1: The DOM is a tree of objects and properties. Scripting is navigating it and changing values β€” the same mental model whether you use ExtendScript or UXP.

βš–οΈ ExtendScript vs UXP

Two scripting worlds coexist. ExtendScript (.jsx) is the legacy engine: old-JavaScript, a mature DOM, run instantly via File β–Έ Scripts β–Έ Browse β€” perfect for quick automation and the vast library of existing scripts online. UXP is the modern platform: current JavaScript, async APIs, and the foundation for plugins with real HTML/CSS panels (Lesson 6.2). For a one-off batch job, ExtendScript is often the fastest path; for a tool you'll ship or give a UI, use UXP.

File β–Έ Scripts
Image Processor… Export Layers to Files… Load Files into Stack… Browse… ← run your .jsx UXP plugins load via the plugin panel (Lesson 6.2), not this menu
Figure 2: File β–Έ Scripts β–Έ Browse runs any .jsx immediately β€” the fastest way to run and test automation. The built-ins above (Image Processor, Export Layers) are scripts too.

⚠️ Copy-adapt before you write from scratch

You rarely start with a blank file. The web is full of Photoshop scripts for almost any task; the real skill is reading one, changing the values and logic to fit, and testing on a copy. Treat scripting like LUTs or brushes β€” a library to draw from, not a language to memorize.

🧾 A Script That Loops & Decides

Here is a complete, readable ExtendScript that does something no Action can: loop every open document, branch on its orientation, and export each at the right crop and multiple sizes. Read it top to bottom β€” you can already follow every line.

// smart-export.jsx  β€”  File β–Έ Scripts β–Έ Browse to run
var sizes = [2000, 1000, 500];              // long-edge sizes to export
var outDir = new Folder("~/Desktop/export");
if (!outDir.exists) outDir.create();

for (var d = 0; d < app.documents.length; d++) {
    var doc = app.documents[d];
    var wide = doc.width.value >= doc.height.value;   // a decision Actions can't make
    var ratio = wide ? (16/9) : (4/5);

    for (var s = 0; s < sizes.length; s++) {
        var copy = doc.duplicate();             // work on a throwaway copy
        cropToRatio(copy, ratio);
        var scale = sizes[s] / Math.max(copy.width.value, copy.height.value);
        copy.resizeImage(copy.width * scale, copy.height * scale);

        var name = doc.name.replace(/\.[^.]+$/, "") + "_" + sizes[s] + ".jpg";
        var opt = new JPEGSaveOptions(); opt.quality = 10;
        copy.saveAs(new File(outDir + "/" + name), opt, true);
        copy.close(SaveOptions.DONOTSAVECHANGES);
    }
}
alert("Exported " + app.documents.length + " docs Γ— " + sizes.length + " sizes.");

function cropToRatio(doc, r) {                 // reusable helper
    var w = doc.width.value, h = doc.height.value;
    if (w / h > r) { var nw = h * r; doc.crop([ (w-nw)/2, 0, (w+nw)/2, h ]); }
    else            { var nh = w / r; doc.crop([ 0, (h-nh)/2, w, (h+nh)/2 ]); }
}

βœ… When the DOM can't, batchPlay can

Some features aren't exposed as tidy DOM properties. Both engines let you replay a recorded low-level command β€” Action Descriptors in ExtendScript, batchPlay in UXP β€” captured with the ScriptingListener plugin or the UXP alchemist tool. It's less pretty, but it means anything you can do in the UI, you can script.

πŸ› οΈ Guided Build: Adapt a Script

Start from the script above (or any script you find) and make it yours.

Step 1: Run it as-is Β· 8 min

  1. Open a few documents. Save the script as smart-export.jsx and run it via File β–Έ Scripts β–Έ Browse. Confirm the export folder fills up.

Step 2: Change the values Β· 8 min

  1. Edit the sizes array and the JPEG quality. Re-run and confirm your changes took effect. You're editing behavior without writing anything from scratch.

Step 3: Add logic Β· 12 min

  1. Add a condition: skip documents already under a certain size, or add a third ratio for square. One if is a capability an Action simply lacks.

Step 4: Make it safe Β· 6 min

  1. Wrap the work in try/catch so one bad file doesn't halt the run, and log failures. Now it's a tool, not a toy. πŸ†

βœ… Project Completion Checklist

  • ☐ Ran an existing script successfully via File β–Έ Scripts
  • ☐ Edited its values and confirmed the change
  • ☐ Added a conditional β€” logic an Action can't do
  • ☐ Wrapped it in try/catch with error logging
  • ☐ Understand where batchPlay/descriptors fit

πŸ§— Now You: Solo Variation

🌟 Your challenge

  1. Write a script that renames or hides layers by a rule (e.g., hide every layer whose name starts with "ref").
  2. Adapt an "export each layer as a PNG" script you find online, and add a filter so it only exports visible layers.
  3. Record a UI action with the ScriptingListener, then paste the descriptor into a script β€” your first taste of scripting the un-exposed.

Going further: read Adobe's UXP scripting docs and port one of your ExtendScripts to UXP JavaScript. The concepts transfer; the syntax modernizes.

🍳 Recipe Card: Scripting

Walk the tree, add the logic

  1. Think in the DOM: app β†’ documents β†’ layers β†’ properties
  2. ExtendScript (.jsx) for quick jobs; UXP for panels/tools
  3. Use loops + conditionals for what Actions can't do
  4. Copy-adapt existing scripts; test on copies
  5. batchPlay/descriptors for un-exposed commands; wrap in try/catch

Mantra: if you can describe it as objects and decisions, you can script it.

πŸ““ Learning Journal

Add to your journal after this lesson:

  • Key concepts you learned
  • Techniques that clicked for you
  • Questions or confusion points to revisit
  • Ideas you want to try
  • Your progress and feelings about learning this

✍️ This lesson's prompt: What repetitive task in your workflow needs a decision Actions can't make? That's your first real script β€” describe it as objects and conditions.

πŸ”­ Where This Leads

A script runs from a menu; a tool has a face. Next: Lesson 6.2 β€” Building a Panel / Plugin, where UXP turns your scripts into a real HTML/CSS panel with buttons, docked inside Photoshop.

Do I have to learn "real" programming for this?

Not to be effective. Reading, adapting, and running scripts covers most professional needs and is a learnable-in-a-weekend skill. Deeper programming unlocks more, but the ROI on "can adapt a script" is enormous on its own.

ExtendScript is old β€” should I ignore it?

No. It's mature, instantly runnable, and backed by a huge library of existing scripts, so it's often the fastest way to solve a one-off. Learn UXP for anything you'll ship or maintain, but ExtendScript is still a productive tool today.