HTML Panels Tips: #2 Including multiple JSX

Davide Barranca —  — 32 Comments

A simple way to dynamically evaluate multiple JSX files in the Scripting context of Photoshop within HTML Panels.

Back in the Flash world, I used to dynamically include external JSX files via:

Being $.fileName the current JSX file within the above line is written and the File.path call meaning the actual path. Alas, this doesn’t seem to work anymore when HTML panels are involved – the File($.fileName).path once resulted to me, don’t ask me why, as “33” –  which is not a bad approximation to the answer to the Ultimate Question of Life, the Universe, and Everything after all 😉

Anyway, what I personally use now is the following function (in the main.js file):

The key here is the above highlighted line, which is the JS equivalent of the JSX line I’ve been using. To load a JSX – which must belong to the root/jsx folder since it’s hardwired in the function, you would write:

Borrowing code from the Extension Builder 3 boilerplate you can get fancier. The first chunk goes in the main JSX, i.e. the one listed in the manifest.xml, enclosed in the ScriptPath tag:

This instead is what goes in the main.js

loadJSX() (for instance called in the init() function) will evaluate all the JSX files in the predefined folder.

Bonus – System Paths

You may be interested in these ones too (from CSInterface-4.0.0.js)


Print Friendly, PDF & Email

32 responses to HTML Panels Tips: #2 Including multiple JSX

  1. Does it work for .jsxbin files as well?

  2. Hi,
    thank you for your time !
    I try but I have an “EvalScript error.” it desn’t seem to load anything ?


  3. Hi Thanks for posting this content,

    I need to evaluate multiple .jsx files and call the functions from many different file. I tried all the way used in your post but in callback function I’m receiving “EvalScript error”. I works fine if I use single file evaluation method.


  4. Hello Davide,

    I have some problems to get your example running with Photoshop.

    Here is some code:


    /*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
    /*global $, window, location, CSInterface, SystemPath, themeManager*/

    (function () {
    ‘use strict’;

    function loadJSX() {
    var csInterface = new CSInterface();
    var extensionRoot = csInterface.getSystemPath(SystemPath.EXTENSION) + “/jsx/”;
    csInterface.evalScript(‘$._ext.evalFiles(“‘ + extensionRoot + ‘”)’);


    var csInterface = new CSInterface();

    function init() {


    $(“#btn_test”).click(function () {




    /*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
    /*global $, Folder*/


    $._ext = {
    //Evaluate a file and catch the exception.
    evalFile : function(path) {
    try {
    } catch (e) {alert(“Exception:” + e);}
    // Evaluate all the files in the given folder
    evalFiles: function(jsxFolderPath) {
    var folder = new Folder(jsxFolderPath);
    if (folder.exists) {
    var jsxFiles = folder.getFiles(“*.jsx”);
    for (var i = 0; i < jsxFiles.length; i++) {
    var jsxFile = jsxFiles[i];


    function sayAstor(){
    alert("hello from astor.jsx");

    Every time i try it nothing happens? Do you maybe know whats going wrong?

  5. Why didn’t you use #include ‘libs/external.jsx’ back in the ExtendScript world?

    • Good catch, I meant “back in the Flash world”. Yet your question about #include holds, and if we fast forward in the HTML Land, all that I can tell you is that it’s not possible in Photoshop right now – with some caveats.
      Let me explain (I wanted to update the blogpost but I hadn’t had the chance yet).
      #include "thisFile.jsxinc" assumes that the preprocessor looks in the original JSX folder and, well, includes the file – same as #include "./thisFile.jsxinc".
      In the context of an HTML Panel (in Photoshop), there’s a bug so that the original JSX doesn’t know its own path, so he can’t look in “./” for files to include.
      You can easily prove this with File($.fileName).path, which gives an empty string (JSX called by an HTML Panel in Photoshop; in InDesign it works as expected).
      You can still include providing absolute paths – also passing the Extension’s path from the JS to the JSX – but because of the bug I mentioned in the previous comment, everything that’s been evaluated except for the original JSX cannot be used (e.g. functions, etc). No ETA for the fix yet from Adobe’s engineers.

  6. Hi Davide, thank you for your very useful articles!
    From what I understand, I can have multiple jsx files in a jsx folder of extension, and part with
    if(typeof($)==’undefined’) goes into hostscript.jsx file. I have a question here, if I have one file which works depend on some others and I include them to this file through #include ‘someFile.js’. How can we go about this in this case? Should I include this depencdensies through #include ot just simply load this files and throw away includes? And what if apart from .jsx files I have .js files? Do I have to specify it like this?
    var jsxFiles = folder.getFiles(“*{.jsx, .js}”);
    Or is it better just give all my .js files .jsx extension?

    I’m stuck with this and just to solve the problem concatenated all the dependency files into one file and removed #includes, but it doesn’t seem like a good idea. Your reply would be greatly appreciated!


    • Hi Ivan,
      #include doesn’t currently work in Panels, so either you copy&paste code in a single JSX file, or you use multiple tags in the manifest.xml, or you load JSX at runtime in the panel.
      Besides, you can safely rename JS to JSX.

      • Thanks a lot for the quick answer!
        By loading JSX at runtime in the panel you mean example showing in your article above? What about support of html panels (extensions) in previous versions of Photoshop like CS3? Will Photoshop recognize it in CEP->extensions folder? Or should I use different API (not html) for building extensions for earlier versions?

        Thanks in advance

        • Hi Ivan,
          only CC onwards supports HTML Panels, from CS4 to CC (also included) you would need Flash panels, but it’s up to you.
          Both can handle ScriptUI dialogs, so if you absolutely need retrocompatibility, it’s the only path.
          Hope this helps,


  7. First of all, thank you for this excellent blog!

    Regarding this post: I am still unsure what the “$” in

    or csInterface.evalScript(‘$.evalFile(“‘ + extensionRoot + fileName + ‘”)’);

    is all about. Is this some kind of alias imposed by the CSInterface library, or what? If so, what is is set to?

    • $ is an ExtendScript provided utility object, see the documentation in the Javascript Tools Guide PDF, page 216.

      This global ExtendScript object provides a number of debugging facilities and informational methods. The properties of the $ object allow you to get global information such as the most recent run-time error, and set flags that control debugging and localization behavior. The methods allow you to output text to the JavaScript Console during script execution, control execution and other ExtendScript behavior programmatically, and gather statistics on object use.

      • Thank you for providing this information. I am still a little bit stuck since I am trying to use jQuery with my panel extension. Something is not working like I expected. But I will try to figure out what the problem is.

      • OK, I did solve my jQuery issue. As far as I could reproduce “$” is something that is available in the context of running JSX scripts via CSInterface. It is not available to the “surrounding” panel in any way. Also – at least as far as I can tell – objects/functions defined globally by the surrounding panel are not visible when executing the JSX scripts.I wasn’t aware of that before, namely that the JSX scripts get executed in their own “environment” – so to speak. That’s OK with me, now that I understand that. Nevertheless, under some cicumstances the “$” binding leaks through to the panel, making it impossible to use jQuery using the “$” alias, I did circumvent this by using a immediate function in my panel code like this:

        (function($j) {
        // all calls to jQuery will be prefixed by $j instead of $

        • Hi – you’re correct, ExtendScript and Javascript are interpreted by two different virtual machines, the contexts are different. And, mind you, ExtendScript (JSX) is EcmaScript 3rd compatible (no built in support for JSON, etc), while Panels (JS) are now EcmaScript 5th.

  8. Hi,

    I am trying to get the absolute location of the active document. Not in jsx file but in the javascript file that calls the jsx file. I was looking for something like this:

    $pathActiveDoc = csInterface.getSystemPath(SystemPath.app.activeDocument);

  9. Davide,

    I am successfully evaluating multiple JSX files at runtime, however no matter what I try, my main .js only successfully calls functions in the first loaded JSX. I am missing something?

    All the you’ve published has been to helpful. Hoping I’m just doing something silly.

    Thank you!

    • I found the answer…identified ironically by none other than yourself on the CEP github page. After being evaluated, functions contained in external jsx files can be reference if defined as such:

      secondJSXFunction = function() {
      alert(“Hello world from anotherFile.jsx”);

  10. Very useful,solved my big problem!

  11. This solution does not seem to work in Adobe Animate. I get the following error message from this code:
    function loadJSX (csInterface, fileName) {
    var extensionRoot = csInterface.getSystemPath(SystemPath.EXTENSION) + “/jsx/libraries/”;
    csInterface.evalScript(‘$.evalFile(“‘ + extensionRoot + fileName + ‘”)’);

    Error message: A javascript error has occured: ReferenceError: $ is not defined

    • What if you just:

      var csInterface = new CSInterface();

      What happens then?

      • I’m having the same issue with animate. I used your code and also tried the test code above but no luck. I just get the “$ is undefined” error. I’ve also tried the “fancier” code, but I get the problem where animate doesn’t recognize the File and Folder objects. Does animate not support extendscript?

        • I’ve no direct experience of Animate, but to support HTML Panels and not JSX would be crazy (like “here’s your car, oh, no wheels I’m sorry”)

        • Hello. I get the same problem with animate. Also I get a problem if I try to include

          #include “./libraries/json2.js”

          or if i try

          loadJSX(csInterface, ‘json2.js’);

          function loadJSX (csInterface, fileName) {
          var extensionRoot = csInterface.getSystemPath(SystemPath.EXTENSION) + “/jsx/libraries/”;
          // alert(extensionRoot + fileName);
          csInterface.evalScript(‘$.evalFile(“‘ + extensionRoot + fileName + ‘”)’);

          • Hi Davide,

            In Animate I got the same issue. The $ global ExtendScript object does not seem to be available in Animate’s runtime scope. I tried with these configuration in manifest file: , and.

            The error is “$.evalFile is not a function”. I could not find any other official documentation except a section for multiple jsx files ‘CEP_7.0_HTML_Extension_Cookbook.pdf’, but it does not say any about AnimateCC.

            Probably this is a limitation/error for Animate?

  12. I’m trying to fully understand how this all works. I’ve gotten your code and the my version of your code (below) to work, but the code below seems to be a bit more versatile when it comes to interfacing with other files as i can use “var Foo = function()”, or “Foo = function()”, or “function Foo()”. Where as your version, while a lot more dynamic (no need to flip a debug boolean, no need to catch recursive calls), only works with “Foo=function()” for whatever reason.

    I’ve looked it over, done a bunch of tests, but i cannot for the life of me understand why the two approaches give two different results. They appear to be doing the same exact thing.

    It seems like if I attempt to pass the file location from the JS side to the JSX side, that’s when things go wrong. But i’m not sure what’s really causing the issue.

    My version of the code is below; Do you have any idea what’s going on?


    var debug = true;
    var nm = “core.jsx”;
    var loc = “/Adobe/CEP/extensions/com.trane.pstools.cc2017’/jsx”;
    var fldr = (debug) ? new Folder(Folder.userData+loc) : new Folder(Folder.commonFiles+loc);

    if (fldr.exists)
    var jsxFiles = fldr.getFiles(“*.jsx”);
    for (var i = 0; i < jsxFiles.length; i++) {
    if(nm == jsxFiles[i].displayName) continue;
    var jsxFile = jsxFiles[i];
    try {
    } catch (e) {alert("Exception:" + e);}
    else alert("Extensions were not loaded");

  13. Some info regarding the following:

    Alas, this doesn’t seem to work anymore when HTML panels are involved – the File($.fileName).path once resulted to me, don’t ask me why, as “33” …

    In the HTML Extension Cookbooks for CEP version 7.0 and 6.1 there is a section “Load Multiple JSX files” which also describes this behaviour:

    Call “$.evalFile(jsxFile)” to load other jsx files. Probably developers will refer to “$.fileName” to find out the jsx files path they expect. The value of “$.fileName” should be the current executed jsx file path.

    But if the “$.fileName” is referred in the FIRST LOADED jsx file, the value is not correct. That is to say, if the snippet above runs in example.jsx which is referred in the manifest.xml, the error will arise. So, PLEASE AVOID using “$.fileName” in the FIRST LOADED jsx file, maybe this is a limitation in ExtendScript.

    So, it seems to me that this is a bug in the ExtendScript engine. The cookbooks are available here:


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="">