Académique Documents
Professionnel Documents
Culture Documents
CC 2018 Edition
The Book
28 Panels
Davide Barranca
This book is for sale at http://htmlpanelsbook.com
This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing
process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and
many iterations to get reader feedback, pivot until you have the right book and build traction once
you do.
© 2016 - 2017 Davide Barranca - Adobe® Photoshop® and Adobe® Creative Cloud® are registered
trademarks of Adobe Systems Incorporated in the United States and/or other countries. All other
trademarks are the property of their respective owners.
To my wife Elena
Contents
Foreword . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iv
Why I wrote this book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . iv
Audience and Assumptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v
What this book is, and how to read it . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vi
What this book is not . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii
What you need to get started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii
Version History and Errata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . viii
Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x
Piracy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x
1. Photoshop Extensibility . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Plug-ins (Photoshop SDK) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
Flash Panels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
HTML Panels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
5. CSInterface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
JS interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
CEP Versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
evalScript() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
getSystemPath() and including multiple JSX . . . . . . . . . . . . . . . . . . . . . . . . . 38
7. Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
No shortage of Events in town . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
Host Application Events - ExtendScript Events in Photoshop . . . . . . . . . . . . . . . . 58
Host Application Events - CEP Application Events . . . . . . . . . . . . . . . . . . . . . 64
Custom ExtendScript Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Custom CEP Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
CEP Panel’s Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Demo Panel: Photoshop ExtendScript Events . . . . . . . . . . . . . . . . . . . . . . . . 71
Demo Panel: Photoshop CEP Events (LoseFocus) . . . . . . . . . . . . . . . . . . . . . . 73
Demo Panel: Photoshop Custom ExtendScript Events . . . . . . . . . . . . . . . . . . . . 74
Demo Panel: CEP Custom Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
8. Styling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Matching the Host Application UI look . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Synch with Photoshop Theme changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Flyout and Contextual menus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Icons, Size and Retina Displays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Demo Panel: Flyout and Contextual menus . . . . . . . . . . . . . . . . . . . . . . . . . 95
Demo Panel: High PPI display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
9. Node.js . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Two of a kind . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
Importing modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
Contexts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
CONTENTS
Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
Copyright . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
Foreword
We are all aware of the possibilities of automating and expanding the functionality of Adobe
applications. Many people, surely, would like to learn the art of programming, so as to add such
functionality, to make their workflow more productive and adapted to their personal needs.
Now that we can create Extensions for Creative Cloud applications, all this has been made possible.
Adobe Configurator, although misunderstood throughout its life, was the tool that allowed even the
less experienced to approach this magical world. Its removal from the scene has limited such access
to programmers, who can only navigate the process of creating Panels and Extensions in the new
HTML format with great difficulty, owing to the lack of adequate documentation.
Of course, nothing is difficult for programmers with considerable experience or a great aptitude for
the subject. Thanks to the talented Davide Barranca, who combines both attributes, we are now
fortunate enough to have a complete and comprehensive guide. He has learned everything in the
field with steady work, passion, dedication and many headaches! For this reason, his work really
needs no introduction, guarantees, or recommendations. A quick trip to the web will demonstrate his
capabilities, the quality and professionalism of his work and the support he has given to the entire
developer community. His blog has quickly gone viral and has offered solutions and information
valuable both to neophytes and the most experienced.
I have known Davide since his first forays into this field. What distinguishes him is his constant
study, his perseverance in the search for solutions, and the tenacity with which he deepens every
aspect of programming.
The difficulty of obtaining information and the sudden changes in requirements caused many, albeit
reluctantly, to abandon the development of extensions. To say nothing of the beginners who did not
enter the field for fear of being stranded on a desert island!
Like a boat in a fierce storm, or in a minefield, those who are not well equipped and aware of the
problems they face risk being shipwrecked. The solution is training, and the exchange of information
and experiences.
The interchange of ideas, the sharing of a project, the grasping of a new technique, is much easier in a
collaborative environment. Learning what others have experienced, and sharing common problems,
is often the easiest path, assuming that colleagues share the same goals. But how do we overcome
the lack of information?
Special-interest online discussion groups are today’s equivalent of that collaborative environment.
They are places where neophytes and experts can each find complete responses and partial solutions
to their problems. Google searches, blogs and private sites of independent developers, open source
communities such as the social network GitHub can also be quite useful for tapping into resources,
collaborating on a project, and/or putting information at the disposition of the community. So,
despite all the difficulties, there is some sharing of this ocean of knowledge.
Foreword ii
We must therefore know how to glean the exact information needed for our specific needs, to find
the one best suited to our particular problem. And time is also a factor: it is essential to get quick
answers, so as to concentrate more on the real problems instead of spending whole days in research,
and ending up with a fistful of nothing. It can be an exasperating experience that in most cases yields
only partial answers. And the information on how to create an HTML extension is as fragmented
as it could possibly be.
There is no one place to find all the explanations and the assembly of concepts, and the search for
it is likely to be frustrating and debilitating. What is lacking is a place where experts and novices
can find everything needed for a proper and rapid development, allowing free rein to creativity and
inventiveness.
This material, however, gets us only halfway there, since in most cases the transition from theory to
practice does not occur without problems. The rest of the process depends on our own energy and
capacity. But where can we find the correct, complete, exhaustive and effective presentation of the
basic material? For me there is no doubt, it is right here in the pages of this book.
Davide has supplied the missing link, the manual that each type of developer needs. Like the Never-
Neverland of Peter Pan, it is a place to discover yourself and explore your own passions and resolve
your own difficulties. He has put his knowledge and experience at our disposal without reserve, not
just to put us in a position to execute our projects but also to recognize pitfalls. The book is rich in
advice and tricks to get around obstacles and avoid confrontations with the evils that inevitably lurk
around the corner.
Every successful enterprise is the fruit of great work and great passion. Thanks to Davide’s
extraordinary teaching abilities, Photoshop HTML Panels Development leads the reader down a
stable and well-defined path. You will be taken step by step, with effective examples and clear
concepts, from a comprehension of the terminology, to a knowledge of the architecture on which
the extensions are based, to the completion of commercially ready products, and finally to the
considerations of how to market them. Above all, you will learn to comprehend the reasons and
concepts behind each step, and thus to achieve the autonomy to develop and create your own
extension. Adding to the completeness of the information, Davide has made all the resources
available on the web.
Photoshop HTML Panels Development is a book suitable for everyone. The beginner will find it a
great way to start, but even top experts will discover new and useful resources.
To the great envy of many, I was lucky enough to read this book during all stages of its drafting. I
myself have discovered ways to integrate and take advantage of new and interesting features, which
allowed me to bring to life certain older projects that were in an embryonic state because I had not
been able to overcome various problems by myself. Davide’s demonstrations and explanations will
be equally valuable for whatever my next projects may be.
I am sure that this book is well worth whatever time you spend on it. As for money, a friend once
told me that one should find at least five good reasons before spending it. I agree, and here are some
of mine.
Foreword iii
I could easily name more than five reasons but I think these are by far sufficient. I just want to add
a note for all of those who have asked me where to start in this field. The answer is now official.
Without this book will be a long and uphill road.
It is not hard to predict the question that comes spontaneously to your mind at this time. Why should
I pay any attention to the words of Giuliana Abbiati? Who is she, and what has she ever done to
qualify her to give me such advice?
I am perhaps the wrong person to ask this of, but I will give you an answer anyway. I could be any
one of you. Titles have little importance in my opinion. They do not always guarantee objectivity.
What is certain is that I have seen every problem involving the creation of panels and extensions,
and if I had had a book like this at my disposal it would have saved me from a thousand moments of
despair and dozens of unnecessary tests. I believe that the same would apply to Davide, with whom
I have shared such moments.
I hold Davide in the highest esteem, and I thank him not only for his work and for the free resources
that he has always put at the community’s disposal, but also for flattering me with the opportunity
to give my personal opinion about the quality and utility of this his first book, and last but certainly
not least for the sincere friendship that has bound us together for many years.
And now, the interesting part: Photoshop HTML Panels Development by Davide Barranca.
Giuliana Abbiati
Author of CPT - Channels Power Tool1 , and Dan Margulis’ PPW Panel2
1
http://www.cs-extensions.com/products/cpt/
2
http://www.moderncolorworkflow.com/free-resources
Introduction
Whether you’ve just bought this book or you’re reading here to make sure it fits your needs and level
of expertise, welcome to the introduction of Adobe Photoshop HTML Panels Development. This
Chapter will shed some light on Creative Cloud Extensions, the reason why they are an interesting
coding experience, and a profitable business too.
Extensions can be turned into a profitable venture: the more you invest on it, the better the yield, of
course.
This book has been written to show you how I’ve been doing it.
• Photoshop
• InDesign
• InCopy
• Illustrator
• Premiere
• Prelude
• After
• Animate
• Audition
• Dreamweaver
• Muse
• Bridge
Excluding some Event-specific parts, I’d say that most if not all of the code shown in this book, and
the whole marketing section, apply to any other Creative Cloud app mentioned above - which has
been corroborated by beta readers who work on InDesign and Illustrator - so you’re going to make
good use of this book even if your main focus is not on Photoshop.
HTML Panels are Web Applications hosted inside, and communicating with, Adobe Creative Cloud
apps. As a developer, you’ll be writing code related to the Panel’s functionality (using the HTML +
CSS + JS stack) and code related to the Host Application operations (Photoshop Scripting, InDesign
Scripting, etc. that is, ExtendScript language).
Introduction vi
If you are totally new to whichever form of coding, I’m afraid this book would be a waste of time and
money: I’d suggest you to take one of the many available free or paid courses on Web Development
first. Enjoy that stack? Come back here and you’ll find new challenges.
If you have an Adobe Configurator background and/or a very basic Javascript / ExtendScript
experience you’ll probably be OK until Chapter 6, that brings you to the point where you know
how build HTML Panels calling Actions in ActionSets, which is what a large majority of former
Configurator users are after. However, it won’t be the kind of book that you can skim through,
picking here and there and jumping to the Demo code straight away. If you’re looking for that kind of
thing, my friendly bit of advice is to look elsewhere. From Chapter 7 onwards, you’ll definitely need
supplementary, supporting material alongside this book, like dedicated CSS / JS / Node.js courses,
otherwise you won’t be able to retain and make the most of what is shown there - and it’s alot. Mind
you I don’t want to sound discouraging, but realistic: a path from the average Configurator user to
the average HTML Panels developer is indeed possible, and this book has been written also for you.
It just requires planning and extra resources, there’s no reason for me to skate over this and allure
you with copywriting tricks.
If you come from good old Photoshop scripting (that’s my own background, so I’m sympathetic),
I assume that you have a fine grasp of ExtendScript - which is nothing but a Javascript superset.
HTML Panels for sure have their own quirks, but you can definitely enjoy the process of learning
how to build them. Get ready to pay frequent visits to StackOverflow and the Mozilla DevNet, since
Web Development is the kind of tree that branches up to the stratosphere and beyond; luckily, if you
want to go into it in more depth, there’s no shortage of resources on the internet.
Conversely, if you are a Web Developer willing to exploit the power of Adobe Creative Cloud
applications, you’ll get easily into the part of the HTML Panel builder: Photoshop scripting will
look quite convoluted at first, but you’re going to get used to that in a reasonable amount of time.
In case you’re the King of the Keyboard and you know Photoshop like the back of your hand, please
have my seat and enjoy the ride.
examples: the way Panels deal with the host when it comes to app-specific Events, how to save
mutable data or successfully sign and timestamp a product for submission to the Adobe Add-ons or
other stores, etc.
Moreover, it is a collection of personal researches on the topic of Photoshop panels, countless hours
spent dealing with experienced people on forums, blogging, submitting bugs and feature requests
to, and discussing them with, Adobe’s engineers.
Adobe Photoshop HTML Panels Development is a tool that will give you an invaluable productiv-
ity head start, equipping you with an arsenal of tested and proven work solutions to the problem of
building and marketing Photoshop and Creative Cloud panels - that I put in practice myself running
my own daily business as an Extensions producer.
Especially If you’re green on development, I urge you to read it from start to finish, because it’s been
designed to slowly build up your skills: each chapter is a prerequisite of the one that follows, and
uses tools and knowledge coming from previous sections.
The book also contains 28 Demo Panels, a true bonanza! Don’t skim through the writing to focus
just on code, though: they usually are a more elaborate example of what’s been discussed during the
chapter, and without a solid understanding of the basics that have been laid out in the text, you’re
going to loose a lot of their potential learning value.
Much water has passed under the bridge… Long story short, the Javascript libraries are now free for
you to grab on GitHub, so the requirement list shrinks to:
You can develop on both OSX and Windows - I strongly suggest you to test the other platform
before submitting your product to marketplaces, since running into platform-specific bugs is not
unfrequent. I use Parallels9 on a Mac, but different solutions are available.
Mind you, running Photoshop in a virtualized OS might require you to deactivate it on a different
machine, if you’ve exceeded the number of maximum Creative Cloud activations. Also, be aware
that virtualizing software such as VMWare10 can capture by default modifiers keys (e.g. the meta on
Mac), so you may need to remap some of your keyboard shortcuts.
This icon will signal you that a Panels’ issue has been resolved from a particular Photoshop
version onwards, and the code working around that problem has to be intended for
backwards compatibility only. Over time, I hope to fill this book with lot of Peace & Love
fingers.
• New: added support to Photoshop CC 2017 (even if it still features CEP7, like CC 2015.5).
• New: added a section on Native Mac and Windows installers to Chapter 14.
• New: added a workaround for Google Chrome (v54.x) broken Enter key in the Console.
• New: mentioned the Spectrum UI CSS in Chapter 8.
• New: I’ve now, once and for all, switched to Vue.js as my JS framework of choice, so this is
what I endorse now on Chapter 11.
• Fix: included Adobe Audition 8 in the list of supported applications.
• Fix: footnote (page 50).
• Fix: typos here and there, minor changes.
• New: Adobe Photoshop CC 2015.5 (despite what you’d think, a major version: 17.0) has been
released June 21st, 2016. CEP has been bumped to version 7.0. I’ve updated all the book, where
needed, to cover the new version.
• New: mentioned Extendscriptr, page 8.
Introduction x
• New: added cefclient and Chrome Dev Tools scrolling fix, page 26.
• Fix: Gabe Harbs’ website link (sorry!), page 26.
• Fix: added a note on “User Cancelled Error” on CC 2015/Windows for the Actions panel, page
50.
• Fix: color in Panel’s icons is in fact allowed, page 92.
• Fix: typos here and there, minor changes.
Feedback
I’d love to hear from you! What is your background, what you’re going to build next, whether
you’ve found this book a good fit or not, and why. If you want to share your thoughts, let me know
at davide.barranca@gmail.com.
Piracy
This book is going to be pirated, like most of the published books, magazines and newspapers for
sale in the digital world. Some would also say that it’s a good thing, other would raise the “let the
one who has never sinned throw the first stone!” argument.
Since it’s very likely that you, the reader, have picked this book because you want to build a business
on top of Extensions yourself, I am confident that you have paid, or will very soon pay, to obtain a
legitimate copy and repay my efforts.
Because if you’re successful in building HTML Panels, you’ll be in my own shoes yourself - very
soon - and you don’t want this to happen to you too, do you? Thank you.
1. Photoshop Extensibility
“In the beginning the Universe was created.
This has made a lot of people very angry and been widely regarded as a bad move.”
-Douglas Adams
Overview
Let’s have a look at the bouquet of options you have as a Photoshop developer - HTML Panels are
not the only choice, and you might want to explore alternatives; either to add features, or broaden
retro-compatibility.
The Photoshop extensibility layer grew over time - as follow a brief overview of what is, and
historically has been, available.
In some cases, Plug-ins are actual stand-alone application whose interaction with Photoshop is
limited to getting and injecting back image data.
11
http://www.adobe.com/devnet/photoshop/sdk.html
1. Photoshop Extensibility 2
Unless you have a good knowledge on both the language and the related tools, plug-ins programming
is possibly the steepest path on Photoshop enlightement.
Scripting
With a script you programmatically drive Photoshop; most of what is not available in the DOM
(Document Object Model - pretty much incomplete if compared to, say, InDesign), is within your
reach using ActionManager code: not the brightest example of API usability, but a tremendous power
at your disposal.
You can script Photoshop using AppleScript on Mac, Visual Basic on Windows, or Extendscript on
both platforms. In fact, there are three distinct layers of scripting available within Photoshop, as
follows.
1. Photoshop Extensibility 3
Extendscript
Extendscript (a superset of Javascript12 ) is the foundation of scripting in a variety of other Creative
Cloud applications (Bridge, Illustrator, InDesign, etc), and it’s what you’re going to use to impart
commands to the host app from within HTML Panels.
Using the peculiar ScriptUI class, you can build Graphic User Interfaces as well, like:
Scripting and scripted dialogs are retro-compatible back to CS3 and earlier, if you don’t mind
distributing unobfuscated (plain) code.
12
ECMA-262, plus EX4 (ECMA357), plus Adobe’s non-standard stuff like Filesystem management, Reflection interface, operator overloading,
etc.
1. Photoshop Extensibility 4
Generator
First released with Photoshop CC (14.1), Generator has been primarily marketed14 as a technology
that lets you export images in background, based on layer names. Actually, there’s much more: a
Node.js server that communicates with Photoshop via Kevlar API (Extendscript), and exposes an
Event based API for third-party plugins - mainly using Generator to access/extract resources from
within Photoshop. Panels can talk to Generator too.
From the very beginning, it has been open-sourced on GitHub15 .
Flash Panels
The first Photoshop Panel appeared back in CS4 and was based on a framework called PatchPanel,
which never left Adobe Labs16 (the Labs are sort of an experimental technology preview: that might,
or might not, find a way to actual Adobe products). According to conventional wisdom, one of the
main promoters of customizable panels has been the former Photoshop Product Manager John Nack,
now at Google. It was of course a Flash thing, because those were the Happy Flash Days at Adobe17 .
Flash Panels are supported from CS418 up to CC (Photoshop v.16) included: they were built in
Flex/ActionScript using Flex Builder (Adobe’s customization of Eclipse) as the IDE, with the help of
a plugin called Adobe Extension Builder. Strange as it may sound, Extension Builder v2.119 is still
available as a paid subscription for about EUR 10 per month, as opposed as the v3.020 targeted to the
newer HTML Panels, which is free.
One of the main catches of Flash Panels, with hindsight, is that you were lured to write all of your
Photoshop code directly in Actionscript - being the alternative to keep the Extendscript and just
13
http://ionic.io
14
http://blogs.adobe.com/photoshop/2013/09/introducing-adobe-generator-for-photoshop-cc.html
15
https://github.com/adobe-photoshop/generator-core
16
http://labs.adobe.com
17
Tons of Flash history and nostalgia in this article.
18
Photoshop CC2015.0.1 implements Node version 0.8.22 (log “process.version” to get it), CC2015.1.1, CC2015.5 and CC2017 use the io.js branch
v.1.2.0; CC 2018 has Node 7.7.4. Generator relies on a Node.js different version (currently 4.8.4 - find the Generator’s node executable in Adobe
Photoshop CC 2018.app/Contents/MacOS/ and run ./node -v).
19
http://www.adobe.com/it/products/adobe-extension-builder.html
20
http://labs.adobe.com/technologies/extensionbuilder3/
1. Photoshop Extensibility 5
evaluate it, inelegantly going back and forth from the Panel to Photoshop21 , and vice versa. Two
problems:
1. Actionscript is strongly typed, Extendscript is not. If you’re used to typecasting (i.e. implicitly
change the data type, say, from String to ArtLayer) you will spend an awful amount of time
trying to fix loosely typed code that suddenly stops working.
2. Developers who wrote and maintained Actionscript libraries for Photoshop have found
themselves empty handed when the wind changed to HTML - facing the burden to re-rewrite
their whole codebase back in Extendscript.
In order to let Flash Panels spread to a bigger audience, Adobe released Configurator22 , a visual, drag
and drop utility to create Panels without coding experience. Even if it didn’t support the whole range
of User Interface tools provided by Extension Builder, some remarkable extensions23 have been built
with it.
Its popularity grew slowly, yet steadily, over time - perhaps too slowly to match Adobe’s standards.
It has reached version 4, always belonging to the Adobe Labs; a promising HTML Widget was
implemented, but the exported Panel was still Flash based, its fate was sealed and Configurator has
then been abandoned. The main developer (who’s based in China I’d say, and then left Adobe)
announced on GitHub to be willing to port the project to HTML, but last time I checked, the
repository was still empty - I’m unable to find it now.
HTML Panels
Unless you’ve been living in a cave, you know what has happened to Flash24 . In four years or so a
new breed of Panels has emerged - now HTML is the reigning standard.
HTML Panels are supported from Photoshop CC (2013), which is the only bridge version that can
handle both Flash and HTML at the same time. We’re possibly allowed to think that they will last
longer, for it is a food that Photoshop itself eats. For instance, the “Library Panel”, the “Export As”
and “Recent Files” dialogs, the “Welcome” screen, they have been coded by Adobe as HTML Panels.
HTML Panel development is free, as opposed to Flash Panels. Extension Builder preview 325 is now
abandoned and won’t support the latest CC out of the box26 : you can build extensions using any
text editor and linking the open sourced libraries.
21
Ironically, this is actually what we’ve ended up doing in HTML Panels.
22
http://labs.adobe.com/downloads/configurator.html
23
http://www.cs-extensions.com/products/cpt/
24
http://www.commitstrip.com/en/2015/07/15/a-brief-history-of-flash/
25
http://labs.adobe.com/technologies/extensionbuilder3/
26
Latest version - which is still a Technology Preview - is dated Aug 1st, 2013. It can be tweaked to be used on Photoshop-latest, although I don’t
really recommend it.
1. Photoshop Extensibility 6
Flash Panels used to be AIR27 applications running within the Host App thanks to APE (Adobe Player
Embedded); not surprisingly, HTML Panels are web applications running within the Host App, such
as Photoshop. But what’s under the hood? How do we start building them?
• Video
• Audio
• Drag and Drop
• Canvas
• SVG
• Web Workers
• Web Storage
• Web SQL Database
27
https://en.wikipedia.org/wiki/Adobe_AIR
28
https://en.wikipedia.org/wiki/Chromium_Embedded_Framework
29
The version implemented in Photoshop CC 2018 is CEF 3.2987, Chromium 57.0.2987.74.
30
https://en.wikipedia.org/wiki/V8_(JavaScript_engine)
2. The HTML Panel Stack 9
• Application Cache
• Server sent events
• Form input types
• Form elements
• Form attributes
• File API
• Session and Persistent Cookies
A note about Cascading Style Sheets. Adobe doesn’t provide any official CSS to be used in third
party panels: you’re free to implement the ones you like better, or borrow ideas used in Photoshop’s
own HTML panels. I’ll cover styling in a dedicate section.
Javascript
The ubiquitous JS is the foundation of Panel’s operations. You can plug in your framework of choice
such as AngularJS, in order to implement the MVC (Model View Controller) pattern; or make Ajax
calls, store data, send Database queries, interact with the server side, whatever you might need. As
I’ve mentioned above, the JS pertaining to a Panel is interpreted by the Chromium’s V8 engine - that
implements ECMAScript 5th version.
Also, Photoshop features a built-in31 instance of Node.js32 , so you’re free to require() code in your
JS, use core packages e.g. fs and http, grab available ones from NPM, or write your own modules.
Extendscript
Finally, the code driving the Host App is Extendscript (aka JSX, like its default file extension). All
the Photoshop heavy lifting - duplicate a document, apply a filter, etc - belongs to the JSX layer,
which has its own distinct Virtual Machine (VM).
I’d like to stress the above sentence: JS and JSX are interpreted and executed by two separate engines.
Sadly enough, Extendscript is stuck to ECMAScript 3rd version33 - that is to say: Photoshop will not
understand what the following line means (and throw an exception):
Layers communication
So, if Javascript and Extendscript belong to different VMs, how is that the Panel magic can happen -
that is: what is that makes a Panel communicating with the Host Application (such as Photoshop)?
On one side, JS can use PlugPlug (a shared Adobe technology component) to send a message to the
JSX engine like “Dear Extendscript VM, can you evaluate this command for me?”, and the JSX layer
is kind enough to perform the task and return back the result to the JS for further processing.
On the other side, the JSX can emit Events - carrying a payload, so data can be transferred. Events
which the JS can listen to, and react accordingly; I’ll be covering in depth these mechanism, so just
don’t worry now.
To sum up, an HTML Panel is a modern web application based on HTML5, CSS3, JS (ES5 and
Node.js), which deals with the host application sending messages to, and listening for Events from,
the host app’s JSX Virtual Machine. Yet, from the sheer point of view of Photoshop operations,
nothing changes - there’s no new hook, everything’s based on good old scripting.
3. Setting up the environment
Code editors
A wise recommendation is: use what you’re already familiar and/or more productive with. You can
code HTML Panels with just a plain text editor, but let’s inspect some of the possibilities.
To date, it still is the closest thing to an Extension development IDE available (templates, code
completion, debugging, etc), but you have to like Eclipse. In order to be able to use it, follow these
steps.
• Install Extension Builder from the Eclipse menu Help > Install New Software… You need to
Add… a new Local… repository pointing to the downloaded Extension Builder, then confirm
few times to have it finally installed.
• Create a File > New > Other.. and pick Application Extension Project from the Adobe
Extension Builder 3 folder.
You can visit Eclipse Help > Adobe Extension Builder 3 Start Page to find the (quite good even if
slightly out-of-date) documentation about it.
Mind you, you need to manually modify some of the preferences in order to target newer versions
of your Host App (Mac users: point to the exec within the App’s package):
Also, you need to manually update JS libraries code with newer ones (CSInterface.js, Vulcan.js,
etc. - which I’ll cover later on); finally, the manifest.xml needs to be changed too (see Chapter 4).
In order to do so, you need to find the hidden one in the .staged-extension/CSXS folder. A piece
of cake, no? Do yourself a favor and don’t use it.
Brackets also provide some great Intellisense for your own JS files, which is definitely a plus.
Luckily, the so-called Debug Flag can switch off this behaviour and bypass the extension signature
check.
On a Mac, fire the Terminal and type:
defaults write com.adobe.CSXS.8 PlayerDebugMode 1
then add a new PlayerDebugMode key of type String with value “1”.
Mind you: in case you want to test your panel on different versions of Photoshop, you need to add
the debug flag to each and every one of the required CSXS files, which Photoshop matching versions
are as follows:
• com.adobe.CSXS.8 = CC 2018
• com.adobe.CSXS.7 = CC 2015.5 and CC 2017
• com.adobe.CSXS.6 = CC 2015
• com.adobe.CSXS.5 = CC 2014
• com.adobe.CSXS.4 = CC
Installation folders
Now that you can momentarily forget about extension signatures, it’s time to know where HTML
Panels belong in the User’s HD - their path. It’s a slightly more complicate matter than I would find
appropriate, so I’ll keep it as short as possible for you.
• CSInterface.js
• Vulcan.js
• AgoraLib.js
Keep them handy because you’ll need to link them in your extensions.
Storing projects
Over the years I’ve tested few different setups, and now I’ve settled to the following one.
As a single developer, I use Git44 as a Version Control System, pushing to BitBucket45 : which allows
unlimited and free private repositories (also their SourceTree46 Git client is my favorite).
42
You don’t need to deploy on both folders, either the User or the System
43
https://github.com/Adobe-CEP/CEP-Resources/tree/master/CEP_8.x
44
https://git-scm.com
45
http://bitbucket.org
46
https://www.sourcetreeapp.com
3. Setting up the environment 16
Each project has of course his own directory/repository, which belongs to a Dropbox local folder
as a safety net. Mind you: some Cloud aggregators47 , such as the otherwise great odrive48 , won’t
backup Git repos.
Then, I create a Symbolic Link49 from each of my Dropbox development folders, to the Installation
Folder. On Mac (open Terminal), it’s like:
This way I can keep coding on my backup-ed, Git managed, local Dropbox folder without the need
to move stuff around to deploy and test on Photoshop.
47
Aggregators are services which allow you to manage multiple Cloud accounts at once, such as Dropbox, Google Drive, Box, OneDrive, etc.
48
http://odrive.com
49
Which is different than creating an alias: symlinks work, aliases don’t.
50
https://www.cygwin.com
4. Building up “Hello World!”
Greeting the world is (by law) the first step in every language, and who am I to break traditions.
In fact we’ll be coding not one but three such panels, and each exercise is nothing but a pretext to
tell you about some very important extension feature. So get ready and don’t just skip to the next
chapter, I can read your mind.
Take 1: Manifest.xml
Create a Hello World folder in the appropriate /CEP/extensions path to contain the whole project,
then create a new index.html file with the following content:
1 <!doctype html>
2 <html>
3 <head>
4 <title>Hello World!</title>
5 </head>
6 <body>
7 <h1>Hello World!</h1>
8 </body>
No really, do it.
I’m afraid if you reboot Photoshop and look in the Window > Extensions menu, you won’t see it
there.
Photoshop needs quite a lot of extra information about your extension, such as its unique ID,
the panel size, the version of the Host App it supports, etc. All this (and much more) goes into a
manifest.xml file that mandatorily has:
1. To exist.
2. To belong to a CSXS folder in the project’s root. If it’s missing, or mistyped (which is not
unfrequent), the panel won’t load.
.
├── CSXS
│ └── manifest.xml
└── index.html
You can look at existing extensions’ manifest to check what the available tags are, but as follows is
a pretty standard one for our super minimal Hello World:
Example of a manifest.xml
34 <ScriptPath>./jsx/photoshop.jsx</ScriptPath>
35 </Resources>
36
37 <Lifecycle>
38 <AutoVisible>true</AutoVisible>
39 </Lifecycle>
40
41 <UI>
42
43 <Type>Panel</Type>
44 <Menu>Hello World!</Menu>
45
46 <Geometry>
47 <Size>
48 <Height>150</Height>
49 <Width>300</Width>
50 </Size>
51 <MinSize>
52 <Height>100</Height>
53 <Width>150</Width>
54 </MinSize>
55 <MaxSize>
56 <Height>200</Height>
57 <Width>350</Width>
58 </MaxSize>
59 </Geometry>
60
61 <Icons>
62 <Icon Type="Normal">./icons/iconNormal.png</Icon>
63 <Icon Type="RollOver">./icons/iconRollover.png</Icon>
64 <Icon Type="Disabled">./icons/iconDisabled.png</Icon>
65 <Icon Type="DarkNormal">./icons/iconDarkNormal.png</Icon>
66 <Icon Type="DarkRollOver">./icons/iconDarkRollover.png</Icon>
67 </Icons>
68
69 </UI>
70 </DispatchInfo>
71 </Extension>
72 </DispatchInfoList>
73 </ExtensionManifest>
Salient elements:
4. Building up “Hello World!” 20
• Version: this is tricky, because it refers to the version of the Common Extensibility Platform
(CEP - covered in following chapters), and must correspond to the value set in the Require-
dRuntime CSXS Version. For CC it’s "4.0", CC 2014 is "5.0", CC 2015 is "6.0", CC 2015.5
and CC 2017 is "7.0", CC 2018 is "8.0".
Photoshop CC 2018.0 aka 19.0.0 does not support Version="8.0". It should, if only because
this is the way things were set in the last four years, from 4.0 up to 7.0: RequiredRuntime
and ExtensionManifest do match the CEP version number. Whether it’s a bug that Adobe
is going to fix or not, is you use 8.0 your panel is not going to show up in the Extensions
list, so stick to 7.0.
• ExtensionBundleId: an extension can bundle multiple Panels, and this is the unique ID for
the Bundle - required even if yours is a one-panel-only Bundle.
• ExtensionBundleVersion: the current version of your Bundle.
• Extension Id: the unique ID for the extension (best practice is to add a .panel or .panel1 to
the ExtensionBundleId), and the Version there is finally your extension version.
• HostList: contains the Host tag, which has the
– Name: see the Debugging section for a list of 4chars codes of all the applications
supported. Mind you, for Photoshop you need to explicitely use both "PHSP" and
"PHXS"51 .
– Version: the supported version of the host app. Either an Array such as "[16.0,16.9]"
(from 16.0 to 16.9), where square brackets mean “included” and round parens mean
“excluded”; or a straight number like "15.0", which means from 15.0 onwards with no
upper limit. Please don’t do "[16.0,9999.9]" as I’ve seen.
• MainPath: the HTML entry point of the Panel.
• ScriptPath: the JSX entry point of the Panel (covered below).
• Geometry: sets the default (required), max and min (optional) size of the panel.
CEP7/8 updates
Starting with Photoshop CC2015.5 you’re allowed to move the <HostList> node inside <Extension>,
that is: specify a custom Host app on a per extension basis, like:
51
They refer to Photoshop and Photoshop Extended, a relic from the past when they were marketed as different products. See here the reason
why you need them both in the manifest.xml.
4. Building up “Hello World!” 21
This is because your Extension can bundle multiple Panels (you’ll see this later on): this way you
can customize a Panel for, say, ID, one for PS, etc. To let you taste the salty sea of HTML Panels just
grab the manifest.xml I’ve provided, save and reboot Photoshop. Now find the “Hello World” panel
in the Window > Extensions menu.
4. Building up “Hello World!” 22
Take 2: ExtendScript
An important and still missing piece of the puzzle is the interaction with the Host App - Hello
World must somehow get in touch with Photoshop. As you remember from the manifest.xml, the
JSX entry point (referred to the extension root) is set there as shown in this excerpt:
<Resources>
<MainPath>./index.html</MainPath>
<ScriptPath>./jsx/photoshop.jsx</ScriptPath>
<CEFCommandLine/>
</Resources>
The above means: as soon as the Panel needs it55 , the content of the ./jsx/main.jsx file is going to
be read and evaluated in the JSX engine. If it contains statements, they’re going to be executed; if it
contains function declarations, they will stick into the JSX Virtual Machine, ready to be called later
if/when needed, you’ll see in a minute how.
Let’s group files more systematically - adding to the panel a js, jsx and css folder, the tree becomes:
.
├── CSXS
│ └── manifest.xml
├── css
│ └── styles.css
├── index.html
├── js
│ ├── libs
│ │ └── CSInterface.js
│ └── main.js
└── jsx
└── photoshop.jsx
52
https://github.com/Adobe-CEP/CEP-Resources/blob/master/CEP_7.x/ExtensionManifest_v_7_0.xsd
53
Or the version of the CEP you’re targeting: there are .xsd files for CEP7, CEP6 and CEP5.
54
http://www.corefiling.com/opensource/schemaValidate.html
55
The JSX isn’t really evalued at Panel loading, but only when the first .evalScript() call is fired.
4. Building up “Hello World!” 23
index.html
1 <!doctype html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <link rel="stylesheet" href="css/styles.css"/>
6 <title>Hello World!</title>
7 </head>
8 <body>
9 <div id="content">
10 <button id="btn_test">Say Hello</button>
11 </div>
12 <script src="js/libs/CSInterface.js"></script>
13 <script src="js/main.js"></script>
14 </body>
15 </html>
photoshop.jsx
1 function sayHello(){
2 alert("Hello from ExtendScript");
3 }
main.js
1 (function () {
2 'use strict';
3
4 var csInterface = new CSInterface();
5
6 document.getElementById('btn_test').addEventListener('click', function () {
7 csInterface.evalScript('sayHello()');
8 });
9
10 }());
As a result, when you press the Panel’s Say Hello button, its click event listener fires the callback,
which in turn says: “Hey Photoshop, does 'sayHello()' mean something for you?”. Photoshop
in turn looks whether the manifest.xml knows about any JSX file to parse (“here it is Sir, it’s
photoshop.jsx”) and hands it to its JSX engine. Finally sayHello() is run, and the alert pops up.
56
Does that sound like Sanskrit to you? Read this clear article to understand more about it.
4. Building up “Hello World!” 25
We’ll make extensive use of both CSInterface methods and ExtendScript code in the next chapters,
so if this Hello World take 2 exercise has left you with unanswered questions (is there a way to
transfer a payload between JS and JSX? Is the other way around possible?), be aware that we’ll
touch those topics again and again, and you won’t miss code examples.
Take 3: Debugging
The Hello World third iteration is about debugging, an activity we all love. How do you do it?
Remotely is the answer - i.e. the panel will act as a server and you’ll be connecting to it.
In the root folder of your extension, create a blank file called .debug, which makes it hidden58 .
You can use your Text Editor for this task, or the Terminal (find it in the Applications/Utilities
folder). First, cd in the appropriate location (you can see in the above screenshot that Folders with
spaces in the name are escaped with a \ which is the default when you drag and drop a Folder from
Finder in the Terminal window), then touch the .debug file to create it.
This file needs to be formatted as an XML and should contain information about the ID of your
extension (i.e. it must match the ID specified in the manifest.xml), and the host/port (in the range
1024 – 65534) you want to connect through.
57
ExtendScript Toolkit.
58
On OSX, a filename that starts with a dot is hidden.
4. Building up “Hello World!” 26
Now, while your Photoshop extension is open, point the Chrome browser to http://localhost:8088
(of course use the port you’ve set in the .debug file). You should see something like this:
4. Building up “Hello World!” 27
Localhost:8080
When you click the Hello World link (which is the title tag set in the index.html) the Chrome
Developer Tools will open and you’ll be able to inspect/debug your extension, set breakpoints, log
messages, like any other web application. Introductory tutorials can be found on DevTools page59 ,
Code School60 , TutsPlus61 .
Breakpoints can be set in the Sources tab, refreshing then the view with Command or Control + R
in order to restart the panel. Mind you, the Chrome Developer Tools cannot reach the JSX level –
it’s just for the HTML panel and its JS; if you’re wondering, a debugger call in the JSX doesn’t fire
up ESTK. If you want to log from JSX in the Chrome Console, you need to use Custom JSX Events
- see Chapter 7.
59
https://developer.chrome.com/devtools
60
https://www.codeschool.com/courses/discover-devtools
61
http://code.tutsplus.com/courses/chrome-developer-tools
4. Building up “Hello World!” 28
Console issues
If you can’t scroll the Chrome Developer Tools Console (that is, when it’s full you can’t see any
more logged lines) the workaround is found here64 – basically you need to inject this CSS to make
it work again:
In case, instead, the return key is not working (that is to say: the cursor goes to a new line, but the
expression in the Console is not evaluated), please refer to this topic65 . A working solution is to use
not Google Chrome but Chromium itself. You can download Chromium here66 – theoretically you
should pick the version that matches the current CEF.
Using cefclient
In the Adobe-CEP GitHub repository you can download cefclient67 , either Mac or Windows. It’s,
well, a CEF client that you can use instead of Google Chrome: be aware that (at least on Mac),
you need to pass a custom flag to the executable or it won’t connect with Photoshop. So the actual
Terminal command is:
JS interface
As the name suggests, CSInterface.js is a Javascript interface to CEP features implemented in the
host application with native code. In other words, Photoshop exposes some CEP hooks that you can
reach using JS code from within an HTML Panel.
Mind you: the CSInterface.js file must to be linked in the index.html (or whatever it is called
the HTML entry point of your extension).
There is no official documentation for the CSInterface.js library, yet the source code is commented
using the JSDoc68 standard, as the following snippet shows:
Excerpt of CSInterface.js
1 /**
2 * Resize extension's content to the specified dimensions.
3 * 1. Works with modal and modeless extensions in all Adobe products.
4 * 2. Extension's manifest min/max size constraints apply and take precedence.
5 * 3. For panel extensions
6 * 3.1 This works in all Adobe products except:
7 * * Premiere Pro
8 * * Prelude
9 * * After Effects
10 * 3.2 When the panel is in certain states (especially when being docked),
11 * it will not change to the desired dimensions even when the
12 * specified size satisfies min/max constraints.
13 *
14 * Since 6.0.0
15 *
16 * @param width The new width
17 * @param height The new height
18 */
68
http://usejsdoc.org
5. CSInterface 30
You can generate your own HTML (or Markdown) documentation installing JsDoc via npm:
jsdoc /Users/davidebarranca/Adobe/CEP_6.x/CSInterface.js
An out folder is generated in your present working directory, containing the HTML doc.
CSInterface Documentation
Another way to explore the CSInterface object is to play with it in the Chrome Developer Tools
console. Open the Hello World panel in Photoshop then connect to localhost:8088 in Chrome and
have fun with code completion:
5. CSInterface 31
You see that - besides Event related stuff - available functions are mostly getters and setters:
csInterface.openURLInDefaultBrowser("http://www.google.com");
csInterface.closeExtension();
csInterface.requestOpenExtension("com.example.jsxDemo");
csInterface.initResourceBundle()
A quick look at the JSDoc reveals that it’s about Localization. You’ll encounter most of them
throughout the book, so feel free to be slightly disoriented now.
CEP Versions
It is important to understand that different Photoshop versions implement different CEP features,
which in turn correspond to different CSInterface.js files to link in your panels. As follows the
CEP version history against Photoshop:
In theory a CEP major update is relased at each major CC release, and a newer CSInterface.js
library is provided on GitHub for you to use in your code. But it’s hard to predict what the future
will bring, given that CC2015.569 , despite the naming convention, is a major Photoshop version
(18), and CC 2017 hasn’t brought CEP8 as we would have expected (as a consequence, there’s no
new CSInterface.js as well). CEP8 came with CC 2018, but Version="8.0" doesn’t work yet in
manifest.xml and as a matter of fact CSInterface.js hasn’t changed from CC 2015.5. Adobeland.
How do you deal with retro-compatibility? First, you must remember that you need to declare the
CEP version in the manifest.xml in two places:
69
Nobody knows the reason why CC 2015.5 is in fact a major version. My theory is that must be an Indian curse on the number 5. Photoshop
went from version 5 to 5.5, from CS5 to CS5.5 (actually 5.1 but within the CS5.5) and now from CC 2015 to C C2015.5.
5. CSInterface 33
Excerpt of manifest.xml
In the above example, the Version="7.0" found in line 3 and 20 refers to the CEP version, and in
fact we’re targeting Photoshop CC 2017 (see lines 13 and 14). In case you want to support Photoshop
CC as well, use Version="4.0" and remember to change the Host Version to Version="14.0" - that,
as you remember, means: from 14.0 onwards with no upper limit.
Mind you, the CSInterface.js library is retro-compatible, so you can keep linking the greatest and
latest found on GitHub. Of course linking a newer CSInterface.js doesn’t automagically mean
the possibility to use new features: for instance, Panel resizing at runtime is available since CEP 6
(Photoshop CC2015) and even if you link CSInterface.js version 6, it won’t work in Photoshop CC
2014.
To sum up: as a rule of thumb, specify the lowest CEP and Host App version that yor panel supports
in the manifest.xml, and link the newest CSInterface.js library available. Then, you can do your
check at runtime against the CEP version, such as:
5. CSInterface 34
In case you’re dubious, the above goes in the main.js (and not in the JSX) since all CEP stuff belongs
to the JS side of the world.
evalScript()
We’ve already used csInterface.evalScript()70 in the Hello World exercise, yet it’s such a crucial
method that it deserves its own section.
Callback
If you look at the CSInterface.js source code, you see that it accepts two parameters, the second
one being optional:
1 /**
2 * Evaluates a JavaScript script, which can use the JavaScript DOM
3 * of the host application.
4 *
5 * @param script The JavaScript script.
6 * @param callback Optional. A callback function that receives the result of ex\
7 ecution.
8 * If execution fails, the callback function receives the error message\
9 \c EvalScript_ErrMessage.
10 */
11 CSInterface.prototype.evalScript = function(script, callback)
12 {
13 if(callback == null || callback == undefined)
14 {
15 callback = function(result){};
70
Mind you CSInterface is the class, csInterface is the instance of that class: var csInterface = new CSInterface(); - the name is totally
arbitrary, you can call it csi or shantanu if you like it better.
5. CSInterface 35
16 }
17 window.__adobe_cep__.evalScript(script, callback);
18 };
Let’s see how this callback parameter works. Say that your panel needs to know how many
documents are open in Photoshop. In ExtendScript you would:
1 app.documents.length
The callback accepts as a parameter the returned value of the ExtendScript evaluation, so it can log
it. To test this you can use the Chrome Developer Tools console (open Photoshop with the Hello
World panel and visit localhost:8088).
evalScript callback
In case you didn’t know, it’s possible to carriage return in the Console with Alt or Option + Enter.
Which logs:
Why is that?! We’ve just defined an openDocuments variable, filled with the retVal number in the
callback, logged in the next line. The answer is: because evalScript is asynchronous.
Quoting StackOverflow71 :
“When you execute something synchronously, you wait for it to finish before moving
on to another task. When you execute something asynchronously, you can move on to
another task before it finishes”.
Visually, three tasks might run this way synchronously (top) and asynchronously (bottom):
Of course the length of each one is proportional to the computational intensity of the corresponding
task (A is something that takes a lot of time, say an AJAX request, B is quicker, etc.) so it’s impossible
to know a priori which one is going to end first.
What happens in the evalScript example above is that the openDocuments variable is declared
and set as undefined. Then csInterface hands the ExtendScript engine the app.documents.length
71
http://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean
5. CSInterface 37
string to evaluate; but it doesn’t wait for the result, and skips right away to the console.log of the
variable, that is (still) undefined.
So how do you work around this? One way is to keep everything inside the callback, like in the
original example; yet this can easily lead to the so-called “callback hell” (nested callbacks headache):
A naif approach is to set a timeout - i.e. wait some predefined amount of time:
Yet there’s a better option: you might want to use Promises72 , which support is provided for instance
by this library called ES6-Promise73 . The code becomes:
1 function evalScript(command) {
2 return new Promise(function(resolve, reject) {
3 csInterface.evalScript(command, resolve);
4 });
5 }
6
7 var csInterface = new CSInterface();
8
9 evalScript('app.documents.length')
10 .then(function(results) {
11 console.log("Number of open documents: " + openDocuments);
12 });
You define an evalScript() method that returns a Promise - way cleaner, in my opinion. In case
you need to chain together evalScript calls, the correct way to structure your code74 passing down
the returned value is as follows:
72
http://www.html5rocks.com/en/tutorials/es6/promises/
73
https://github.com/jakearchibald/es6-promise
74
Thanks to the developer James Stewart for this one.
5. CSInterface 38
1 evalScript('firstJSXFunction()')
2 .then(function(results) {
3 return evalScript('secondJSXFunction()')
4 })
5 .then(function(results) {
6 return evalScript('thirdSXFunction()')
7 });
A list of the available System Paths is as follows, with the result of the getter in my own computer
on both platforms.
SystemPath.USER_DATA = "userData"
SystemPath.COMMON_FILES = "commonFiles"
SystemPath.MY_DOCUMENTS = "myDocuments"
SystemPath.EXTENSION = "extension"
SystemPath.EXTENSION = "extension"
[Win]:
"C:/Users/davidebarranca/AppData/Roaming/Adobe/CEP/extensions/com.example.helloworld"
SystemPath.HOST_APPLICATION = "hostApplication"
System Paths are particularly useful because, in the context of an HTML Panel (in Photoshop), a
JSX file doesn’t know anymore where it belongs - let me explain. We’re used, in traditional
ExtendScript, to take advantage of the $ helper object to get the location of a JSX file (its path):
1 File($.fileName).path
2 // ~/Desktop
If you attempt to do the same in the JSX of a Photoshop panel you’ll get some really weird result
- for instance alert(File($.fileName)) got me /94 on Mac, and /C/Program Files/Adobe/Adobe
Photoshop CC 2017/25 on Windows, and the path property is equals to "". As a direct consequence,
you can’t expect preprocessor directives such as #include to work in the Panels’ JSX:
1 #include "jsxinc/lib.jsx"
2 // will fail in Photoshop, will work in InDesign
The reason why it fails is: how can the JSX find the jsxinc folder (relative to its own location) if it
can’t find its own path?
Now, according to CEP7 official documentation, the $.fileName fails only if it’s called from the
first loaded JSX (the one in the manifest.xml); you should use CSInterface.evalScript() to
$.evalFile() a second JSX, and finally in that second JSX $.fileName works as expected and you
can do your regular stuff. From my humble point of view the above is laughable, and there is a
quicker way to work around the apparent impossibility to load multiple JSX files.
You need to retrieve in the JS the extension’s absolute path using our friend the getSystemPath()
method, then pass it down to the JSX; that in turn will use it to evaluate a secondary JSX file using
the $.evalFile() function.
5. CSInterface 40
In the main.js
In the photoshop.jsx
1 function evalFile(path) {
2 try {
3 $.evalFile(path);
4 } catch (e) {
5 alert("Exception:" + e);
6 }
7 }
evalFile syntax
Panels are sort of a heap of tangled matters - it’s very difficult to cover one topic
not employing another one that you still have to mention. Namely, I’ve used the
nasty .evalScript('evalFile("' mixed quotes syntax to pass down to the JSX the
extensionRoot variable. This construct is explained in thorough detail in this section of
the next chapter, so have a look at it if you just can’t wait.
Also, you can use a helper function to load any JSX file that belongs to a folder - this way you can
put them all in, say, jsx/includes/:
5. CSInterface 41
1 function evalFile(path) {
2 // same as before...
3 }
4
5 function evalFiles(jsxFolderPath) {
6 var folder = new Folder(jsxFolderPath);
7 if (folder.exists) {
8 var jsxFiles = folder.getFiles("*.jsx");
9 for (var i = 0; i < jsxFiles.length; i++) {
10 var jsxFile = jsxFiles[i];
11 try {
12 $.evalFile(jsxFile);
13 } catch (e) {
14 alert(e.message + "\n" + jsxFile);
15 }
16 }
17 }
18 }
In the main.js
… and the reason is that secondaryFun is undefined - don’t ask me why. I’ve logged a bug75
against this behaviour, that by the time you’re reading this might or might not be closed76 .
The only way to build a function in a secondary JSX that sticks in the ExtendScript engine
is omitting the var:
secondaryFun = function(param) { ... }
Since you already are in the global scope there should be no difference - both var
secondaryFun and secondaryFun will become global variables. Polluting the global scope
is another cardinal sin, so you might want to use some JS pattern to keep it as clean as
possible (easiest way is to group everything in an object literal).
75
https://github.com/Adobe-CEP/CEP-Resources/issues/27
76
October 2017, nothing has changed yet.
Enjoyed the content so far?
I’m afraid here ends the free content that I’ve been happy to share with you!
Much more advanced topics, the fully commented code of 28 custom made panels covered in the
book, and three hours of HD video tutorials await you for purchase on h#p://htmlpanelsbook.com
You can subscribe to the newsle#er to get a preview of the video content as well (half of an hour, for
free) - no spam involved.
Feel free to get in touch if you want - in the Course homepage you can find email, socials, etc.
!ank you and kind regards from Italy!
Davide Barranca
268
Copyright
© 2016 Davide Barranca
Adobe® Photoshop® and Adobe® Creative Cloud® are registered trademarks of Adobe Systems
Incorporated in the United States and/or other countries. All other trademarks are the property of
their respective owners.
THIS PRODUCT IS NOT ENDORSED OR SPONSORED BY ADOBE SYSTEMS INCORPORATED,
PUBLISHER OF ADOBE PHOTOSHOP AND THE ADOBE CREATIVE CLOUD.
This book was made using Leanpub. Leanpub empowers authors and publishers with the Lean
Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight
tools and many iterations to get reader feedback, pivot until you have the right book and build
traction once you do.
I’d like to thank their team for the support, professionality and care - I couldn’t recommend them
more if you’re interested in producing your own book.
269