No items found.

When I started writing scripts this was one of the things that got me so confused, and for the right reason. There is not enough information about it on the web, at least not relative to the demand. Most scripts you used before in After-Effects have them, so why does it seem so complicated to achieve?

Let’s break it down to what makes a dockable ScriptUI Panel, well, dockable.

For the final code + TLDR scroll down.

The secret to a Dockable ScriptUI Panel

When I started writing scripts this was one of the things that got me so confused, and for the right reason. There is not enough information about it on the web, at least not relative to the demand. Most scripts you used before in After-Effects have them, so why does it seem so complicated to achieve?

Let’s break it down to what makes a dockable ScriptUI Panel, well, dockable.

For the final code + TLDR scroll down.

Let’s break it down to what makes a dockable ScriptUI Panel, well, dockable.

What’s a Rich Text element?

What’s a Rich Text element?

What’s a Rich Text element?

What’s a Rich Text element?

The rich text element allows you to create and format headings, paragraphs, blockquotes, images, and video all in one place instead of having to add and format them individually. Just double-click and easily create content.

Static and dynamic content editing

A rich text element can be used with static or dynamic content. For static content, just drop it into any page and begin editing. For dynamic content, add a rich text field to any collection and then connect a rich text element to that field in the settings panel. Voila!

How to customize formatting for each rich text

Headings, paragraphs, blockquotes, figures, images, and figure captions can all be styled after a class is added to the rich text element using the "When inside of" nested selector system.

Starting with a Non-Dockable Window

The simplest way to declare a window is the following:

var dialog = new Window("dialog");;

In the first line you create the dialog window, then in the second line you show it. If you run this script an empty dialog would appear. Good!

Best Seller
Recolor entire comps like in Illustrator
Convert an image to a palette like in Procreate
Work with palettes like nowhere else
There is no looking back
Colors is the quick and intuitive Color Sampler Adobe forgot to put into After-Effects. People who used Colors have said they can't see themselves going back to working without it ever again
Key Features
  • Quickly sample frames from photos / videos into a palette
  • Generates beautiful new palettes for you
  • Left-Click to apply Fill, Right-Click to apply Stroke. With no layers selected it will quickly create a new coloured solid for you.
  • Lets you save palettes for easy use across multiple projects
  • Recolor entire comps including nested comps in a few clicks
  • Easily edit palettes
Buy if...
  • You often find yourself feeling uninspired
  • You don't understand color science well enough, finding it hard to come up with beautiful color combinations
  • You are constantly using workarounds to pick colors, including the Character panel's color picker.
  • You feel like After-Effects is holding you back from being a better designer
  • You are often working with references online, importing screen-grabs and manually sampling color palettes
Why Buy?
Good Boy Ninja
75% OFF
Promo ends 30 Aug, 20:00 UTC

Making it dockable

Let’s completely ignore the code above for a second.

In order to make a dockable panel, all we need is one simple line:

var dialog = this;

That’s it? Well, yes, theoretically. Here’s a short explanation:

The word “this” refers to the document itself (yes, the document is an object). In fact, the document is a different kind of object based on whether the script is launched from the scriptUI Panels folder or not. We’ll get to why in a moment.
All you need to remember is that when you launch your script from the ScriptUI Panels folder, the document object is the Panel. We refer to the document object by using the word “this”.

Congratulations! You made a dockable panel. Now please let me ruin the party and tell you all the reasons why it’s actually not as simple as one line of code. Bear with me, this is some good stuff!

Panels ≠  Windows

Our instinct when starting to learn about this is that windows and panels are the same, the only difference is that panels can be docked.
Windows and Panels are actually completely different, and this is where things get complex.
Remember in the first example, when we declared a dialog window, we specifically showed it?;

“.show()” is a method that only exists for windows, not panels.

Notice that we don’t need to call “.show()” for the panel?
When creating a dockable panel you don’t need to specifically show it, but when you are creating a window you do (if you want to see it anyways).
In fact, if you try to call “.show()” on a panel your code will break. “.show()” is simply not part of the things panels can do.

Shape layers on steroids
Why Buy?
Endless Possibilities
Unleash 11 new exciting ways to animate shape layers like the pros
Key Features
  • Reshape, Subdivide, Fractalize and Connect points on your path
  • Instantly add dynamics by sequencing each effect along the path points, making each point animate with a specified delay
  • Reorder the effects for virtually endless combinations
  • Automatically animated to an input wave for instant creativity
  • Plug multiple effects to the same animator for synced motions
Buy if...
  • You are often being told to make an illustration 'breathe' for long loopable projections in keynotes and events
  • You are often asked to add dynamics to boring, regular geometric shapes in logos or symbols
  • You often work with loops, music or other rhythmic elements
  • You are underwhelmed by the limited set of shape animators in After-Effects
  • You are into modular, procedural systems
  • You are looking for hours of fun

You want to work with a window and end up with a Panel

So here’s the thing. When working on a script, you want to be able to quickly launch it from the code editor. Unfortunately, If we declare a panel it would only work when you launch it from the ScriptUI Panels folder. The same script would simply not run from the code editor.

To solve this issue we want the code to basically perform a quick check:
“Is “this” a panel? If it is, use it, otherwise declare a window”.

Here’s how we can do it:

