HTML Panels Tips: #11 CEP Events (ExternalObject)

Davide Barranca —  — 6 Comments

The new CEP5 (from Photoshop CC 2014 onwards) has introduced the possibility to dispatch Custom Events from JSX and listen to them in the HTML Panel – this Tip shows you how to implement this communication.

Events et al.

I’ve already covered Events in this series, so let me summarize what we can do with them and the different kinds of Events we might deal with.

  1. CEP Host Application Events – i.e. Photoshop events related either to the app itself or the documents (but from the “host app point of view”, see this post) such as:
    • appOffline
    • appOnline
    • applicationActivate
    • documentAfterActivate
    • documentAfterDeactivate
  2. ExtendScript Events – i.e. Events related to actual Photoshop operations (dispatched when the user creates new Layer, selects/moves something, etc), see this post and a different approach.
  3. Custom ExtendScript Events – i.e. Events you dispatch yourself in the JSX to communicate with, and pass data to, the HTML Panel (what this post is all about).


Photoshop, Illustrator and Premiere Pro CC 2014 by the time of this writing (July 2014) support natively the dispatching of custom Events (using the PlugPlugExternalObject – which library is embedded in the app and we can happily forget about it), while InDesign must explicitly add and reference it (download it here and see the SDK Guide at pag 45).

Basically you set an Event Listener in the JS for a custom event (named as you like), providing a callback. Then in the JSX you create and dispatch a CSXSEvent() at will.


You can download a full panel from my PS Panels Boilerplate repository on GitHub here. As follows some code highlights to demo the mechanism.


In the JS side there’s a simple EventListener with a callback as usual.


In the JSX you create an ExternalObject instance: "lib:\PlugPlugExternalObject" is the only parameter to pass. If there’s no error (the library exists and it’s available) you create a new CSXSEvent setting the type (which is referenced in the EventListener – the string must be the same, in the example “My Custom Event”) and a data property which is the payload that the HTML Panel is going to receive.

JSX2CEP-panelIn the GitHub panel things are slightly more elaborate: I’ve set a JSX function triggered by a button – which sends Custom Events spaced 1 second each. The Events’ payloads are then logged in a textarea.

I’m facing two issues, though. First, I would expect that the log messages come time spaced (first log, 1″ wait, second log, 1″ wait, third log, 1″ wait, etc), while the get to the textarea all together.

Second, the [Return Message…] which comes as the result value passed to the evalScript() callback appears as the first, and not last, log.

As far as I understand, the Events are kept on hold until the whole JSX routine is done and the evalScript() callback executed – whether this is a problem of Event dispatching (the Photoshop / ExtendScript side) or Event listening (the JS / HTML Panel side) I can’t really say.


A Twitter conversation withthe digital artist Sergey Kritskiy led me to experiment whether the Panel is able to listen for CSXSEvents dispatched only from its own JSX files (the ones in its scope), or not. In other words, can an (open) HTML Panel fire a callback in response to a Custom Event of the right type coming from whatever Script might happen to run in Photoshop in that moment?

The answer is yes: in fact if you keep the JSX to CEP Communication panel open and run in the ExtendScript ToolKit the same chunk of code provided in the JSX section above in this very post, the Panel shows “some payload data…” in its textarea.


Print Friendly, PDF & Email

6 responses to HTML Panels Tips: #11 CEP Events (ExternalObject)

  1. Awesome !
    I was able to make up the extension What to your post.
    Thank you.

  2. Hi davide,

    I have following queries about custom extendscript listening.
    1. Is it possible to set an InDesign object say(Document object) reference to event data field and use it in the HTML panel.
    I did following but not work let me know what I am missing.
    // JS code
    new CSInterface().addEventListener(“myCustomEvent”, function(evt) {
    console.log(; // here I am not getting the document object.

    // jsx code
    try {
    var xLib = new ExternalObject(“lib:\PlugPlugExternalObject”);
    } catch (e) {

    function mainRoutine() {
    var doc = app.activeDocument;
    if (xLib) {
    var eventObj = new CSXSEvent();
    eventObj.type = “myCustomEvent”; = doc;

    2. How to set an array of objects in the field

  3. HY,
    I’m working with InDesign scripting and I was wondering if there is and event that fires on every deleted page, I’ve looked up in loads of places but I can’t find anything…
    any clue?

  4. Great – this worked well for me ! Thanks for your help.

  5. Hi, guys.
    For whatever reason the event appears to dispatch only if I include this ‘alert(“Hello?”)’ call in the
    ‘if (xLib)’ check before ‘eventObj.dispatch();’. Otherwise the event won’t seem to dispatch.
    Why is that?
    if (xLib) {
    var eventObj = new CSXSEvent();
    eventObj.type = “My Custom Event”; = “some payload data…”;
    alert(“Hello?”);//This is what makes it work? How and why?
    (The app in question is AE CC, but I doubt that matters.)

    • UPDATE:
      It later occurred to me to dispatch the event with a slight delay and see if that worked. (I accomplished this by wrapping ExtendScript’s native $.sleep() function inside a $.setTimeout alias as discussed here)

      if (xLib) {
      var eventObj = new CSXSEvent();
      eventObj.type = "My Custom Event"; = "some payload data...";
      $.setTimeout(function () {eventObj.dispatch()}, 500);
      $.setTimeout = function(func, time){

      I supposed I could settle for this work-around for now, but I’d really like to understand the problem.

Leave a Reply

Text formatting is available via select .

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">