var isPanel = this instanceof Panel;
if (isPanel) {
	var dialog = this;
} else {
	var dialog = new Window("dialog");;

Now let me make this straight, this code is bad and we will get to why in a second.
The first variable is either True or False based on whether the script is launched from the scriptUI Panels Folder or not.
We can then use that variable to create a condition. If it does, declare a panel (using this, as we did earlier). Otherwise, declare a window and show it using “.show()”
This code is easy to read and follow.

We successfully made it possible to launch a window when the script is running from the code editor and launch a dockable panel when we run it from the ScriptsUI Panels folder or not.

But this code needs refactoring. Notice how we are declaring “dialog” twice?
Also, where do you write the rest of your script? Inside the if block? Inside the else block?
This simply is not the way to do it. Instead, we’re going to use a similar logic but using a different structure:

var isPanel = this instanceof Panel; // true or false
var dialog = isPanel  ? this : new Window("dialog");

// rest of script goes here

if (!isPanel) {
	dialog .show();

That is much better. We start with the same “isPanel” variable.
Then we use it in the dialog declaration using a tannery operator which is basically a compact if/else statement.
That way the “dialog” variable will be a panel if the document is a panel and a window if it isn’t. This is a neat way to get the best of both worlds.
This also leaves us space to write the rest of the script. You usually want to create the UI and other script logic stuff before you show the window.
Finally, we are using an if statement to say (“if it’s not a panel, use .show()”).
Remember how we said “.show()” simply does not work for panels? See how we tricked our way around this?

However, we can do better.

Give shapes soft-body like physics,
Create loose-tracking
and smooth slippery motions
Why Buy?
Noodle saves your butt
By adding secondary motions automatically, it will save you from evil clients who ask for too many last-minute changes.

It's the animator's wettest dream.
Key Features
  • Simulate 'soft' / 'delayed' parenting
  • Create 'soft body' like effects by making paths react to layer transforms
  • Adds 'jello' effect to puppet-pin rigs
  • Updates automatically to changes in the original motion
  • Point-by-point control for shape layers squash and stretch
  • Bake / Unbake for maximum performance
Buy if...
  • Your clients often harras you with too many last minute changes
  • You are often facing tight deadlines and looking for ways to animate more easily without compromising on quality
  • Your timelines are often bloated with keyframes
  • You are missing 'soft body' like simulators from other software which do not exist in After-Effects
  • You are animating NSFW illustrations or images and looking for a quick way to add bounce and jiggle to your products

The Final Code

While the code above works, I want to also attach what is common to find online about the topic. Usually, people would recommend to write your script like this:

    var isPanel = thisObj instanceof Panel; // true or false
    var dialog = isPanel  ? thisObj : new Window("dialog", "My Script Name");

    // rest of your script goes here

    if (!isPanel) {
      // if it's a window;
    } else {
      // if it's a panel

Again, don’t panic. This is almost the same as what we wrote before.
The only difference is that the entire thing is written inside a function that launches itself (which has a funny syntax if you are new to JavaScript).

This is a good practice because “this” in javascript can change based on where it is called from. In order to make sure the “this” we want refers to the document, we pass it from outside the function so it’s inside nothing else but the document. We pass it from outside and assign it to a variable called “thisObj” (you can call it anything really, it’s just a variable). Then inside the function, we use “thisObj” to perform all the same checks we performed before.

Also, this code has some additional methods for when the thing is a dockable panel, like “layout” and “resize”. They basically arrange the content of the window when the script is launched.
So this is your final template. You can save this as a snippet so you won’t have to start from scratch.


We learned that writing a dockable panel is actually easy, really easy, we’re talking one-line easy. The hard part is actually making it comfortable for us to work on the script from our text editor. We had to create a block of code that can determine whether the script is running from the ScriptUI Panels folder or not, and based on that whole premise decide whether to build a panel or a window.

That’s why I am writing this blog post. When I started scripting years ago this felt like hell. It feels very unintuitive at first and seems like a whole lot of unnecessary preparation for something that feels like it should be as simple as an On/Off toggle.

This whole thing stems from the fact that Panels and Windows are not of the same kind. We had to write code to adjust for both scenarios.

We also learned that “this”, in the global scope, refers to the document. If you are just starting out you have no way to know this and it’s conceptually weird. But it’s good to know that the type of the document changes based on whether the script is launched from the scriptUI Panels folder or not.

We then wrapped the entire thing in a function and passed “this” from outside, simply to make sure it refers to the document and not to anything else. That function invokes itself, therefore the weird syntax you might not be familiar with.

So in short, there’s a lot to wrap your head around here. Please save this snippet, even if you feel like it’s a little too advanced for where you are now. It’s a good starting point for your scripts and I promise you it gets much easier to read and understand the more you practice writing JavaScript / ExtendScript code.

You can do it!

Good Boy Ninja

Paths from Nulls
Why Download?
What does it do?
It connects existing nulls with a new path
Key Features
  • Connect multiple nulls with a path
  • Choose whether the new path points follow the nulls using an expression or not
  • Hold Alt while hovering the interface to reveal the options to connect other layer types (like solids and footage) instead of nulls
  • Optional: simulate ropes when bringing the new path points closer together
Download if
  • Eager clients often ask you to connect a lot of corporate logos and trademarks with a line, or a dashed line
  • You often import 3D camera tracking data from other software and interested in creating bridges / geometric shapes using the tracked points
  • You are intrested in a free, easy plexus alternative
  • You like free tools!
How to install
the tools of the
Good Boy Ninja?
(Make Money)
Good Boy Ninja
Motion Designer since 2008.
Maker of tools for Adobe After-Effects
Quick jump:
August 22, 2021
Similar Posts